Author: mladen.turk(a)jboss.com
Date: 2008-05-28 11:50:29 -0400 (Wed, 28 May 2008)
New Revision: 1632
Added:
sandbox/aloha/httpd/
sandbox/aloha/httpd/modules/
sandbox/aloha/httpd/modules/manager/
sandbox/aloha/httpd/modules/manager/Makefile.in
sandbox/aloha/httpd/modules/manager/NMAKEmakefile
sandbox/aloha/httpd/modules/manager/NMAKEmanager
sandbox/aloha/httpd/modules/manager/config.m4
sandbox/aloha/httpd/modules/manager/mm_api.h
sandbox/aloha/httpd/modules/manager/mm_app.c
sandbox/aloha/httpd/modules/manager/mm_asmm.c
sandbox/aloha/httpd/modules/manager/mm_asmm.h
sandbox/aloha/httpd/modules/manager/mm_balancer.c
sandbox/aloha/httpd/modules/manager/mm_cookie.c
sandbox/aloha/httpd/modules/manager/mm_cookie.h
sandbox/aloha/httpd/modules/manager/mm_host.c
sandbox/aloha/httpd/modules/manager/mm_manager.c
sandbox/aloha/httpd/modules/manager/mm_member.c
sandbox/aloha/httpd/modules/manager/mm_module.c
sandbox/aloha/httpd/modules/manager/mm_node.c
sandbox/aloha/httpd/modules/manager/mm_pool.c
sandbox/aloha/httpd/modules/manager/mm_server.c
sandbox/aloha/httpd/modules/manager/mm_util.c
sandbox/aloha/httpd/modules/manager/modules.mk
Log:
Add httpd manager module
Added: sandbox/aloha/httpd/modules/manager/Makefile.in
===================================================================
--- sandbox/aloha/httpd/modules/manager/Makefile.in (rev 0)
+++ sandbox/aloha/httpd/modules/manager/Makefile.in 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,3 @@
+# a modules Makefile has no explicit targets -- they will be defined by
+# whatever modules are enabled. just grab special.mk to deal with this.
+include $(top_srcdir)/build/special.mk
Property changes on: sandbox/aloha/httpd/modules/manager/Makefile.in
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/NMAKEmakefile
===================================================================
--- sandbox/aloha/httpd/modules/manager/NMAKEmakefile (rev 0)
+++ sandbox/aloha/httpd/modules/manager/NMAKEmakefile 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,43 @@
+# Copyright 2001-2007 The Apache Software Foundation or its licensors, as
+# applicable.
+#
+# 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,
+# 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.
+#
+# ====================================================================
+#
+# NMAKEmakefile Master HTTPD Manager module makefile.
+#
+# Originally contributed by Mladen Turk <mturk redhat.com>
+#
+# ====================================================================
+#
+
+TARGET=DLL
+!IF !DEFINED(SRCDIR) || "$(SRCDIR)" == ""
+SRCDIR = .
+!ENDIF
+
+!include <..\..\NMAKEcommon.inc>
+!include <..\..\NMAKEhttpd.inc>
+
+MODULES = \
+ $(SRCDIR)\NMAKEmanager
+
+$(MODULES):
+ @$(MAKE) -nologo -f $@ PREFIX=$(PREFIX) install
+
+$(WORKDIR):
+ @$(MAKEWORKDIR)
+
+install: $(WORKDIR) $(MODULES)
+ @xcopy "$(WORKDIR)\*.so" "$(BUILDMOD)" /Y /Q 2>NUL
Property changes on: sandbox/aloha/httpd/modules/manager/NMAKEmakefile
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/NMAKEmanager
===================================================================
--- sandbox/aloha/httpd/modules/manager/NMAKEmanager (rev 0)
+++ sandbox/aloha/httpd/modules/manager/NMAKEmanager 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,81 @@
+# Copyright 2001-2007 The Apache Software Foundation or its licensors, as
+# applicable.
+#
+# 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,
+# 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.
+#
+# ====================================================================
+#
+# NMAKEmakefile cluster module makefile.
+#
+# Originally contributed by Mladen Turk <mturk redhat.com>
+#
+# ====================================================================
+#
+
+TARGET=DLL
+PROJECT = mod_manager
+
+!IF !DEFINED(SRCDIR) || "$(SRCDIR)" == ""
+SRCDIR = .
+!ENDIF
+
+!include <..\..\NMAKEcommon.inc>
+!include <..\..\NMAKEhttpd.inc>
+
+LDIRS = /libpath:"$(BUILDLIB)"
+LFLAGS = $(LFLAGS) user32.lib psapi.lib gdi32.lib shlwapi.lib wldap32.lib ole32.lib
$(LIBAPR) $(LIBAPU) $(LIBHTTPD)
+CFLAGS = $(CFLAGS) -DMANAGER_DECLARE_EXPORT
+
+INCLUDES = -I$(SRCDIR) -I$(BUILDINC) -I../generators -I../ssl
+PDBFLAGS = -Fo$(WORKDIR)\ -Fd$(WORKDIR)\$(PROJECT)-src
+
+BUILDBIN = $(WORKDIR)\$(PROJECT).so
+BUILDPDB = $(WORKDIR)\$(PROJECT).pdb
+BUILDRES = $(WORKDIR)\$(PROJECT).res
+BUILDMFT = $(BUILDBIN).manifest
+
+RCFLAGS = $(RCFLAGS) /d BIN_NAME="$(PROJECT).so" /d
LONG_NAME="manager_module for Apache"
+
+OBJDEPS = \
+ $(SRCDIR)\mm_asmm.h \
+ $(SRCDIR)\mm_cookie.h \
+ $(SRCDIR)\mm_api.h \
+ $(SRCDIR)\NMAKEmakefile
+
+OBJECTS = \
+ $(WORKDIR)\mm_util.obj \
+ $(WORKDIR)\mm_app.obj \
+ $(WORKDIR)\mm_asmm.obj \
+ $(WORKDIR)\mm_cookie.obj \
+ $(WORKDIR)\mm_balancer.obj \
+ $(WORKDIR)\mm_host.obj \
+ $(WORKDIR)\mm_manager.obj \
+ $(WORKDIR)\mm_member.obj \
+ $(WORKDIR)\mm_pool.obj \
+ $(WORKDIR)\mm_server.obj \
+ $(WORKDIR)\mm_module.obj
+
+{$(SRCDIR)}.c{$(WORKDIR)}.obj:
+ $(CC) $(CFLAGS) $(INCLUDES) $(PDBFLAGS) $<
+
+$(OBJECTS): $(OBJDEPS)
+
+$(BUILDRES): ..\..\build\win32\httpd.rc
+ $(RC) $(RCFLAGS) /i "$(BUILDINC)" /fo $(BUILDRES) ..\..\build\win32\httpd.rc
+
+$(BUILDBIN): $(OBJECTS) $(BUILDRES)
+ $(LINK) $(LFLAGS) $(OBJECTS) $(BUILDRES) $(LIBS) $(LDIRS) /pdb:$(BUILDPDB)
/out:$(BUILDBIN)
+ IF EXIST $(BUILDMFT) \
+ mt -nologo -manifest $(BUILDMFT) -outputresource:$(BUILDBIN);2
+
+install: $(BUILDBIN)
Added: sandbox/aloha/httpd/modules/manager/config.m4
===================================================================
--- sandbox/aloha/httpd/modules/manager/config.m4 (rev 0)
+++ sandbox/aloha/httpd/modules/manager/config.m4 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,19 @@
+dnl modules enabled in this directory by default
+
+APACHE_MODPATH_INIT(manager)
+
+if test "$enable_manager" = "shared"; then
+ manager_mods_enable=shared
+elif test "$enable_manager" = "yes"; then
+ manager_mods_enable=yes
+else
+ manager_mods_enable=no
+fi
+
+manager_objs="mm_app.lo mm_asmm.lo mm_balancer.lo mm_cookie.lo mm_host.lo
mm_manager.lo mm_member.lo mm_module.lo mm_pool.lo mm_server.lo mm_util.lo"
+APACHE_MODULE(manager, Apache manager module, $manager_objs, , $manager_mods_enable)
+
+
+APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current/../generators])
+
+APACHE_MODPATH_FINISH
Property changes on: sandbox/aloha/httpd/modules/manager/config.m4
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_api.h
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_api.h (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_api.h 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,873 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+#ifndef MM_API_H
+#define MM_API_H
+
+/**
+ * @file mm_api.h
+ * @brief Manager Extension Module for Apache
+ *
+ * @defgroup MOD_MANAGER mod_manager
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#define CORE_PRIVATE
+
+#include "apr_hooks.h"
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_buckets.h"
+#include "apr_md5.h"
+#include "apr_network_io.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+#include "apr_date.h"
+#include "apr_strmatch.h"
+#include "apr_fnmatch.h"
+#include "apr_reslist.h"
+#include "apr_optional.h"
+#include "apr_uuid.h"
+#include "apr_version.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "ap_config.h"
+#include "ap_listen.h"
+#include "http_core.h"
+#include "http_protocol.h"
+#include "http_request.h"
+#include "http_vhost.h"
+#include "http_main.h"
+#include "http_log.h"
+#include "http_connection.h"
+#include "util_filter.h"
+#include "util_ebcdic.h"
+#include "util_time.h"
+#include "ap_provider.h"
+#include "ap_mpm.h"
+#include "mpm.h"
+#include "mpm_common.h"
+
+#include "mm_asmm.h"
+
+#if APR_HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if APR_HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if !APR_HAS_THREADS
+#error This module does not compile unless you have a thread capable APR!
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MM_MMN 20080805
+
+#define MM_MCMP_MAJOR 1
+#define MM_MCMP_MINOR 0
+
+#define MM_MCMP_VERSION (MM_MCMP_MAJOR * 10 + MM_MCMP_MINOR)
+
+#define MM_MCMP_VERSION_STRING \
+ APR_STRINGIFY(MM_MCMP_MAJOR) "." \
+ APR_STRINGIFY(MM_MCMP_MINOR)
+
+
+#define MM_DEFAULT_NAME "_default_"
+#define MM_DEFAULT_DBROOT "logs"
+#define MM_LOCK_NAME "/_mm_lock"
+#define MM_DEFAULT_HANDLE "/server-manager"
+#define MM_HANDLER_NAME "Manager-Handler"
+#define MM_CMDHEADER_NAME "X-Server-Command"
+#define MM_RESHEADER_NAME "X-Server-Resource"
+#define MM_PINGHEADER_NAME "X-Server-Ping"
+#define MM_DEF_SESSION_C "JSESSIONID"
+#define MM_DEF_SESSION_P ";jsessionid"
+
+#define MM_DEFAULT_PROTOCOL mm_protocol_ajp
+#define MM_DEFAULT_AJP_PORT 8009
+#define MM_DEFAULT_HTTP_PORT 8080
+#define MM_DEFAULT_HTTPS_PORT 8443
+#define MM_DEFAULT_ADDRESS "localhost"
+
+
+/**
+ * MCMP Protocol commands
+ */
+#define MM_MCMP_INFO "Info"
+#define MM_MCMP_ENABLE "Enable"
+#define MM_MCMP_DISABLE "Disable"
+#define MM_MCMP_STOP "Stop"
+#define MM_MCMP_DELETE "Delete"
+#define MM_MCMP_CONFIG "Config"
+#define MM_MCMP_EXEC "Exec"
+#define MM_MCMP_RESET "Reset"
+
+/**
+ * Manager Resource types
+ */
+#define MM_RES_MANAGER "Manager"
+#define MM_RES_SERVER "Server"
+#define MM_RES_APP_POOL "ApplicationPool"
+#define MM_RES_BALANCER "Balancer"
+#define MM_RES_HOST "Host"
+#define MM_RES_MEMBER "Member"
+#define MM_RES_APPLICATION "Application"
+
+#define MM_BSIZE 4096
+#define MM_SSIZE 1024
+#define MM_DEFAULT_ADVPORT 23364
+#define MM_TM_RESOLUTION APR_TIME_C(100000)
+#define MM_DEFAULT_ADV_FREQ apr_time_from_sec(10)
+#define MM_TM_MAINTAIN_STEP 10
+
+/**
+ * Advertise protocol types
+ */
+#define MM_ADVERTISE_SERVER 0
+#define MM_ADVERTISE_STATUS 1
+
+/**
+ * Posix error codes
+ */
+#define MME_EPERM 1
+#define MME_EACCES 1
+#define MME_EINTR 4
+#define MME_EBUSY 16
+#define MME_ENODEV 19
+#define MME_EINVAL 22
+#define MME_ENOTCONN 57
+
+/**
+ * Table indexes
+ */
+#define MMDB_SERVER 0
+#define MMDB_MANAGER 1
+#define MMDB_HOST 2
+#define MMDB_HOST_LIST 3
+#define MMDB_APP_POOL 4
+#define MMDB_BALANCER 5
+#define MMDB_MEMBER 6
+#define MMDB_APPLICATION 7
+#define MMDB_MEMBERAPP 8
+
+/**
+ * Database record string sizes
+ */
+#define MMDB_TSSIZE 16
+#define MMDB_SSSIZE 32
+#define MMDB_MSSIZE 64
+#define MMDB_HSSIZE 256
+
+/**
+ * Boolean macros
+ */
+#define MM_STR_ON "On"
+#define MM_STR_OFF "Off"
+#define MM_STR_TRUE "True"
+#define MM_STR_FALSE "False"
+#define MM_STR_YES "Yes"
+#define MM_STR_NO "No"
+#define MM_STR_ONOFF(x) ((x) ? MM_STR_ON : MM_STR_OFF)
+#define MM_STR_BOOL(x) ((x) ? MM_STR_TRUE : MM_STR_FALSE)
+#define MM_STR_YN(x) ((x) ? MM_STR_YES : MM_STR_NO)
+#define MM_VAL_BOOL(x) ((!strcasecmp((x), "True") || !strcasecmp((x),
"On") || \
+ *(x) == '1' || *(x) == 'Y' || *(x) ==
'y') ? 1 : 0)
+
+#define MM_VAL_ONOFF MM_VAL_BOOL
+#define MM_VAL_YN(x) (*(x) == 'Y' || *(x) == 'y' ? 1 : 0)
+
+#define MM_FORCE_DEFAULT_NAME_REQ 0
+#define MM_FFNMATCH APR_FNM_CASE_BLIND
+/**
+ * Multicast Time to Live (ttl) for a advertise transmission.
+ */
+#define MM_ADVERTISE_HOPS 10
+
+/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
+ * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
+ */
+#if !defined(WIN32)
+#define MANAGER_DECLARE(type) type
+#define MANAGER_DECLARE_NONSTD(type) type
+#define MANAGER_DECLARE_DATA
+#elif defined(MANAGER_DECLARE_STATIC)
+#define MANAGER_DECLARE(type) type __stdcall
+#define MANAGER_DECLARE_NONSTD(type) type
+#define MANAGER_DECLARE_DATA
+#elif defined(MANAGER_DECLARE_EXPORT)
+#define MANAGER_DECLARE(type) __declspec(dllexport) type __stdcall
+#define MANAGER_DECLARE_NONSTD(type) __declspec(dllexport) type
+#define MANAGER_DECLARE_DATA __declspec(dllexport)
+#else
+#define MANAGER_DECLARE(type) __declspec(dllimport) type __stdcall
+#define MANAGER_DECLARE_NONSTD(type) __declspec(dllimport) type
+#define MANAGER_DECLARE_DATA __declspec(dllimport)
+#endif
+
+void dbprintf(const char *format, ...);
+
+#define MM_SSAFE_COPY(t, f) \
+ if ((f)) \
+ apr_cpystrn((t), (f), sizeof((t)))
+
+#define MM_NSAFE_COPY(t, f, s) \
+ if ((f)) \
+ apr_cpystrn((t), (f), (s))
+
+#define MM_MAYBEQ_RPUTS(r, p, s) \
+ if ((p) && (strchr((s), ' ') || strchr((s), ';') || \
+ strchr((s), ',') || strchr((s), '\t'))) \
+ ap_rvputs((r), "\"", (s), "\"", NULL); \
+ else ap_rvputs((r), (s), NULL)
+
+
+/**
+ * Mod status type enumeration.
+ */
+typedef enum {
+ mm_status_off,
+ mm_status_on,
+ mm_status_full
+} mm_status_e;
+
+/**
+ * Protocol type enumeration.
+ */
+typedef enum {
+ mm_protocol_unknown,
+ mm_protocol_ajp,
+ mm_protocol_http,
+ mm_protocol_https
+} mm_protocol_e;
+
+/**
+ * Advertise mode enumeration.
+ */
+typedef enum {
+ mm_advertise_off,
+ mm_advertise_status,
+ mm_advertise_on
+} mm_advertise_e;
+
+/**
+ * Maintain mode enumeration.
+ */
+typedef enum {
+ mm_maintain_step, /** Step interval */
+ mm_maintain_full, /** Full maintenance */
+ mm_maintain_force /** Forced maintenance */
+} mm_maintain_e;
+
+/**
+ * Response type enumeration.
+ */
+typedef enum {
+ mm_response_ok,
+ mm_response_error, /** ?Error: */
+ mm_response_utype, /** ?Unknown-Type: */
+ mm_response_uparam, /** ?Unknown-Param: */
+ mm_response_version /** ?MCMP-Version */
+} mm_respose_type_e;
+
+/**
+ * MCMP Protocol command enumeration.
+ */
+typedef enum {
+ mm_mcmp_unknown,
+ mm_mcmp_info,
+ mm_mcmp_enable,
+ mm_mcmp_disable,
+ mm_mcmp_stop,
+ mm_mcmp_delete,
+ mm_mcmp_config,
+ mm_mcmp_exec,
+ mm_mcmp_reset
+} mm_mcmp_command_e;
+
+/**
+ * Manager Resource operation enumeration.
+ */
+typedef enum {
+ mm_resource_init,
+ mm_resource_open,
+ mm_resource_child_init,
+ mm_resource_close
+} mm_resource_op_e;
+
+/**
+ * Manager Resource state enumeration.
+ */
+typedef enum {
+ mm_state_unknown, /** - */
+ mm_state_active, /** A */
+ mm_state_busy, /** B */
+ mm_state_disabled, /** D */
+ mm_state_idle, /** I */
+ mm_state_stopped, /** S */
+ mm_state_error, /** E */
+} mm_state_e;
+
+/**
+ * Balancer method used for standalone operations.
+ */
+typedef enum {
+ mm_balance_undef,
+ mm_balance_r, /** R (Round Robin) */
+ mm_balance_b /** B (Bussines) */
+} mm_balance_method_e;
+
+/**
+ * Connection flush mode.
+ */
+typedef enum {
+ mm_flush_none, /** N (None) */
+ mm_flush_wait, /** T (FlushTimeout) */
+ mm_flush_auto /** A (Auto for ajp) */
+} mm_flush_mode_e;
+
+/**
+ * Data structure representing a Manager server
+ * configuration.
+ */
+typedef struct mm_server_conf_t mm_server_conf_t;
+struct mm_server_conf_t {
+ apr_pool_t *pool;
+ server_rec *server;
+ server_rec *main_server;
+ mm_status_e status;
+ int status_set;
+ const char *handle;
+ int handle_set;
+};
+
+/**
+ * Resource provider data structure
+ */
+typedef struct mm_resource_provider_t mm_resource_provider_t;
+
+/**
+ * Resource provider list structure
+ */
+typedef struct mm_resource_list_t mm_resource_list_t;
+
+/**
+ * Advertise header data structure
+ */
+typedef struct mm_advertise_hdr_t mm_advertise_hdr_t;
+struct mm_advertise_hdr_t {
+ int type;
+ apr_status_t status;
+ char suuid[APR_UUID_FORMATTED_LENGTH + 1];
+};
+
+/**
+ * Advertise server data structure
+ */
+typedef struct mm_advertise_srv_t mm_advertise_srv_t;
+struct mm_advertise_srv_t {
+ const char *handle;
+ const char *address;
+ const char *protocol;
+ server_rec *server;
+ apr_port_t port;
+};
+
+
+/**
+ * Shared memory data record structures
+ */
+typedef struct mmdb_manager_t mmdb_manager_t;
+struct mmdb_manager_t {
+ int strict;
+ int type;
+ int case_blind;
+ int status;
+ int advertise;
+ mm_advertise_e advertise_mode;
+ apr_uuid_t suuid;
+ char srvid[APR_UUID_FORMATTED_LENGTH + 2];
+ unsigned char ssalt[APR_MD5_DIGESTSIZE];
+ int generation;
+};
+
+typedef struct mmdb_hostlist_t mmdb_hostlist_t;
+struct mmdb_hostlist_t {
+ apr_uint32_t host_id;
+ apr_uint32_t selfref;
+ char name[MMDB_MSSIZE];
+};
+
+typedef struct mmdb_host_t mmdb_host_t;
+struct mmdb_host_t {
+ apr_uint32_t balancer_id;
+ mm_state_e status;
+ int is_virtual;
+ int keep_alive;
+ apr_uint32_t keep_alive_max;
+ apr_uint32_t limit_req_line;
+ apr_time_t timeout;
+ apr_time_t keep_alive_timeout;
+ char scheme[MMDB_TSSIZE];
+ char document_root[MMDB_HSSIZE];
+ char address[MMDB_MSSIZE];
+ apr_uint32_t port;
+};
+
+typedef struct mmdb_balancer_t mmdb_balancer_t;
+struct mmdb_balancer_t {
+ mm_state_e status;
+ apr_uint32_t members;
+ apr_uint32_t hosts;
+ int sticky_session;
+ int sticky_session_force;
+ int sticky_session_remove;
+ int retries;
+ int abort_if_headers_send;
+ int abort_if_response_get;
+ mm_balance_method_e method;
+ apr_time_t timeout;
+ char name[MMDB_SSSIZE];
+ char sticky_session_cookie[MMDB_SSSIZE];
+ char sticky_session_path[MMDB_SSSIZE];
+ /* Statistical data */
+};
+
+typedef struct mmdb_member_t mmdb_member_t;
+struct mmdb_member_t {
+ apr_uint32_t balancer_id;
+ mm_protocol_e type;
+ apr_uint32_t port;
+ apr_uint32_t ping;
+ apr_uint32_t ttl;
+ apr_uint32_t max_conn;
+ apr_uint32_t min_conn;
+ apr_uint32_t max_clients;
+ char name[MMDB_MSSIZE];
+ char address[MMDB_MSSIZE];
+ char route[MMDB_MSSIZE];
+ char domain[MMDB_MSSIZE];
+ apr_status_t err;
+ mm_state_e activation;
+ mm_flush_mode_e flush;
+ apr_time_t flush_wait;
+ /* Statistical data */
+ volatile mm_state_e state;
+ volatile apr_uint32_t lf;
+ volatile apr_uint32_t distance;
+ volatile apr_uint64_t lf_mult;
+ volatile apr_uint32_t busy;
+ volatile apr_uint32_t connected;
+ volatile apr_uint32_t elected;
+ volatile apr_uint32_t ssessions;
+ volatile apr_uint32_t err_client;
+ volatile apr_uint32_t err_node;
+ volatile apr_uint32_t trace;
+ volatile apr_uint32_t err_trace;
+ volatile apr_uint64_t readed;
+ volatile apr_uint64_t transferred;
+};
+
+typedef struct mmdb_app_pool_t mmdb_app_pool_t;
+struct mmdb_app_pool_t {
+ apr_uint32_t applications;
+ apr_time_t timeout;
+ volatile mm_state_e status;
+ volatile apr_uint32_t busy;
+ volatile apr_uint32_t concurrency;
+ char name[MMDB_MSSIZE];
+};
+
+typedef struct mmdb_app_t mmdb_app_t;
+struct mmdb_app_t {
+ apr_uint32_t host_id;
+ apr_uint32_t app_pool_id;
+ int status;
+ volatile mm_state_e state;
+ char url[MMDB_HSSIZE];
+};
+
+typedef struct mmdb_memberapp_t mmdb_memberapp_t;
+struct mmdb_memberapp_t {
+ apr_uint32_t app_id;
+ apr_uint32_t member_id;
+ volatile mm_state_e state;
+ /* Statistical data */
+ volatile apr_uint32_t busy;
+ volatile apr_uint32_t transactions;
+ volatile apr_uint32_t err_client;
+ volatile apr_uint32_t err_node;
+ volatile apr_uint64_t readed;
+ volatile apr_uint64_t transferred;
+};
+
+/**
+ * Data structure representing a Manager request
+ */
+typedef struct mm_request_rec mm_request_rec;
+struct mm_request_rec {
+ request_rec *r;
+ mm_server_conf_t *sc;
+};
+
+/**
+ * Manager private.
+ * Initialize callback system.
+ * @param pool The pool to use for callbacks.
+ */
+void mm_callback_initialize(apr_pool_t *pool);
+
+
+/**
+ * Manager private.
+ * Retrurn error description.
+ * @param status Error code.
+ */
+const char *mm_strerror(apr_status_t s);
+
+/**
+ * Manager private.
+ * Run advertise callbacks.
+ * @param mode Advertise mode from configuration.
+ * @param opaque Data passed to callback function.
+ * @param callback Callback function executed for
+ * each registered advertise callback.
+ * see @mm_advertisefn_t for details.
+ */
+apr_status_t mm_advertise_callback_run(mm_advertise_e mode, void *opaque,
+ apr_status_t (*callback)(void *, const char *));
+
+/**
+ * Manager private.
+ * Run maintenance callbacks.
+ * @param mode Maintenance mode. @see mm_maintain_e.
+ */
+apr_status_t mm_maintain_callback_run(mm_maintain_e mode);
+
+/**
+ * Manager private.
+ * Send response message.
+ * @param r Request to use
+ * @param type Response type
+ * @param s APR status code
+ */
+void mm_send_response_ex(request_rec *r, mm_respose_type_e type,
+ apr_status_t s, ...);
+
+/**
+ * Manager private.
+ * Get Command type enumeration.
+ * @param cmd Command string
+ */
+mm_mcmp_command_e mm_mcmp_command_get(const char *cmd);
+
+/**
+ * Manager private.
+ * Get Command type name.
+ * @param cmd Command. @see mm_mcmp_command_e.
+ */
+const char *mm_mcmp_command_name_get(mm_mcmp_command_e cmd);
+
+/**
+ * Manager private.
+ * Get State type name.
+ * @param state State. @see mm_state_e.
+ */
+const char *mm_state_name_get(mm_state_e state);
+
+/**
+ * Manager private.
+ * Get State type.
+ * @param state State string. @see mm_state_e.
+ */
+mm_state_e mm_state_get(const char *sstate);
+
+/**
+ * Manager private.
+ * Get Protocol type.
+ * @param protocol Protocol string. @see mm_protocol_e.
+ */
+mm_protocol_e mm_protocol_get(const char *protocol);
+
+/**
+ * Manager private.
+ * Get Protocol type name.
+ * @param protocol Protocol. @see mm_protocol_e.
+ */
+const char *mm_protocol_name_get(mm_protocol_e protocol);
+
+/**
+ * Manager private.
+ * Create Manager database.
+ * @param dbpath Path to the database directory
+ * @param pool The pool to use
+ */
+apr_status_t mmdb_create(const char *dbpath, apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Open Manager database.
+ * @param dbpath Path to the database directory
+ * @param pool The pool to use
+ */
+apr_status_t mmdb_open(const char *dbpath, apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Close Manager database.
+ */
+apr_status_t mmdb_close();
+
+/**
+ * Manager private.
+ * Maintain Manager database.
+ */
+apr_status_t mmdb_maintain(server_rec *s);
+
+/**
+ * Manager private.
+ * Return table slotmem.
+ * @param name Table name
+ */
+asmm_slotmem_t *mmdb_table_get(const char *name);
+
+/**
+ * Manager private.
+ * Return table slotmem.
+ * @param index Table number
+ */
+asmm_slotmem_t *mmdb_table_getn(int index);
+
+/**
+ * Manager private.
+ * Return table name.
+ * @param index Table number
+ */
+const char *mmdb_table_name_get(int id);
+
+/**
+ * Manager private.
+ * Join to advertise group.
+ * @param addr Advertise group address
+ * @param addr Advertise group port
+ * @param pool The pool to use
+ */
+apr_status_t mma_group_join(const char *addr, apr_port_t port,
+ apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * leave advertise group and close socket.
+ */
+void mma_group_leave();
+
+/**
+ * Manager private.
+ * Server advertise callback.
+ */
+apr_status_t mm_advertise_server_cb(void *cd, const char *data);
+
+/**
+ * The prototype for advertise callback function.
+ * @param mode Advertise mode. @see mm_advertise_e.
+ * @param context Callback private data.
+ * @param data Callback provided data buffer
+ * @param len Callback data buffer length
+ */
+typedef apr_status_t (mm_advertisefn_t)(mm_advertise_e mode, void *context,
+ char *data, apr_size_t size);
+
+/**
+ * Register advetrise callback.
+ * @param pool The pool to create any storage from
+ * @param context Callback private data.
+ * @param callback Callback function. @see mm_advertisefn_t for details.
+ */
+MANAGER_DECLARE(void) mm_register_advertise_callback(apr_pool_t *pool,
+ const void *context,
+ mm_advertisefn_t *callback);
+
+
+/**
+ * The prototype for maintenance callback function.
+ * @param mode Advertise mode. @see mm_advertise_e.
+ * @param context Callback private data.
+ */
+typedef apr_status_t (mm_maintainfn_t)(mm_maintain_e mode, void *context);
+
+/**
+ * Register maintain callback.
+ * @param pool The pool to create any storage from
+ * @param data Opaque data
+ * @param callback Callback function. @see mm_maintainfn_t for details.
+ */
+MANAGER_DECLARE(void) mm_register_maintain_callback(apr_pool_t *pool,
+ const void *data,
+ mm_maintainfn_t *callback);
+
+
+/**
+ * The prototype for resource provider function.
+ * @param cfg Manager configuration.
+ * @param cmd Command to execute.
+ * @param name Resource name.
+ * @param prev Previous resource data provider.
+ * @param prev_id Previous resource record id.
+ * @param prev_rec Previous resource record data.
+ * @param cmd_table Command table.
+ * @param cmd_offset Command table offset to the first instruction;
+ * @param r Current request record
+ */
+typedef apr_status_t (mm_runproviderfn_t)(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r);
+
+
+/**
+ * The prototype for resource provider initizalize function.
+ * @param cfg Manager configuration.
+ * @param op Resource operation. @see mm_resource_op_e
+ * @param pool The pool to create any storage from
+ */
+typedef apr_status_t (mm_iniproviderfn_t)(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool);
+
+/**
+ * Resource provider data structure
+ */
+struct mm_resource_provider_t {
+ int id; /** Id of the Resource */
+ const char *name; /** Name of the resource */
+ mm_runproviderfn_t *func; /** @see mm_runproviderfn_t */
+ mm_iniproviderfn_t *init; /** @see mm_iniproviderfn_t */
+ void *context; /** General purpose storage */
+};
+
+
+/**
+ * Resource provider list structure
+ */
+struct mm_resource_list_t {
+ mm_resource_provider_t *provider;
+ mm_resource_list_t *next;
+};
+
+
+/**
+ * Register resource provider.
+ * @param pool The pool to create any storage from
+ * @param provider Resource provider data structure
+ */
+MANAGER_DECLARE(void) mm_register_resource_provider(apr_pool_t *pool,
+ mm_resource_provider_t *provider);
+
+/**
+ * Find registered resource provider.
+ * @param name Resource provider name.
+ */
+MANAGER_DECLARE(mm_resource_provider_t *)mm_lookup_resource_provider(const char *name);
+
+/**
+ * List registered resource provider.
+ * @param pool The poll to allocate list.
+ */
+MANAGER_DECLARE(mm_resource_list_t *)mm_list_resource_providers(apr_pool_t *pool);
+
+/**
+ * Run registered resource providers.
+ * @param cfg Manager configuration.
+ * @param op Resource operation. @see mm_resource_op_e
+ * @param pool The pool to create any storage from
+ */
+MANAGER_DECLARE(void)mm_run_resource_providers(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register static Manager resource
+ */
+void mm_register_resource_manager(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register static Server resource
+ */
+void mm_register_resource_server(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register Host resource
+ */
+void mm_register_resource_host(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register ApplicationPool resource
+ */
+void mm_register_resource_app_pool(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register Balancer resource
+ */
+void mm_register_resource_balancer(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register Member resource
+ */
+void mm_register_resource_member(apr_pool_t *pool);
+
+/**
+ * Manager private.
+ * Register Application resource
+ */
+void mm_register_resource_application(apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* MM_API_H */
Property changes on: sandbox/aloha/httpd/modules/manager/mm_api.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_app.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_app.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_app.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,730 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Application object resource routines */
+#include "mm_api.h"
+
+static mmdb_manager_t *manager_rec = NULL;
+static mm_resource_provider_t *this_provider = NULL;
+
+static const char *app_params[] = {
+ "",
+ "Host",
+ "ApplicationPool",
+ "State",
+ "Status",
+ NULL
+};
+
+static const char *memberapp_params[] = {
+ "",
+ "State",
+ /* Statistical data */
+ "Busy",
+ "Transactions",
+ "ClientErrors",
+ "NodeErrors",
+ "Readed",
+ "Transferred",
+ NULL
+};
+
+static const char *get_host_name(apr_uint32_t id)
+{
+ apr_uint32_t next = 0;
+ mmdb_hostlist_t *hostlist;
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+
+ while ((hostlist = asmm_slot_next(hostlist_db, &next))) {
+ if (hostlist->host_id == id && hostlist->selfref == (next - 1))
+ return hostlist->name;
+ }
+ return NULL;
+}
+
+static const char *get_app_pool_name(apr_uint32_t id)
+{
+ mmdb_app_pool_t *app_pool;
+ asmm_slotmem_t *app_pool_db = mmdb_table_getn(MMDB_APP_POOL);
+
+ if ((app_pool = asmm_slot(app_pool_db, id))) {
+ return app_pool->name;
+ }
+ return NULL;
+}
+
+static mmdb_app_pool_t *get_app_pool(const char *value, apr_uint32_t *id)
+{
+ apr_uint32_t next = 0;
+ mmdb_app_pool_t *app_pool;
+ asmm_slotmem_t *app_pool_db = mmdb_table_getn(MMDB_APP_POOL);
+
+ while ((app_pool = asmm_slot_next(app_pool_db, &next))) {
+ if (strcasecmp(value, app_pool->name))
+ continue;
+ *id = next - 1;
+ return app_pool;
+ }
+ return NULL;
+}
+
+static void rdo_app_info_print(int pi, int pp,
+ mmdb_app_t *app,
+ request_rec *r)
+{
+ if (pp) {
+ ap_rvputs(r, app_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* Host */
+ ap_rvputs(r, get_host_name(app->host_id), NULL);
+ break;
+ case 2: /* ApplicationPool */
+ ap_rvputs(r, get_app_pool_name(app->app_pool_id), NULL);
+ break;
+ case 3: /* State */
+ ap_rputs(mm_state_name_get(app->state), r);
+ break;
+ case 4: /* Status */
+ ap_rprintf(r, "%d", app->status);
+ break;
+ }
+}
+
+static void rdo_memberapp_info_print(int pi, int pp,
+ mmdb_memberapp_t *mem,
+ request_rec *r)
+{
+ if (pp) {
+ ap_rvputs(r, memberapp_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* State */
+ ap_rputs(mm_state_name_get(mem->state), r);
+ break;
+ case 2: /* Busy */
+ ap_rprintf(r, "%u", mem->busy);
+ break;
+ case 3: /* Transactions */
+ ap_rprintf(r, "%u", mem->transactions);
+ break;
+ case 4: /* ClientErrors */
+ ap_rprintf(r, "%u", mem->err_client);
+ break;
+ case 5: /* NodeErrors */
+ ap_rprintf(r, "%u", mem->err_node);
+ break;
+ case 6: /* Readed */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->readed);
+ break;
+ case 7: /* Transferred */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->transferred);
+ break;
+ }
+}
+
+/* Dump Application info */
+static void rdo_app_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_app_t *app,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (app_params[j]) {
+ if (apr_fnmatch(ce[i].key, app_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (app_params[j]) {
+ if (!strcasecmp(ce[i].key, app_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_app_info_print(m, wcm, app, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (app_params[j]) {
+ if (apr_fnmatch(ce[i].key, app_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_app_info_print(j, 1, app, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (app_params[j]) {
+ if (!strcasecmp(ce[i].key, app_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_app_info_print(j, 1, app, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+/* Dump MemberApplication info */
+static void rdo_memberapp_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_memberapp_t *mem,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (memberapp_params[j]) {
+ if (apr_fnmatch(ce[i].key, memberapp_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (memberapp_params[j]) {
+ if (!strcasecmp(ce[i].key, memberapp_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_memberapp_info_print(m, wcm, mem, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (memberapp_params[j]) {
+ if (apr_fnmatch(ce[i].key, memberapp_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_memberapp_info_print(j, 1, mem, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (memberapp_params[j]) {
+ if (!strcasecmp(ce[i].key, memberapp_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_memberapp_info_print(j, 1, mem, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static apr_status_t rdo_app_config_do(int pi,
+ const char *value,
+ mmdb_app_t *app,
+ request_rec *r)
+{
+ int i;
+ apr_uint32_t app_pool_id;
+ mmdb_app_pool_t *app_pool;
+
+ switch (pi) {
+ case 2: /* ApplicationPool */
+ if (app->app_pool_id) {
+ if (!(app_pool = asmm_slot(mmdb_table_getn(MMDB_APP_POOL),
+ app->app_pool_id)))
+ return MME_EINVAL;
+ if (app_pool->applications)
+ app_pool->applications--;
+ }
+ if ((app_pool = get_app_pool(value, &app_pool_id))) {
+ app->state = mm_state_get(value);
+ if (app_pool_id)
+ app_pool->applications++;
+ }
+ break;
+ case 3: /* State */
+ app->state = mm_state_get(value);
+ break;
+ case 4: /* Status */
+ i = atoi(value);
+ if (ap_is_HTTP_VALID_RESPONSE(i))
+ app->status = i;
+ else
+ return MME_EINVAL;
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_memberapp_config_do(int pi,
+ const char *value,
+ mmdb_memberapp_t *mem,
+ request_rec *r)
+{
+ switch (pi) {
+ case 1: /* State */
+ mem->state = mm_state_get(value);
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+/* Configure Application */
+static int rdo_app_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ mmdb_app_t *app,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (app_params[j]) {
+ if (!strcasecmp(ce[i].key, app_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_app_config_do(j, ce[i].val,
+ app, r)) != APR_SUCCESS) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Configure MemberApplication */
+static int rdo_memberapp_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ mmdb_memberapp_t *memberapp,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (memberapp_params[j]) {
+ if (!strcasecmp(ce[i].key, memberapp_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_memberapp_config_do(j, ce[i].val,
+ memberapp, r)) != APR_SUCCESS) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static apr_status_t rdo_app(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int cblind = 0;
+ int wcm;
+ apr_uint32_t next = 0;
+ apr_uint32_t mapp = 0;
+
+ mmdb_app_t *app;
+ mmdb_memberapp_t *memberapp;
+ mmdb_member_t *member = NULL;
+ mmdb_host_t *host = NULL;
+ mmdb_app_pool_t *app_pool = NULL;
+
+ asmm_slotmem_t *member_db = mmdb_table_getn(MMDB_MEMBER);
+ asmm_slotmem_t *app_db = mmdb_table_getn(MMDB_APPLICATION);
+ asmm_slotmem_t *memberapp_db = mmdb_table_getn(MMDB_MEMBERAPP);
+ asmm_slotmem_t *app_pool_db = mmdb_table_getn(MMDB_APP_POOL);
+
+ if (!memberapp_db || !app_db || !member_db || !app_pool_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty Application name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ }
+ if (manager_rec && manager_rec->case_blind)
+ cblind = 1;
+ if (prev) {
+ switch (prev->id) {
+ case MMDB_HOST:
+ host = (mmdb_host_t *)prev_rec;
+ break;
+ case MMDB_MEMBER:
+ member = (mmdb_member_t *)prev_rec;
+ break;
+ case MMDB_APP_POOL:
+ app_pool = (mmdb_app_pool_t *)prev_rec;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: type %s in not a valid root for "
+ "Application: %s",
+ prev->name, name);
+ return APR_SUCCESS;
+ break;
+
+ }
+ }
+ if (!host && !member && !app_pool) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Missing root object for Application: %s",
+ name);
+ return APR_SUCCESS;
+ }
+ if (*name != '~')
+ wcm = apr_fnmatch_test(name);
+ while ((app = asmm_slot_next(app_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, app->url,
+ cblind ? MM_FFNMATCH : 0) != APR_SUCCESS)
+ continue;
+ }
+ else if (cblind ? strcasecmp(name, app->url) : strcmp(name, app->url))
+ continue;
+ if (host) {
+ if (prev_id != app->host_id)
+ continue;
+ /* Application defined inside Host
+ */
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm)
+ ap_rvputs(r, "@" MM_RES_APPLICATION "/",
+ app->url, ": ", NULL);
+ rdo_app_info(cmd_table, cmd_offset, wcm, app, r);
+ break;
+ case mm_mcmp_config:
+ if (rdo_app_config(cfg, cmd_table, cmd_offset,
+ app, r))
+ return APR_SUCCESS;
+ break;
+ case mm_mcmp_enable:
+ app->state = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ app->state = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ app->state = mm_state_stopped;
+ break;
+ case mm_mcmp_delete:
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for "
+ "Application",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ }
+ else if (member) {
+ /* Manage MemberApplication object
+ * because we were called from
+ * Member object
+ */
+ while ((memberapp = asmm_slot_next(memberapp_db, &mapp))) {
+ if (memberapp->app_id == (next - 1))
+ break;
+ }
+ if (!memberapp) {
+ /* No MemberApplication object found
+ * Database corrupted
+ */
+ return APR_ESYMNOTFOUND;
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm)
+ ap_rvputs(r, "@" MM_RES_APPLICATION "/",
+ app->url, ": ", NULL);
+ rdo_memberapp_info(cmd_table, cmd_offset, wcm,
+ memberapp, r);
+ break;
+ case mm_mcmp_config:
+ if (rdo_memberapp_config(cfg, cmd_table, cmd_offset,
+ memberapp, r))
+ return APR_SUCCESS;
+ break;
+ case mm_mcmp_enable:
+ memberapp->state = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ memberapp->state = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ memberapp->state = mm_state_stopped;
+ break;
+ case mm_mcmp_reset:
+ /* Reset statistical data */
+ memberapp->busy = 0;
+ memberapp->transactions = 0;
+ memberapp->err_client = 0;
+ memberapp->err_node = 0;
+ memberapp->readed = 0;
+ memberapp->transferred = 0;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for "
+ "MemberApplication",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ }
+ else {
+ if (prev_id != app->app_pool_id)
+ continue;
+ /* Application defined inside ApplicationPool
+ */
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm)
+ ap_rvputs(r, MM_RES_APPLICATION "/",
+ app->url, CRLF, NULL);
+ else
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ case mm_mcmp_delete:
+ app->app_pool_id = 0;
+ if (app_pool->applications)
+ app_pool->applications--;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for "
+ "Application",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone && host) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_uint32_t app_id;
+ /* Create new Application and
+ * MemberApplications for all
+ * Members matching balancer_id
+ */
+ if (!(app = asmm_salloc_ex(app_db, &app_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(app->url, name);
+ app->host_id = prev_id;
+ app->state = host->status;
+ app->status = HTTP_OK;
+ /* Configure Application from params */
+ if (rdo_app_config(cfg, cmd_table, cmd_offset, app, r)) {
+ /* There was an error during initial config
+ * Delete Application we created
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: failed creating Application: %s",
+ name);
+ asmm_free(app_db, app);
+ return APR_SUCCESS;
+ }
+
+ /* Add MemberApplication objects */
+ next = 0;
+ while ((member = asmm_slot_next(member_db, &next))) {
+ if (member->balancer_id == host->balancer_id) {
+ if (!(memberapp = asmm_salloc(memberapp_db)))
+ return apr_get_os_error();
+ memberapp->app_id = app_id;
+ memberapp->member_id = next - 1;
+ memberapp->state = app->state;
+ }
+ }
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_app(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ case mm_resource_open:
+ case mm_resource_child_init:
+ manager_rec = asmm_slot(mmdb_table_getn(MMDB_MANAGER), 0);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a Applications */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t app_provider = {
+ MMDB_APPLICATION,
+ MM_RES_APPLICATION,
+ rdo_app,
+ ini_app,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_application(apr_pool_t *pool)
+{
+ this_provider = &app_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_app.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_asmm.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_asmm.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_asmm.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,1548 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Advanced shared memory utility routines */
+#include "mm_asmm.h"
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for getpid() */
+#endif
+
+#if APR_IS_BIGENDIAN
+#define ASMM_DEAD_COOKIE 0xDEADBEEF
+#else
+#define ASMM_DEAD_COOKIE 0xEFBEADDE
+#endif
+
+static apr_byte_t __zero_bit_mask[] = {
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+static apr_byte_t __ones_bit_mask[] = {
+ 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE
+};
+
+static struct __byte_bits {
+ apr_byte_t left; /* number of left zeros */
+ apr_byte_t right; /* number of right zeros */
+ apr_byte_t count; /* zeros count*/
+ apr_byte_t first; /* first zero position */
+ apr_byte_t hole; /* hole size */
+ apr_byte_t pos; /* hole position */
+} __bit_mask[] = {
+ /* L R C F H P */
+ /* 00000000 */ { 8, 8, 8, 0, 8, 0},
+ /* 00000001 */ { 7, 0, 7, 0, 7, 0},
+ /* 00000010 */ { 6, 1, 7, 0, 6, 0},
+ /* 00000011 */ { 6, 0, 6, 0, 6, 0},
+ /* 00000100 */ { 5, 2, 7, 0, 5, 0},
+ /* 00000101 */ { 5, 0, 6, 0, 5, 0},
+ /* 00000110 */ { 5, 1, 6, 0, 5, 0},
+ /* 00000111 */ { 5, 0, 5, 0, 5, 0},
+ /* 00001000 */ { 4, 3, 7, 0, 4, 0},
+ /* 00001001 */ { 4, 0, 6, 0, 4, 0},
+ /* 00001010 */ { 4, 1, 6, 0, 4, 0},
+ /* 00001011 */ { 4, 0, 5, 0, 4, 0},
+ /* 00001100 */ { 4, 2, 6, 0, 4, 0},
+ /* 00001101 */ { 4, 0, 5, 0, 4, 0},
+ /* 00001110 */ { 4, 1, 5, 0, 4, 0},
+ /* 00001111 */ { 4, 0, 4, 0, 4, 0},
+ /* 00010000 */ { 3, 4, 7, 0, 4, 4},
+ /* 00010001 */ { 3, 0, 6, 0, 3, 0},
+ /* 00010010 */ { 3, 1, 6, 0, 3, 0},
+ /* 00010011 */ { 3, 0, 5, 0, 3, 0},
+ /* 00010100 */ { 3, 2, 6, 0, 3, 0},
+ /* 00010101 */ { 3, 0, 5, 0, 3, 0},
+ /* 00010110 */ { 3, 1, 5, 0, 3, 0},
+ /* 00010111 */ { 3, 0, 4, 0, 3, 0},
+ /* 00011000 */ { 3, 3, 6, 0, 3, 0},
+ /* 00011001 */ { 3, 0, 5, 0, 3, 0},
+ /* 00011010 */ { 3, 1, 5, 0, 3, 0},
+ /* 00011011 */ { 3, 0, 4, 0, 3, 0},
+ /* 00011100 */ { 3, 2, 5, 0, 3, 0},
+ /* 00011101 */ { 3, 0, 4, 0, 3, 0},
+ /* 00011110 */ { 3, 1, 4, 0, 3, 0},
+ /* 00011111 */ { 3, 0, 3, 0, 3, 0},
+ /* 00100000 */ { 2, 5, 7, 0, 5, 0},
+ /* 00100001 */ { 2, 0, 6, 0, 4, 0},
+ /* 00100010 */ { 2, 1, 6, 0, 3, 0},
+ /* 00100011 */ { 2, 0, 5, 0, 3, 0},
+ /* 00100100 */ { 2, 2, 6, 0, 2, 0},
+ /* 00100101 */ { 2, 0, 5, 0, 2, 0},
+ /* 00100110 */ { 2, 1, 5, 0, 2, 0},
+ /* 00100111 */ { 2, 0, 4, 0, 2, 0},
+ /* 00101000 */ { 2, 3, 6, 0, 3, 5},
+ /* 00101001 */ { 2, 0, 5, 0, 2, 0},
+ /* 00101010 */ { 2, 1, 5, 0, 2, 0},
+ /* 00101011 */ { 2, 0, 4, 0, 2, 0},
+ /* 00101100 */ { 2, 2, 5, 0, 2, 0},
+ /* 00101101 */ { 2, 0, 4, 0, 2, 0},
+ /* 00101110 */ { 2, 1, 4, 0, 2, 0},
+ /* 00101111 */ { 2, 0, 3, 0, 2, 0},
+ /* 00110000 */ { 2, 4, 6, 0, 4, 4},
+ /* 00110001 */ { 2, 0, 5, 0, 3, 4},
+ /* 00110010 */ { 2, 1, 5, 0, 2, 0},
+ /* 00110011 */ { 2, 0, 4, 0, 2, 0},
+ /* 00110100 */ { 2, 2, 5, 0, 2, 0},
+ /* 00110101 */ { 2, 0, 4, 0, 2, 0},
+ /* 00110110 */ { 2, 1, 4, 0, 2, 0},
+ /* 00110111 */ { 2, 0, 3, 0, 2, 0},
+ /* 00111000 */ { 2, 3, 5, 0, 3, 5},
+ /* 00111001 */ { 2, 0, 4, 0, 2, 0},
+ /* 00111010 */ { 2, 1, 4, 0, 2, 0},
+ /* 00111011 */ { 2, 0, 3, 0, 2, 0},
+ /* 00111100 */ { 2, 2, 4, 0, 2, 0},
+ /* 00111101 */ { 2, 0, 3, 0, 2, 0},
+ /* 00111110 */ { 2, 1, 3, 0, 2, 0},
+ /* 00111111 */ { 2, 0, 2, 0, 2, 0},
+ /* 01000000 */ { 1, 6, 7, 0, 6, 2},
+ /* 01000001 */ { 1, 0, 6, 0, 5, 2},
+ /* 01000010 */ { 1, 1, 6, 0, 4, 2},
+ /* 01000011 */ { 1, 0, 5, 0, 4, 2},
+ /* 01000100 */ { 1, 2, 6, 0, 3, 2},
+ /* 01000101 */ { 1, 0, 5, 0, 3, 2},
+ /* 01000110 */ { 1, 1, 5, 0, 3, 2},
+ /* 01000111 */ { 1, 0, 4, 0, 3, 2},
+ /* 01001000 */ { 1, 3, 6, 0, 3, 5},
+ /* 01001001 */ { 1, 0, 5, 0, 2, 2},
+ /* 01001010 */ { 1, 1, 5, 0, 2, 2},
+ /* 01001011 */ { 1, 0, 4, 0, 2, 2},
+ /* 01001100 */ { 1, 2, 5, 0, 2, 2},
+ /* 01001101 */ { 1, 0, 4, 0, 2, 2},
+ /* 01001110 */ { 1, 1, 4, 0, 2, 2},
+ /* 01001111 */ { 1, 0, 3, 0, 2, 2},
+ /* 01010000 */ { 1, 4, 6, 0, 4, 4},
+ /* 01010001 */ { 1, 0, 5, 0, 3, 4},
+ /* 01010010 */ { 1, 1, 5, 0, 2, 4},
+ /* 01010011 */ { 1, 0, 4, 0, 2, 4},
+ /* 01010100 */ { 1, 2, 5, 0, 2, 6},
+ /* 01010101 */ { 1, 0, 4, 0, 1, 0},
+ /* 01010110 */ { 1, 1, 4, 0, 1, 0},
+ /* 01010111 */ { 1, 0, 3, 0, 1, 0},
+ /* 01011000 */ { 1, 3, 5, 0, 3, 5},
+ /* 01011001 */ { 1, 0, 4, 0, 2, 5},
+ /* 01011010 */ { 1, 1, 4, 0, 1, 0},
+ /* 01011011 */ { 1, 0, 3, 0, 1, 0},
+ /* 01011100 */ { 1, 2, 4, 0, 2, 6},
+ /* 01011101 */ { 1, 0, 3, 0, 1, 0},
+ /* 01011110 */ { 1, 1, 3, 0, 1, 0},
+ /* 01011111 */ { 1, 0, 2, 0, 1, 0},
+ /* 01100000 */ { 1, 5, 6, 0, 5, 0},
+ /* 01100001 */ { 1, 0, 5, 0, 4, 0},
+ /* 01100010 */ { 1, 1, 5, 0, 3, 0},
+ /* 01100011 */ { 1, 0, 4, 0, 3, 0},
+ /* 01100100 */ { 1, 2, 5, 0, 2, 0},
+ /* 01100101 */ { 1, 0, 4, 0, 2, 0},
+ /* 01100110 */ { 1, 1, 4, 0, 2, 0},
+ /* 01100111 */ { 1, 0, 3, 0, 2, 0},
+ /* 01101000 */ { 1, 3, 5, 0, 3, 5},
+ /* 01101001 */ { 1, 0, 4, 0, 2, 5},
+ /* 01101010 */ { 1, 1, 4, 0, 1, 0},
+ /* 01101011 */ { 1, 0, 3, 0, 1, 0},
+ /* 01101100 */ { 1, 2, 4, 0, 2, 6},
+ /* 01101101 */ { 1, 0, 3, 0, 1, 0},
+ /* 01101110 */ { 1, 1, 3, 0, 1, 0},
+ /* 01101111 */ { 1, 0, 2, 0, 1, 0},
+ /* 01110000 */ { 1, 4, 5, 0, 4, 4},
+ /* 01110001 */ { 1, 0, 4, 0, 3, 4},
+ /* 01110010 */ { 1, 1, 4, 0, 2, 4},
+ /* 01110011 */ { 1, 0, 3, 0, 2, 4},
+ /* 01110100 */ { 1, 2, 4, 0, 2, 6},
+ /* 01110101 */ { 1, 0, 3, 0, 1, 0},
+ /* 01110110 */ { 1, 1, 3, 0, 1, 0},
+ /* 01110111 */ { 1, 0, 2, 0, 1, 0},
+ /* 01111000 */ { 1, 3, 4, 0, 3, 5},
+ /* 01111001 */ { 1, 0, 3, 0, 2, 5},
+ /* 01111010 */ { 1, 1, 3, 0, 1, 0},
+ /* 01111011 */ { 1, 0, 2, 0, 1, 0},
+ /* 01111100 */ { 1, 2, 3, 0, 2, 6},
+ /* 01111101 */ { 1, 0, 2, 0, 1, 0},
+ /* 01111110 */ { 1, 1, 2, 0, 1, 0},
+ /* 01111111 */ { 1, 0, 1, 0, 1, 0},
+ /* 10000000 */ { 0, 7, 7, 1, 7, 1},
+ /* 10000001 */ { 0, 0, 6, 1, 6, 1},
+ /* 10000010 */ { 0, 1, 6, 1, 5, 1},
+ /* 10000011 */ { 0, 0, 5, 1, 5, 1},
+ /* 10000100 */ { 0, 2, 6, 1, 4, 1},
+ /* 10000101 */ { 0, 0, 5, 1, 4, 1},
+ /* 10000110 */ { 0, 1, 5, 1, 4, 1},
+ /* 10000111 */ { 0, 0, 4, 1, 4, 1},
+ /* 10001000 */ { 0, 3, 6, 1, 3, 1},
+ /* 10001001 */ { 0, 0, 5, 1, 3, 1},
+ /* 10001010 */ { 0, 1, 5, 1, 3, 1},
+ /* 10001011 */ { 0, 0, 4, 1, 3, 1},
+ /* 10001100 */ { 0, 2, 5, 1, 3, 1},
+ /* 10001101 */ { 0, 0, 4, 1, 3, 1},
+ /* 10001110 */ { 0, 1, 4, 1, 3, 1},
+ /* 10001111 */ { 0, 0, 3, 1, 3, 1},
+ /* 10010000 */ { 0, 4, 6, 1, 4, 4},
+ /* 10010001 */ { 0, 0, 5, 1, 3, 4},
+ /* 10010010 */ { 0, 1, 5, 1, 2, 1},
+ /* 10010011 */ { 0, 0, 4, 1, 2, 1},
+ /* 10010100 */ { 0, 2, 5, 1, 2, 1},
+ /* 10010101 */ { 0, 0, 4, 1, 2, 1},
+ /* 10010110 */ { 0, 1, 4, 1, 2, 1},
+ /* 10010111 */ { 0, 0, 3, 1, 2, 1},
+ /* 10011000 */ { 0, 3, 5, 1, 3, 5},
+ /* 10011001 */ { 0, 0, 4, 1, 2, 1},
+ /* 10011010 */ { 0, 1, 4, 1, 2, 1},
+ /* 10011011 */ { 0, 0, 3, 1, 2, 1},
+ /* 10011100 */ { 0, 2, 4, 1, 2, 1},
+ /* 10011101 */ { 0, 0, 3, 1, 2, 1},
+ /* 10011110 */ { 0, 1, 3, 1, 2, 1},
+ /* 10011111 */ { 0, 0, 2, 1, 2, 1},
+ /* 10100000 */ { 0, 5, 6, 1, 5, 1},
+ /* 10100001 */ { 0, 0, 5, 1, 4, 1},
+ /* 10100010 */ { 0, 1, 5, 1, 3, 1},
+ /* 10100011 */ { 0, 0, 4, 1, 3, 1},
+ /* 10100100 */ { 0, 2, 5, 1, 2, 1},
+ /* 10100101 */ { 0, 0, 4, 1, 2, 1},
+ /* 10100110 */ { 0, 1, 4, 1, 2, 1},
+ /* 10100111 */ { 0, 0, 3, 1, 2, 1},
+ /* 10101000 */ { 0, 3, 5, 1, 3, 5},
+ /* 10101001 */ { 0, 0, 4, 1, 2, 5},
+ /* 10101010 */ { 0, 1, 4, 1, 1, 1},
+ /* 10101011 */ { 0, 0, 3, 1, 1, 1},
+ /* 10101100 */ { 0, 2, 4, 1, 2, 6},
+ /* 10101101 */ { 0, 0, 3, 1, 1, 1},
+ /* 10101110 */ { 0, 1, 3, 1, 1, 1},
+ /* 10101111 */ { 0, 0, 2, 1, 1, 1},
+ /* 10110000 */ { 0, 4, 5, 1, 4, 4},
+ /* 10110001 */ { 0, 0, 4, 1, 3, 4},
+ /* 10110010 */ { 0, 1, 4, 1, 2, 4},
+ /* 10110011 */ { 0, 0, 3, 1, 2, 4},
+ /* 10110100 */ { 0, 2, 4, 1, 2, 6},
+ /* 10110101 */ { 0, 0, 3, 1, 1, 1},
+ /* 10110110 */ { 0, 1, 3, 1, 1, 1},
+ /* 10110111 */ { 0, 0, 2, 1, 1, 1},
+ /* 10111000 */ { 0, 3, 4, 1, 3, 5},
+ /* 10111001 */ { 0, 0, 3, 1, 2, 5},
+ /* 10111010 */ { 0, 1, 3, 1, 1, 1},
+ /* 10111011 */ { 0, 0, 2, 1, 1, 1},
+ /* 10111100 */ { 0, 2, 3, 1, 2, 6},
+ /* 10111101 */ { 0, 0, 2, 1, 1, 1},
+ /* 10111110 */ { 0, 1, 2, 1, 1, 1},
+ /* 10111111 */ { 0, 0, 1, 1, 1, 1},
+ /* 11000000 */ { 0, 6, 6, 2, 6, 2},
+ /* 11000001 */ { 0, 0, 5, 2, 5, 2},
+ /* 11000010 */ { 0, 1, 5, 2, 4, 2},
+ /* 11000011 */ { 0, 0, 4, 2, 4, 2},
+ /* 11000100 */ { 0, 2, 5, 2, 3, 2},
+ /* 11000101 */ { 0, 0, 4, 2, 3, 2},
+ /* 11000110 */ { 0, 1, 4, 2, 3, 2},
+ /* 11000111 */ { 0, 0, 3, 2, 3, 2},
+ /* 11001000 */ { 0, 3, 5, 2, 3, 5},
+ /* 11001001 */ { 0, 0, 4, 2, 2, 2},
+ /* 11001010 */ { 0, 1, 4, 2, 2, 2},
+ /* 11001011 */ { 0, 0, 3, 2, 2, 2},
+ /* 11001100 */ { 0, 2, 4, 2, 2, 2},
+ /* 11001101 */ { 0, 0, 3, 2, 2, 2},
+ /* 11001110 */ { 0, 1, 3, 2, 2, 2},
+ /* 11001111 */ { 0, 0, 2, 2, 2, 2},
+ /* 11010000 */ { 0, 4, 5, 2, 4, 4},
+ /* 11010001 */ { 0, 0, 4, 2, 3, 4},
+ /* 11010010 */ { 0, 1, 4, 2, 2, 4},
+ /* 11010011 */ { 0, 0, 3, 2, 2, 4},
+ /* 11010100 */ { 0, 2, 4, 2, 2, 6},
+ /* 11010101 */ { 0, 0, 3, 2, 1, 2},
+ /* 11010110 */ { 0, 1, 3, 2, 1, 2},
+ /* 11010111 */ { 0, 0, 2, 2, 1, 2},
+ /* 11011000 */ { 0, 3, 4, 2, 3, 5},
+ /* 11011001 */ { 0, 0, 3, 2, 2, 5},
+ /* 11011010 */ { 0, 1, 3, 2, 1, 2},
+ /* 11011011 */ { 0, 0, 2, 2, 1, 2},
+ /* 11011100 */ { 0, 2, 3, 2, 2, 6},
+ /* 11011101 */ { 0, 0, 2, 2, 1, 2},
+ /* 11011110 */ { 0, 1, 2, 2, 1, 2},
+ /* 11011111 */ { 0, 0, 1, 2, 1, 2},
+ /* 11100000 */ { 0, 5, 5, 3, 5, 3},
+ /* 11100001 */ { 0, 0, 4, 3, 4, 3},
+ /* 11100010 */ { 0, 1, 4, 3, 3, 3},
+ /* 11100011 */ { 0, 0, 3, 3, 3, 3},
+ /* 11100100 */ { 0, 2, 4, 3, 2, 3},
+ /* 11100101 */ { 0, 0, 3, 3, 2, 3},
+ /* 11100110 */ { 0, 1, 3, 3, 2, 3},
+ /* 11100111 */ { 0, 0, 2, 3, 2, 3},
+ /* 11101000 */ { 0, 3, 4, 3, 3, 5},
+ /* 11101001 */ { 0, 0, 3, 3, 2, 5},
+ /* 11101010 */ { 0, 1, 3, 3, 1, 3},
+ /* 11101011 */ { 0, 0, 2, 3, 1, 3},
+ /* 11101100 */ { 0, 2, 3, 3, 2, 6},
+ /* 11101101 */ { 0, 0, 2, 3, 1, 3},
+ /* 11101110 */ { 0, 1, 2, 3, 1, 3},
+ /* 11101111 */ { 0, 0, 1, 3, 1, 3},
+ /* 11110000 */ { 0, 4, 4, 4, 4, 4},
+ /* 11110001 */ { 0, 0, 3, 4, 3, 4},
+ /* 11110010 */ { 0, 1, 3, 4, 2, 4},
+ /* 11110011 */ { 0, 0, 2, 4, 2, 4},
+ /* 11110100 */ { 0, 2, 3, 4, 2, 6},
+ /* 11110101 */ { 0, 0, 2, 4, 1, 4},
+ /* 11110110 */ { 0, 1, 2, 4, 1, 4},
+ /* 11110111 */ { 0, 0, 1, 4, 1, 4},
+ /* 11111000 */ { 0, 3, 3, 5, 3, 5},
+ /* 11111001 */ { 0, 0, 2, 5, 2, 5},
+ /* 11111010 */ { 0, 1, 2, 5, 1, 5},
+ /* 11111011 */ { 0, 0, 1, 5, 1, 5},
+ /* 11111100 */ { 0, 2, 2, 6, 2, 6},
+ /* 11111101 */ { 0, 0, 1, 6, 1, 6},
+ /* 11111110 */ { 0, 1, 1, 7, 1, 7},
+ /* 11111111 */ { 0, 0, 0, 0, 0, 0}
+};
+
+static apr_byte_t __sbit_mask[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 0
+};
+
+
+#define _GET_BIT(a, x) ((((a)[(x) >> 3] & __zero_bit_mask[(x) & 0x07]) !=
0))
+#define _SET_BIT(a, x) ((void)((a)[(x) >> 3] |= __zero_bit_mask[(x) & 0x07]))
+#define _CLR_BIT(a, x) ((void)((a)[(x) >> 3] &= __ones_bit_mask[(x) &
0x07]))
+#define _FLP_BIT(a, x) ((void)((a)[(x) >> 3] ^= __zero_bit_mask[(x) & 0x07]))
+
+#define _ASMM_VLOCK(m) \
+ if ((m)->lock) \
+ (void)apr_global_mutex_lock((m)->lock)
+
+#define _ASMM_LOCK(m) \
+ if ((m)->lock) { \
+ apr_status_t _rv; \
+ if ((_rv = apr_global_mutex_lock((m)->lock)) != APR_SUCCESS) { \
+ apr_set_os_error(_rv); \
+ return NULL; } } else (void)(0)
+
+#define _ASMM_UNLOCK(m) \
+ if ((m)->lock) apr_global_mutex_unlock((m)->lock)
+
+static apr_status_t asmm_bmp_get(const apr_byte_t *bmp, apr_uint32_t len,
+ apr_uint32_t *pos)
+{
+ apr_uint32_t i;
+
+ for (i = 0; i < len; i++) {
+ if (bmp[i] != 0xFF) {
+ *pos = (i << 3) + __sbit_mask[bmp[i]];
+ return APR_SUCCESS;
+ }
+ }
+ return APR_EOF;
+}
+
+static apr_uint32_t asmm_bmp_free(const apr_byte_t *bmp, apr_uint32_t len)
+{
+ apr_uint32_t i, c = 0;
+
+ for (i = 0; i < len; i++) {
+ c += __bit_mask[i].count;
+ }
+ return c;
+}
+
+static apr_status_t asmm_bmp_find(const apr_byte_t *bmp, apr_uint32_t len,
+ apr_uint32_t size, apr_uint32_t *pos)
+{
+ apr_uint32_t i;
+
+ len = len >> 3;
+ if (size > 8) {
+ apr_uint32_t nb, p;
+ nb = size >> 3;
+ if ((nb << 3) < size)
+ nb++;
+ for (i = 0; i <= len - nb; i++) {
+ apr_uint32_t r;
+ if ((r = __bit_mask[bmp[i]].right) != 0) {
+ p = (i << 3) + 8 - r;
+ if (!_GET_BIT(bmp, p + size - 1)) {
+ apr_uint32_t j;
+ for (j = 1; j < nb; j++) {
+ if (__bit_mask[bmp[i + j]].left != 8)
+ break;
+ r += __bit_mask[bmp[i + j]].left;
+ }
+ if (r >= size) {
+ *pos = p;
+ return APR_SUCCESS;
+ }
+ }
+ else
+ i += nb;
+ }
+ }
+ }
+ else { /* find the hole in the bitmap */
+ for (i = 0; i < len; i++) {
+ if (__bit_mask[bmp[i]].hole >= (apr_byte_t)size) {
+ *pos = (i << 3) + __bit_mask[bmp[i]].pos;
+ return APR_SUCCESS;
+ }
+ else if (__bit_mask[bmp[i]].right +
+ __bit_mask[bmp[i + 1]].left >= (apr_byte_t)size) {
+ *pos = (i << 3) + 8 - __bit_mask[bmp[i]].right;
+ return APR_SUCCESS;
+ }
+ }
+ }
+ return APR_EOF;
+}
+
+static void asmm_bmp_set(apr_byte_t *bmp, apr_uint32_t from,
+ apr_uint32_t to)
+{
+ for (; from < to; from++)
+ _SET_BIT(bmp, from);
+}
+
+static void asmm_bmp_clr(apr_byte_t *bmp, apr_uint32_t from,
+ apr_uint32_t to)
+{
+ for (; from < to; from++)
+ _CLR_BIT(bmp, from);
+}
+
+
+/* In shared memory bitmap data */
+typedef struct asmm_shm_data_t asmm_shm_data_t;
+struct asmm_shm_data_t {
+ volatile apr_uint64_t timestamp;
+ volatile apr_uint16_t flags;
+ volatile apr_uint16_t nsections;
+ apr_uint32_t section;
+ apr_uint32_t blksize;
+ apr_uint32_t nblocks;
+ /* Followed by apr_byte_t[nblocks >> 3] */
+ /* Followed by apr_byte_t[nblocks * blksize] */
+};
+
+/* In memory wrapper over shared memory bitmaps */
+typedef struct asmm_mem_data_t asmm_mem_data_t;
+struct asmm_mem_data_t {
+ const char *name;
+ apr_shm_t *shm;
+ asmm_shm_data_t *hdr;
+ apr_byte_t *bitmap;
+ apr_byte_t *data;
+ asmm_mem_data_t *next;
+};
+
+/* In memory */
+struct asmm_slotmem_t {
+ volatile apr_uint64_t timestamp;
+ volatile apr_uint16_t nsections;
+ volatile apr_uint16_t flags;
+ apr_uint16_t maxsections;
+ apr_uint16_t pflags;
+ apr_uint32_t blksize;
+ apr_uint32_t nblocks;
+ apr_interval_time_t timeout;
+ const char *prefix;
+ asmm_mem_data_t *sections;
+ apr_global_mutex_t *lock;
+ apr_pool_t *pool;
+};
+
+/* Memory node header
+ * When refcount is zero only then the node
+ * can be deallocated
+ */
+typedef struct asmm_mem_node_t asmm_mem_node_t;
+struct asmm_mem_node_t {
+ volatile apr_uint32_t refcount;
+ apr_uint32_t size;
+ /* Followed by apr_byte_t[size * blksize] */
+};
+
+static apr_status_t slotmem_cleanup(asmm_slotmem_t *mem)
+{
+ asmm_mem_data_t *bmp = mem->sections;
+ apr_uint16_t clr = 0;
+
+ if (mem->maxsections)
+ clr = ASMM_DIRTY;
+
+ while (bmp) {
+ bmp->hdr->flags |= clr;
+ if (mem->pflags & ASMM_OWNER) {
+ apr_shm_destroy(bmp->shm);
+ apr_file_remove(bmp->name, NULL);
+ }
+ else {
+ apr_shm_detach(bmp->shm);
+ }
+ bmp = bmp->next;
+ }
+ mem->sections = NULL;
+ return APR_SUCCESS;
+}
+
+static apr_status_t create_bitmap_segment(asmm_mem_data_t **bmp,
+ apr_uint32_t blksize,
+ apr_uint32_t nblocks,
+ const char *name,
+ apr_pool_t *ctx)
+{
+ apr_size_t size;
+ apr_uint32_t bsa;
+ apr_uint32_t nba;
+ apr_uint32_t bba;
+ apr_byte_t *data;
+ apr_status_t rv;
+
+ *bmp = (asmm_mem_data_t *)apr_palloc(ctx, sizeof(asmm_mem_data_t));
+
+ /* Align everything to 8 bytes */
+ bsa = APR_ALIGN(blksize + sizeof(asmm_mem_node_t), 8);
+ nba = APR_ALIGN(nblocks, 8);
+ bba = APR_ALIGN(nblocks, 64);
+ size = sizeof(asmm_shm_data_t) + (bba >> 3) + nba * bsa;
+
+ apr_shm_remove(name, ctx);
+ if ((rv = apr_shm_create(&(*bmp)->shm, size, name, ctx)) != APR_SUCCESS)
+ return rv;
+
+ data = (apr_byte_t *)apr_shm_baseaddr_get((*bmp)->shm);
+
+ (*bmp)->hdr = (asmm_shm_data_t *)data;
+ (*bmp)->bitmap = data + sizeof(asmm_shm_data_t);
+ (*bmp)->data = (*bmp)->bitmap + (bba >> 3);
+ (*bmp)->next = NULL;
+ (*bmp)->name = apr_pstrdup(ctx, name);
+
+ /* Set bitmap to all free except alignment overflow */
+ memset((*bmp)->bitmap, 0xFF, bba >> 3);
+ memset((*bmp)->bitmap, 0, nba >> 3);
+ memset((*bmp)->data, 0, nba * bsa);
+
+ (*bmp)->hdr->blksize = bsa;
+ (*bmp)->hdr->nblocks = nba;
+ (*bmp)->hdr->section = 0;
+ (*bmp)->hdr->nsections = 0;
+ (*bmp)->hdr->flags = 0;
+ (*bmp)->hdr->timestamp = 0;
+ /* Ignore errors */
+ mm_unixd_set_shm_perms(name);
+
+ return APR_SUCCESS;
+}
+
+static void copy_bitmap_segment(asmm_mem_data_t *to,
+ asmm_mem_data_t *from)
+{
+
+ to->hdr->blksize = from->hdr->blksize;
+ to->hdr->nblocks = from->hdr->nblocks;
+ to->hdr->section = from->hdr->section;
+ to->hdr->nsections = from->hdr->nsections;
+ to->hdr->flags = from->hdr->flags;
+ /* Copy bitmap */
+ memcpy(to->bitmap, from->bitmap, from->hdr->nblocks >> 3);
+ /* Copy data */
+ memcpy(to->data, from->data, from->hdr->nblocks *
from->hdr->blksize);
+}
+
+
+static apr_status_t open_bitmap_segment(asmm_mem_data_t **bmp,
+ const char *name,
+ apr_pool_t *ctx)
+{
+ apr_byte_t *data;
+ apr_status_t rv;
+
+ apr_shm_t *shm = NULL;
+
+ if ((rv = apr_shm_attach(&shm, name, ctx)) != APR_SUCCESS) {
+ *bmp = NULL;
+ return rv;
+ }
+ *bmp = (asmm_mem_data_t *)apr_palloc(ctx, sizeof(asmm_mem_data_t));
+ data = (apr_byte_t *)apr_shm_baseaddr_get(shm);
+
+ (*bmp)->shm = shm;
+ (*bmp)->hdr = (asmm_shm_data_t *)data;
+ (*bmp)->bitmap = data + sizeof(asmm_shm_data_t);
+ (*bmp)->data = (*bmp)->bitmap + (APR_ALIGN((*bmp)->hdr->nblocks, 64)
>> 3);
+ (*bmp)->next = NULL;
+ (*bmp)->name = apr_pstrdup(ctx, name);
+
+ if ((*bmp)->hdr->flags & ASMM_DIRTY) {
+ /* Memory is dirty probably already closed by parent */
+ apr_shm_destroy(shm);
+ *bmp = NULL;
+ return APR_EBADF;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t new_slotmem_segment(asmm_slotmem_t *mem)
+{
+ apr_status_t rv;
+ asmm_mem_data_t *bmp, *p;
+ char sname[APR_PATH_MAX];
+
+ if (mem->nsections + 1 > mem->maxsections)
+ return APR_EOF;
+ sprintf(sname, "%s.%03d", mem->prefix, mem->nsections);
+
+ if ((rv = create_bitmap_segment(&bmp, mem->blksize,
+ mem->nblocks, sname,
+ mem->pool)) != APR_SUCCESS)
+ return rv;
+ bmp->hdr->section = mem->nsections++;
+ bmp->hdr->flags = mem->flags;
+ bmp->hdr->timestamp = apr_time_now();
+ if (mem->timestamp == bmp->hdr->timestamp) {
+ /* Make sure they are always different
+ */
+ bmp->hdr->timestamp++;
+ mem->timestamp = bmp->hdr->timestamp;
+ }
+ else
+ mem->timestamp = bmp->hdr->timestamp;
+ mem->sections->hdr->nsections = mem->nsections;
+ /* Put the segment to the end of list */
+ for (p = mem->sections; p; p = p->next) {
+ p->hdr->timestamp = mem->timestamp;
+ if (p->next == NULL) {
+ p->next = bmp;
+ break;
+ }
+ }
+ return rv;
+}
+
+static apr_status_t add_slotmem_segment(asmm_slotmem_t *mem)
+{
+ apr_status_t rv;
+ apr_uint16_t n;
+ asmm_mem_data_t *bmp = NULL;
+ asmm_mem_data_t *p = NULL;
+ char sname[APR_PATH_MAX];
+
+ for (n = mem->nsections; n < mem->sections->hdr->nsections; n++) {
+ sprintf(sname, "%s.%03d", mem->prefix, n);
+ if ((rv = open_bitmap_segment(&bmp, sname, mem->pool)) != APR_SUCCESS)
+ return rv;
+ mem->timestamp = bmp->hdr->timestamp;
+ mem->nsections++;
+ if (p && p->next == NULL) {
+ p->next = bmp;
+ p = bmp;
+ continue;
+ }
+ /* Put the segment to the end of list */
+ for (p = mem->sections; p; p = p->next) {
+ if (p->next == NULL) {
+ p->next = bmp;
+ break;
+ }
+ }
+ }
+ return rv;
+}
+
+apr_status_t asmm_slotmem_create(asmm_slotmem_t **mem,
+ const char *name,
+ apr_uint32_t blksize,
+ apr_uint32_t nblocks,
+ apr_uint16_t flags,
+ apr_uint16_t maxsections,
+ apr_pool_t *ctx)
+{
+ apr_status_t rv;
+ asmm_mem_data_t *bmp;
+ char sname[APR_PATH_MAX];
+
+ strcpy(sname, name);
+ strcat(sname, ".000");
+ if ((rv = create_bitmap_segment(&bmp, blksize,
+ nblocks, sname, ctx)) != APR_SUCCESS) {
+ *mem = NULL;
+ return rv;
+ }
+ *mem = (asmm_slotmem_t *)apr_palloc(ctx, sizeof(asmm_slotmem_t));
+ (*mem)->prefix = apr_pstrdup(ctx, name);
+ (*mem)->blksize = bmp->hdr->blksize;
+ (*mem)->nblocks = bmp->hdr->nblocks;
+ (*mem)->nsections = bmp->hdr->nsections = 1;
+ (*mem)->flags = bmp->hdr->flags = flags;
+ (*mem)->timestamp = bmp->hdr->timestamp = apr_time_now();
+ (*mem)->maxsections = maxsections;
+ (*mem)->pool = ctx;
+ (*mem)->sections = bmp;
+ (*mem)->timeout = ASMM_WAIT_INTERVAL * ASMM_WAIT_LOOPS;
+ (*mem)->pflags = ASMM_OWNER;
+ (*mem)->lock = NULL;
+
+ return rv;
+}
+
+apr_status_t asmm_slotmem_close(asmm_slotmem_t *mem)
+{
+ if (mem)
+ return slotmem_cleanup(mem);
+ else
+ return APR_EINVAL;
+}
+
+apr_status_t asmm_slotmem_open(asmm_slotmem_t **mem, const char *name,
+ apr_pool_t *ctx)
+{
+ apr_uint32_t i;
+ apr_status_t rv;
+ asmm_mem_data_t *bmp;
+ char sname[APR_PATH_MAX];
+
+ strcpy(sname, name);
+ strcat(sname, ".000");
+ if ((rv = open_bitmap_segment(&bmp, sname, ctx)) != APR_SUCCESS) {
+ *mem = NULL;
+ return rv;
+ }
+ *mem = (asmm_slotmem_t *)apr_palloc(ctx, sizeof(asmm_slotmem_t));
+ (*mem)->prefix = apr_pstrdup(ctx, name);
+ (*mem)->blksize = bmp->hdr->blksize;
+ (*mem)->nblocks = bmp->hdr->nblocks;
+ (*mem)->nsections = bmp->hdr->nsections;
+ (*mem)->timestamp = bmp->hdr->timestamp;
+ (*mem)->maxsections = 0;
+ (*mem)->pool = ctx;
+ (*mem)->sections = bmp;
+ (*mem)->timeout = ASMM_WAIT_INTERVAL * ASMM_WAIT_LOOPS;
+ (*mem)->pflags = 0;
+ (*mem)->lock = NULL;
+
+ for (i = 1; i < (*mem)->nsections; i++) {
+ asmm_mem_data_t *sec;
+ sprintf(sname, "%s.%03d", name, i);
+ if ((rv = open_bitmap_segment(&sec, sname, ctx)) == APR_SUCCESS) {
+ bmp->next = sec;
+ bmp = sec;
+ }
+ else {
+ /* One of the segments is missing? */
+ slotmem_cleanup(*mem);
+ *mem = NULL;
+ return APR_EBADF;
+ }
+ }
+ return rv;
+}
+
+apr_status_t asmm_slotmem_copy(asmm_slotmem_t **mem, asmm_slotmem_t *org,
+ const char *name, apr_pool_t *ctx)
+{
+ apr_uint32_t i = 1;
+ apr_status_t rv;
+ asmm_mem_data_t *bmp;
+ asmm_mem_data_t *sec;
+ asmm_mem_data_t *ptr = org->sections;
+ char sname[APR_PATH_MAX];
+
+ strcpy(sname, name);
+ strcat(sname, ".000");
+ if ((rv = create_bitmap_segment(&bmp, ptr->hdr->blksize,
+ ptr->hdr->nblocks,
+ sname, ctx)) != APR_SUCCESS) {
+ *mem = NULL;
+ return rv;
+ }
+ copy_bitmap_segment(bmp, org->sections);
+ *mem = (asmm_slotmem_t *)apr_palloc(ctx, sizeof(asmm_slotmem_t));
+ (*mem)->prefix = name;
+ (*mem)->blksize = bmp->hdr->blksize;
+ (*mem)->nblocks = bmp->hdr->nblocks;
+ (*mem)->timestamp = bmp->hdr->timestamp;
+ (*mem)->nsections = org->nsections;
+ (*mem)->maxsections = org->maxsections;
+ (*mem)->pool = ctx;
+ (*mem)->sections = bmp;
+ (*mem)->timeout = org->timeout;
+ (*mem)->pflags = ASMM_OWNER;
+ (*mem)->lock = NULL;
+
+ ptr = ptr->next;
+ while (ptr) {
+ sprintf(sname, "%s.%03d", name, i);
+ if ((rv = create_bitmap_segment(&sec, (*mem)->blksize,
+ (*mem)->nblocks, sname,
+ (*mem)->pool)) != APR_SUCCESS) {
+ /* One of the segments cannot be created */
+ slotmem_cleanup(*mem);
+ *mem = NULL;
+ return APR_EBADF;
+ }
+ copy_bitmap_segment(sec, ptr);
+ bmp->next = sec;
+ bmp = sec;
+ ptr = ptr->next;
+ }
+ return rv;
+}
+
+void asmm_slotmem_lock_set(asmm_slotmem_t *mem,
+ apr_global_mutex_t *lock)
+{
+ mem->lock = lock;
+}
+
+void asmm_slotmem_timeout_set(asmm_slotmem_t *mem,
+ apr_interval_time_t timeout)
+{
+ mem->timeout = timeout;
+}
+
+apr_global_mutex_t *asmm_slotmem_lock_get(asmm_slotmem_t *mem)
+{
+ return mem->lock;
+}
+
+apr_status_t asmm_slotmem_lock(asmm_slotmem_t *mem)
+{
+ if (mem->lock)
+ return apr_global_mutex_lock(mem->lock);
+ else
+ return APR_SUCCESS;
+}
+
+apr_status_t asmm_slotmem_unlock(asmm_slotmem_t *mem)
+{
+ if (mem->lock)
+ return apr_global_mutex_unlock(mem->lock);
+ else
+ return APR_SUCCESS;
+}
+
+apr_status_t asmm_slotmem_maintain(asmm_slotmem_t *mem)
+{
+ apr_status_t rv = APR_SUCCESS;
+ if (mem && mem->sections->hdr->flags & ASMM_NEW_SECTION) {
+ if (mem->lock)
+ (void)apr_global_mutex_lock(mem->lock);
+ rv = new_slotmem_segment(mem);
+ mem->sections->hdr->flags &= ~ASMM_NEW_SECTION;
+ if (mem->lock)
+ (void)apr_global_mutex_unlock(mem->lock);
+ }
+ return rv;
+}
+
+void *asmm_malloc(asmm_slotmem_t *mem, apr_size_t size)
+{
+ apr_status_t rv;
+ apr_size_t sza;
+ apr_uint32_t n, p;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ if ((bmp->hdr->flags & ASMM_DYNAMIC) != ASMM_DYNAMIC) {
+ apr_set_os_error(APR_EINVAL);
+ return NULL;
+ }
+
+ sza = APR_ALIGN(size + sizeof(asmm_mem_node_t), mem->blksize);
+ n = sza / mem->blksize;
+ if (n > mem->nblocks) {
+ /* Segment overflow.
+ * Adjust the memory so that largest
+ * alloc size can fit inside a single Segment
+ */
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ _ASMM_LOCK(mem);
+ while (bmp) {
+ if (asmm_bmp_find(bmp->bitmap, bmp->hdr->nblocks,
+ n, &p) == APR_SUCCESS) {
+ data = bmp->data + p * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ node->refcount = 0;
+ node->size = n;
+ asmm_bmp_set(bmp->bitmap, p, p + n);
+ break;
+ }
+ bmp = bmp->next;
+ }
+ if (data) {
+ /* Slotmem is modified */
+ mem->timestamp = apr_time_now();
+ while (bmp) {
+ bmp->hdr->timestamp = mem->timestamp;
+ bmp = bmp->next;
+ }
+ }
+ _ASMM_UNLOCK(mem);
+ if (data) {
+ return data + sizeof(asmm_mem_node_t);
+ }
+ else {
+ if (!mem->maxsections) {
+ apr_interval_time_t i;
+ /* Add new segment request
+ */
+ mem->sections->hdr->flags |= ASMM_NEW_SECTION;
+ /* TODO: Wait for flag to be cleared
+ * and then try again.
+ * This is 1000 * 10ms maximum delay (10 sec)
+ */
+ for (i = 0; i < mem->timeout; i += ASMM_WAIT_INTERVAL) {
+ apr_sleep(ASMM_WAIT_INTERVAL);
+ if (mem->sections->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ if ((mem->sections->hdr->flags & ASMM_NEW_SECTION) !=
+ ASMM_NEW_SECTION) {
+ _ASMM_LOCK(mem);
+ add_slotmem_segment(mem);
+ _ASMM_UNLOCK(mem);
+ break;
+ }
+ }
+ if (mem->sections->hdr->flags & ASMM_NEW_SECTION) {
+ apr_set_os_error(APR_TIMEUP);
+ return NULL;
+ }
+ }
+ else if (mem->nsections + 1 > mem->maxsections) {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ else {
+ _ASMM_LOCK(mem);
+ if ((rv = new_slotmem_segment(mem)) != APR_SUCCESS) {
+ _ASMM_UNLOCK(mem);
+ apr_set_os_error(rv);
+ return NULL;
+ }
+ mem->sections->hdr->flags &= ~ASMM_NEW_SECTION;
+ _ASMM_UNLOCK(mem);
+ }
+ _ASMM_LOCK(mem);
+ bmp = mem->sections;
+ while (bmp) {
+ if (asmm_bmp_find(bmp->bitmap, bmp->hdr->nblocks,
+ n, &p) == APR_SUCCESS) {
+ data = bmp->data + p * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ node->refcount = 0;
+ node->size = n;
+ asmm_bmp_set(bmp->bitmap, p, p + n);
+ break;
+ }
+ bmp = bmp->next;
+ }
+ _ASMM_UNLOCK(mem);
+ if (data) {
+ return data + sizeof(asmm_mem_node_t);
+ }
+ else {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ }
+}
+
+void *asmm_salloc_ex(asmm_slotmem_t *mem, apr_uint32_t *slot)
+{
+ apr_status_t rv;
+ apr_uint32_t p;
+ apr_uint32_t sn = 1;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ _ASMM_LOCK(mem);
+
+ while (bmp) {
+ if (asmm_bmp_get(bmp->bitmap, bmp->hdr->nblocks,
+ &p) == APR_SUCCESS) {
+ data = bmp->data + p * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->refcount == ASMM_DEAD_COOKIE) {
+ /* Clear old memory */
+ memset(data, 0, bmp->hdr->blksize);
+ }
+ node->size = 1;
+ asmm_bmp_set(bmp->bitmap, p, p + 1);
+ *slot = p * sn;
+ break;
+ }
+ sn++;
+ bmp = bmp->next;
+ }
+ if (data) {
+ /* Slotmem is modified */
+ mem->timestamp = apr_time_now();
+ while (bmp) {
+ bmp->hdr->timestamp = mem->timestamp;
+ bmp = bmp->next;
+ }
+ }
+ _ASMM_UNLOCK(mem);
+ if (data) {
+ return data + sizeof(asmm_mem_node_t);
+ }
+ else {
+ if (!mem->maxsections) {
+ apr_interval_time_t i;
+ /* Add new segment request
+ */
+ mem->sections->hdr->flags |= ASMM_NEW_SECTION;
+ /* TODO: Wait for flag to be cleared
+ * and then try again.
+ * This is 1000 * 10ms maximum delay (10 sec)
+ */
+ for (i = 0; i < mem->timeout; i += ASMM_WAIT_INTERVAL) {
+ apr_sleep(ASMM_WAIT_INTERVAL);
+ if (mem->sections->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ if ((mem->sections->hdr->flags & ASMM_NEW_SECTION) !=
+ ASMM_NEW_SECTION) {
+ _ASMM_LOCK(mem);
+ add_slotmem_segment(mem);
+ _ASMM_UNLOCK(mem);
+ break;
+ }
+ }
+ if (mem->sections->hdr->flags & ASMM_NEW_SECTION) {
+ apr_set_os_error(APR_TIMEUP);
+ return NULL;
+ }
+ }
+ else if (mem->nsections + 1 > mem->maxsections) {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ else {
+ _ASMM_LOCK(mem);
+ if ((rv = new_slotmem_segment(mem)) != APR_SUCCESS) {
+ _ASMM_UNLOCK(mem);
+ apr_set_os_error(rv);
+ return NULL;
+ }
+ mem->sections->hdr->flags &= ~ASMM_NEW_SECTION;
+ _ASMM_UNLOCK(mem);
+ }
+ sn = 1;
+ _ASMM_LOCK(mem);
+ bmp = mem->sections;
+ while (bmp) {
+ if (asmm_bmp_get(bmp->bitmap, bmp->hdr->nblocks,
+ &p) == APR_SUCCESS) {
+ data = bmp->data + p * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->refcount == ASMM_DEAD_COOKIE) {
+ /* Clear old memory */
+ memset(data, 0, bmp->hdr->blksize);
+ }
+ node->size = 1;
+ asmm_bmp_set(bmp->bitmap, p, p + 1);
+ *slot = p * sn;
+ break;
+ }
+ sn++;
+ bmp = bmp->next;
+ }
+ _ASMM_UNLOCK(mem);
+ if (data) {
+ return data + sizeof(asmm_mem_node_t);
+ }
+ else {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ }
+}
+
+void *asmm_salloc(asmm_slotmem_t *mem)
+{
+ apr_uint32_t unused;
+ return asmm_salloc_ex(mem, &unused);
+}
+
+void asmm_free(asmm_slotmem_t *mem, void *p)
+{
+ apr_byte_t *data;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return;
+ }
+
+ data = (apr_byte_t *)p - sizeof(asmm_mem_node_t);
+ node = (asmm_mem_node_t *)data;
+ if (node->refcount) {
+ /* memory is still referenced */
+ if (node->refcount != ASMM_DEAD_COOKIE) {
+ node->refcount--;
+ apr_set_os_error(APR_EBUSY);
+ }
+ else
+ apr_set_os_error(APR_ENOENT);
+ return;
+ }
+ _ASMM_VLOCK(mem);
+ while (bmp) {
+ if (data >= bmp->data &&
+ data < bmp->data + bmp->hdr->blksize * bmp->hdr->nblocks)
{
+ apr_uint32_t pos = (data - bmp->data) / bmp->hdr->blksize;
+ asmm_bmp_clr(bmp->bitmap, pos, pos + node->size);
+ node->size = 0;
+ node->refcount = ASMM_DEAD_COOKIE;
+ break;
+ }
+ bmp = bmp->next;
+ }
+ /* Slotmem is modified */
+ mem->timestamp = apr_time_now();
+ while (bmp) {
+ bmp->hdr->timestamp = mem->timestamp;
+ bmp = bmp->next;
+ }
+ _ASMM_UNLOCK(mem);
+}
+
+void asmm_memref(void *p, int on)
+{
+ apr_byte_t *data = (apr_byte_t *)p;
+ asmm_mem_node_t *node;
+
+ node = (asmm_mem_node_t *)(data - sizeof(asmm_mem_node_t));
+ if (node->refcount != ASMM_DEAD_COOKIE) {
+ if (on)
+ node->refcount++;
+ else if (node->refcount)
+ node->refcount--;
+ }
+}
+
+int asmm_memsize(void *p)
+{
+ apr_byte_t *data = (apr_byte_t *)p;
+ asmm_mem_node_t *node;
+
+ node = (asmm_mem_node_t *)(data - sizeof(asmm_mem_node_t));
+ if (node->refcount != ASMM_DEAD_COOKIE)
+ return node->size;
+ else
+ return 0;
+}
+
+void *asmm_slot(asmm_slotmem_t *mem, apr_uint32_t slot)
+{
+ apr_uint32_t section = 1;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp;
+
+ if (!mem) {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ bmp = mem->sections;
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ if (slot < section * bmp->hdr->nblocks) {
+ data = bmp->data + (slot - (section - 1) * bmp->hdr->nblocks) *
bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size)
+ return data + sizeof(asmm_mem_node_t);
+ else {
+ apr_set_os_error(APR_EINIT);
+ return NULL;
+ }
+ }
+ bmp = bmp->next;
+ section++;
+ }
+ apr_set_os_error(APR_ESYMNOTFOUND);
+ return NULL;
+}
+
+void *asmm_slot_next(asmm_slotmem_t *mem, apr_uint32_t *next)
+{
+ apr_uint32_t i, section = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ for (i = *next - section * bmp->hdr->nblocks;
+ i < (section + 1) * bmp->hdr->nblocks; i++) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size) {
+ *next = i + 1 + section * bmp->hdr->nblocks;
+ return data + sizeof(asmm_mem_node_t);
+ }
+ }
+ bmp = bmp->next;
+ section++;
+ }
+ apr_set_os_error(APR_EOF);
+ return NULL;
+}
+
+void *asmm_memory(asmm_slotmem_t *mem, apr_uint32_t index)
+{
+ apr_uint32_t i, idx = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks; idx++) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (idx == index)
+ break;
+ if (node->size)
+ i += node->size;
+ else
+ i++;
+ }
+ if (data)
+ break;
+ bmp = bmp->next;
+ }
+ if (data)
+ return data + sizeof(asmm_mem_node_t);
+ else {
+ apr_set_os_error(APR_ESYMNOTFOUND);
+ return NULL;
+ }
+}
+
+static void **create_slot_array(asmm_slotmem_t *mem, apr_size_t *size,
+ apr_pool_t *ctx)
+{
+
+ apr_uint32_t i, x = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+ void **a = NULL;
+
+ a = (void **)apr_pcalloc(ctx, sizeof(void *) *
+ (mem->nsections * bmp->hdr->nblocks + 1));
+
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks; i++, x++) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ a[x] = data + sizeof(asmm_mem_node_t);
+ }
+ bmp = bmp->next;
+ }
+ *size = x;
+ return a;
+}
+
+static void **create_memory_array(asmm_slotmem_t *mem, apr_size_t *size,
+ apr_pool_t *ctx)
+{
+
+ apr_uint32_t i, x = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp = mem->sections;
+ void **a = NULL;
+
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks;) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size) {
+ i += node->size;
+ x++;
+ }
+ else
+ i++;
+ }
+ bmp = bmp->next;
+ }
+ a = (void **)apr_pcalloc(ctx, sizeof(void *) * (x + 1));
+ bmp = mem->sections;
+ x = 0;
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks;) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size) {
+ i += node->size;
+ a[x++] = data + sizeof(asmm_mem_node_t);
+ }
+ else
+ i++;
+ }
+ bmp = bmp->next;
+ }
+ *size = x;
+ return a;
+}
+
+void **asmm_aalloc(asmm_slotmem_t *mem, apr_size_t *size, apr_pool_t *ctx)
+{
+ if (mem->flags & ASMM_DYNAMIC)
+ return create_memory_array(mem, size, ctx);
+ else
+ return create_slot_array(mem, size, ctx);
+}
+
+apr_uint32_t asmm_slotmem_free_get(asmm_slotmem_t *mem)
+{
+ apr_uint32_t cnt = 0;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return 0;
+ }
+ while (bmp) {
+ cnt += asmm_bmp_free(bmp->bitmap, bmp->hdr->nblocks);
+ bmp = bmp->next;
+ }
+ return cnt;
+}
+
+apr_uint32_t asmm_slotmem_used_get(asmm_slotmem_t *mem)
+{
+ apr_uint32_t num = 0, cnt = 0;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return 0;
+ }
+ while (bmp) {
+ num += bmp->hdr->nblocks;
+ cnt += asmm_bmp_free(bmp->bitmap, bmp->hdr->nblocks);
+ bmp = bmp->next;
+ }
+ return (num - cnt);
+}
+
+apr_size_t asmm_slotmem_overhead_get()
+{
+ return sizeof(asmm_mem_node_t);
+}
+
+apr_size_t asmm_slotmem_slotsize_get(asmm_slotmem_t *mem)
+{
+ if (mem->sections)
+ return mem->sections->hdr->blksize;
+ else
+ return 0;
+}
+
+int asmm_slotmem_is_modified(asmm_slotmem_t *mem)
+{
+ if (mem->sections && mem->sections->hdr->timestamp !=
mem->timestamp)
+ return 1;
+ else
+ return 0;
+}
+
+void asmm_slotmem_set_modified(asmm_slotmem_t *mem)
+{
+ asmm_mem_data_t *bmp = mem->sections;
+ apr_time_t now = apr_time_now();
+
+ while (bmp) {
+ bmp->hdr->timestamp = now;
+ bmp = bmp->next;
+ }
+ mem->timestamp = now;
+}
+
+void asmm_slotmem_sync_modified(asmm_slotmem_t *mem)
+{
+ if (mem->sections)
+ mem->timestamp = mem->sections->hdr->timestamp;
+}
+
+void asmm_slotmem_set_dirty(asmm_slotmem_t *mem)
+{
+ asmm_mem_data_t *bmp = mem->sections;
+
+ while (bmp) {
+ bmp->hdr->flags |= ASMM_DIRTY;
+ bmp = bmp->next;
+ }
+}
+
+void asmm_slotmem_clr_dirty(asmm_slotmem_t *mem)
+{
+ asmm_mem_data_t *bmp = mem->sections;
+
+ while (bmp) {
+ bmp->hdr->flags &= ~ASMM_DIRTY;
+ bmp = bmp->next;
+ }
+}
+
+void *asmm_slotmem_section_base_get(asmm_slotmem_t *mem, apr_uint32_t section)
+{
+ apr_uint32_t sn = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_data_t *bmp = mem->sections;
+
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ if (sn == section) {
+ return bmp->data;
+ }
+ bmp = bmp->next;
+ sn++;
+ }
+ apr_set_os_error(APR_ESYMNOTFOUND);
+ return NULL;
+}
+
+apr_uint32_t asmm_slotmem_sections_get(asmm_slotmem_t *mem)
+{
+ return mem->nsections;
+}
+
+void *asmm_slot_search(asmm_slotmem_t *mem,
+ const char *key, int icase,
+ apr_size_t key_offset,
+ apr_uint32_t *slot)
+{
+ apr_uint32_t i, section = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp;
+
+ if (!mem) {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ bmp = mem->sections;
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks; i++) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size) {
+ const char *s = data + sizeof(asmm_mem_node_t) + key_offset;
+ if (icase ? !strcasecmp(s, key) : !strcmp(s, key)) {
+ if (slot)
+ *slot = i + section * bmp->hdr->nblocks;
+ return data + sizeof(asmm_mem_node_t);
+ }
+ }
+ }
+ bmp = bmp->next;
+ section++;
+ }
+ apr_set_os_error(APR_EOF);
+ return NULL;
+}
+
+void *asmm_slot_match(asmm_slotmem_t *mem,
+ const char *key, int icase,
+ apr_size_t key_offset,
+ apr_uint32_t *slot)
+{
+ apr_uint32_t i, section = 0;
+ apr_byte_t *data = NULL;
+ asmm_mem_node_t *node;
+ asmm_mem_data_t *bmp;
+ int mf = icase ? APR_FNM_CASE_BLIND : 0;
+
+ if (!mem) {
+ apr_set_os_error(APR_ENOMEM);
+ return NULL;
+ }
+ bmp = mem->sections;
+ if (bmp && bmp->hdr->flags & ASMM_DIRTY) {
+ apr_set_os_error(APR_EBADF);
+ return NULL;
+ }
+ while (bmp) {
+ for (i = 0; i < bmp->hdr->nblocks; i++) {
+ data = bmp->data + i * bmp->hdr->blksize;
+ node = (asmm_mem_node_t *)data;
+ if (node->size) {
+ const char *s = data + sizeof(asmm_mem_node_t) + key_offset;
+ if (*s == '~' && apr_fnmatch(s + 1, key, mf) ==
APR_SUCCESS) {
+ if (slot)
+ *slot = i + section * bmp->hdr->nblocks;
+ return data + sizeof(asmm_mem_node_t);
+ }
+ }
+ }
+ bmp = bmp->next;
+ section++;
+ }
+ apr_set_os_error(APR_EOF);
+ return NULL;
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_asmm.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_asmm.h
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_asmm.h (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_asmm.h 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,361 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+#ifndef MM_ASMM_H
+#define MM_ASMM_H
+
+/**
+ * @file mm_asmm.h
+ * @brief Advanced shared memory
+ */
+/**
+ * @defgroup MM_ASMM shared memory routines
+ * @ingroup Manager
+ * @{
+ */
+
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_fnmatch.h"
+#include "apr_shm.h"
+#include "apr_time.h"
+#include "apr_global_mutex.h"
+#include "apr_thread_proc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ASMM_DYNAMIC 0x0001
+#define ASMM_NEW_SECTION 0x0002
+#define ASMM_DIRTY 0x0004
+#define ASMM_HAS_LOCK 0x0008
+#define ASMM_OWN_LOCK 0x0010
+#define ASMM_UNLIMITED 0xFFFF
+#define ASMM_OWNER 0x0001
+#define ASMM_WAIT_INTERVAL APR_TIME_C(10000)
+#define ASMM_WAIT_LOOPS 1000
+
+
+/**
+ * Structure for referencing slot memory.
+ */
+typedef struct asmm_slotmem_t asmm_slotmem_t;
+
+/**
+ * Create shared slot memory.
+ * @param mem The newly created slotmem descriptor.
+ * @param name The full path to the backup file prefix
+ * (using / on all systems)
+ * @param blksize Size of each slot (rounded to 8 bytes)
+ * @param nblocks Maximum number of slots (rounded to 8 slots)
+ * @param flags Or'ed value of:
+ * <PRE>
+ * ASMM_DYNAMIC allow large slots
+ * ASMM_HAS_LOCK create global lock mutex
+ * </PRE>
+ * @param maxsections Maximum number of sections that can
+ * be dynamically created. If 0 the memory is not
+ * resizable. For maximum allowable use ASMM_UNLIMITED.
+ * @param ctx The pool to use.
+ */
+apr_status_t asmm_slotmem_create(asmm_slotmem_t **mem,
+ const char *name,
+ apr_uint32_t blksize,
+ apr_uint32_t nblocks,
+ apr_uint16_t flags,
+ apr_uint16_t maxsections,
+ apr_pool_t *ctx);
+
+/**
+ * Close the specified slotmem.
+ * @param mem The slotmem descriptor to close.
+ * @remark If the slotmem descriptor is the one obrained
+ * by creating slotmem the attached shared memory
+ * will be marked as ASMM_DIRTY. Subsequent alloc
+ * requests will fail with APR_EBADF error.
+ */
+apr_status_t asmm_slotmem_close(asmm_slotmem_t *mem);
+
+/**
+ * Open shared slot memory.
+ * @param mem The opened slotmem descriptor.
+ * @param name The full path to the backup file prefix
+ * (using / on all systems). The same as used
+ * for asmm_create_slotmem.
+ * @param ctx The pool to use.
+ */
+apr_status_t asmm_slotmem_open(asmm_slotmem_t **mem, const char *name,
+ apr_pool_t *ctx);
+
+/**
+ * Copy shared memory.
+ * @param mem The newly created slotmem descriptor.
+ * @param org The slotmem to copy from.
+ * @param name The full path to the backup file prefix
+ * (using / on all systems)
+ * @param ctx The pool to use.
+ */
+apr_status_t asmm_slotmem_copy(asmm_slotmem_t **mem, asmm_slotmem_t *org,
+ const char *name, apr_pool_t *ctx);
+
+/**
+ * Set allocation timeout.
+ * @param mem The slotmem descriptor to set.
+ * @param timeout Timeout in microseconds.
+ * @remark When child tries to allocate the memory
+ * and cannot obtain enough free memory it sets
+ * the ASMM_NEW_SECTION flag and waits up to timeout
+ * for a new slotmem segment to be created by the parent.
+ * Default timeout value is 10 seconds.
+ */
+void asmm_slotmem_timeout_set(asmm_slotmem_t *mem,
+ apr_interval_time_t timeout);
+
+/**
+ * Set global lock mutex.
+ * @param mem The slotmem descriptor to set.
+ * @param lock Mutex to use.
+ */
+void asmm_slotmem_lock_set(asmm_slotmem_t *mem,
+ apr_global_mutex_t *lock);
+
+/**
+ * Get global lock mutex.
+ * @param mem The slotmem descriptor to get.
+ */
+apr_global_mutex_t *asmm_slotmem_lock_get(asmm_slotmem_t *mem);
+
+/**
+ * Lock the slotmem.
+ * @param mem The slotmem descriptor to lock.
+ */
+apr_status_t asmm_slotmem_lock(asmm_slotmem_t *mem);
+
+/**
+ * Unlock previously locked slotmem.
+ * @param mem The slotmem descriptor to unlock.
+ */
+apr_status_t asmm_slotmem_unlock(asmm_slotmem_t *mem);
+
+/**
+ * Maintain slotmem.
+ * @param mem The slotmem descriptor to use.
+ * @remark Function will add new slotmem segment if
+ * ASMM_NEW_SECTION flag was set
+ */
+apr_status_t asmm_slotmem_maintain(asmm_slotmem_t *mem);
+
+/**
+ * Allocate memory.
+ * @param mem The slotmem descriptor to allocate from.
+ * @param size The memory size to allocate.
+ * @remark The memory must be created with ASMM_DYNAMIC flag
+ * or this call will return NULL and set errno to APR_EINVAL
+ *
+ * @remark If the memory was closed by creator the
+ * return value is NULL errno is set to APR_EBADF
+ *
+ * @remark If there was not enough free memory to satisfy the
+ * requested size the call will wait up to timeout
+ * microseconds for creator to create a new memory segment.
+ * If creator fails to do that within timeout the return
+ * value is NULL and errno is set to APR_TIMEUP.
+ */
+void *asmm_malloc(asmm_slotmem_t *mem, apr_size_t size);
+
+
+/**
+ * Allocate one memory slot
+ * @param mem The slotmem descriptor to allocate from.
+ * @param slot The slot number allocated.
+ * @remark If the memory was closed by creator the
+ * return value is NULL errno is set to APR_EBADF
+ *
+ * @remark If there was not enough free memory for a slot
+ * the call will wait up to timeout
+ * microseconds for creator to create a new memory segment.
+ * If creator fails to do that within timeout the return
+ * value is NULL and errno is set to APR_TIMEUP.
+ */
+void *asmm_salloc_ex(asmm_slotmem_t *mem, apr_uint32_t *slot);
+
+/**
+ * Allocate one memory slot
+ * @param mem The slotmem descriptor to allocate from.
+ * @remark If the memory was closed by creator the
+ * return value is NULL errno is set to APR_EBADF
+ *
+ * @remark If there was not enough free memory for a slot
+ * the call will wait up to timeout
+ * microseconds for creator to create a new memory segment.
+ * If creator fails to do that within timeout the return
+ * value is NULL and errno is set to APR_TIMEUP.
+ */
+void *asmm_salloc(asmm_slotmem_t *mem);
+
+/**
+ * Deallocate previously allocated memory
+ * @param mem The slotmem descriptor to use.
+ * @param p Memory previously allocated by calling asmm_malloc
+ * or asmm_salloc.
+ * @remark Memory will be actually deallocated when its reference
+ * count is zero
+ */
+void asmm_free(asmm_slotmem_t *mem, void *p);
+
+/**
+ * Reference or derefrence allocated memory.
+ * @param p Memory previously allocated by calling asmm_malloc
+ * or asmm_salloc.
+ * @param on If non zero reference the memory. If zero dereference
+ * the memory
+ */
+void asmm_memref(void *p, int on);
+
+/**
+ * Return the memory slot size in number of slots
+ * @param p Memory previously allocated by calling asmm_malloc
+ * or asmm_salloc.
+ * @remark If memory was deallocated the returned size is 0
+ */
+int asmm_memsize(void *p);
+
+/**
+ * Get memory slot address
+ * @param mem The slotmem descriptor to use.
+ * @param slot Slot number
+ */
+void *asmm_slot(asmm_slotmem_t *mem, apr_uint32_t slot);
+
+/**
+ * Get next memory slot address
+ * @param mem The slotmem descriptor to use.
+ * @param next Start/next slot number.
+ * @remark On return next points to slot number + 1.
+ */
+void *asmm_slot_next(asmm_slotmem_t *mem, apr_uint32_t *next);
+
+/**
+ * Search for memory slot address
+ * @param mem The slotmem descriptor to use.
+ * @param key The memory key to find.
+ * @param icase Case insensitive searc if non zero.
+ * @param key_off Key offset in allocated memory.
+ * @param slot On success the slot number.
+ */
+void *asmm_slot_search(asmm_slotmem_t *mem, const char *key,
+ int icase,
+ apr_size_t key_offset,
+ apr_uint32_t *slot);
+
+/**
+ * Get memory address
+ * @param mem The slotmem descriptor to use.
+ * @param index Allocated memory index
+ */
+void *asmm_memory(asmm_slotmem_t *mem, apr_uint32_t index);
+
+/**
+ * Create array of allocated memory slots
+ * @param mem The slotmem descriptor to use.
+ * @param size Return array size
+ * @param ctx Pool to allocate from
+ * @remark Each item of the returned array points to
+ * to the allocated memory slot.
+ */
+void **asmm_aalloc(asmm_slotmem_t *mem, apr_size_t *size, apr_pool_t *ctx);
+
+/**
+ * Return number of free blocks.
+ * @param mem The slotmem descriptor to use.
+ */
+apr_uint32_t asmm_slotmem_free_get(asmm_slotmem_t *mem);
+
+/**
+ * Return number of used blocks.
+ * @param mem The slotmem descriptor to use.
+ */
+apr_uint32_t asmm_slotmem_used_get(asmm_slotmem_t *mem);
+
+/**
+ * Return the overhead for each slot in slotmem.
+ */
+apr_size_t asmm_slotmem_overhead_get();
+
+/**
+ * Return the size of each slot
+ * @param mem The slotmem descriptor to use.
+ */
+apr_uint32_t asmm_slotmem_slotsize_get(asmm_slotmem_t *mem);
+
+/**
+ * Return the section base address
+ * @param mem The slotmem descriptor to use.
+ * @param section Section number.
+ */
+void *asmm_slotmem_section_base_get(asmm_slotmem_t *mem, apr_uint32_t section);
+
+/**
+ * Return non zero if shared memory is modified
+ * @param mem The slotmem descriptor to use.
+ * @remark Function compares in-memory with shared memory timestamps
+ * and returns non zero if they are different.
+ */
+int asmm_slotmem_is_modified(asmm_slotmem_t *mem);
+
+/**
+ * Synchronise and set shared memory modification timestamps
+ * @param mem The slotmem descriptor to use.
+ */
+void asmm_slotmem_set_modified(asmm_slotmem_t *mem);
+
+/**
+ * Synchronise shared memory modification timestamps
+ * @param mem The slotmem descriptor to use.
+ */
+void asmm_slotmem_sync_modified(asmm_slotmem_t *mem);
+
+/**
+ * Return the number of sections
+ * @param mem The slotmem descriptor to use.
+ */
+apr_uint32_t asmm_slotmem_sections_get(asmm_slotmem_t *mem);
+
+/**
+ * Set unix security permissions.
+ * @param fname Shared memory name.
+ */
+apr_status_t mm_unixd_set_shm_perms(const char *fname);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* MM_ASMM_H */
Property changes on: sandbox/aloha/httpd/modules/manager/mm_asmm.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_balancer.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_balancer.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_balancer.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,552 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Balancer object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+
+static const char *balancer_params[] = {
+ "",
+ "Status",
+ "StickySession",
+ "StickySessionCookie",
+ "StickySessionPath",
+ "StickySessionRemove",
+ "StickySessionForce",
+ "TimeOut",
+ "MaxFailoverAttempts",
+ "AbortIfHeadersSend",
+ "AbortIfResponseReceived",
+ "InterstageMethod",
+ NULL
+};
+
+static const char *bal_get_method_name(mm_balance_method_e method)
+{
+ switch(method) {
+ case mm_balance_r:
+ return "R";
+ break;
+ case mm_balance_b:
+ return "B";
+ break;
+ }
+ return "-";
+}
+
+static mm_balance_method_e bal_get_method(const char *method)
+{
+ switch(apr_toupper(*method)) {
+ case 'R':
+ return mm_balance_r;
+ break;
+ case 'B':
+ return mm_balance_r;
+ break;
+ }
+ return mm_balance_undef;
+}
+
+static void rdo_balancer_info_print(int pi, int pp,
+ mmdb_balancer_t *bal,
+ request_rec *r)
+{
+ if (pp) {
+ ap_rvputs(r, balancer_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* Status */
+ ap_rputs(mm_state_name_get(bal->status), r);
+ break;
+ case 2: /* StickySession */
+ ap_rputs(MM_STR_ONOFF(bal->sticky_session), r);
+ break;
+ case 3: /* StickySessionCookie */
+ ap_rvputs(r, bal->sticky_session_cookie, NULL);
+ break;
+ case 4: /* StickySessionPath */
+ MM_MAYBEQ_RPUTS(r, pp, bal->sticky_session_path);
+ break;
+ case 5: /* StickySessionRemove */
+ ap_rputs(MM_STR_ONOFF(bal->sticky_session_remove), r);
+ break;
+ case 6: /* StickySessionForce */
+ ap_rputs(MM_STR_ONOFF(bal->sticky_session_force), r);
+ break;
+ case 7: /* TimeOut */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
apr_time_as_msec(bal->timeout));
+ break;
+ case 8: /* MaxFailoverAttempts */
+ ap_rprintf(r, "%d", bal->retries);
+ break;
+ case 9: /* AbortIfHeadersSend */
+ ap_rputs(MM_STR_ONOFF(bal->abort_if_headers_send), r);
+ break;
+ case 10: /* AbortIfResponseReceived */
+ ap_rputs(MM_STR_ONOFF(bal->abort_if_response_get), r);
+ break;
+ case 11: /* InterstageMethod */
+ ap_rputs(bal_get_method_name(bal->method), r);
+ break;
+ }
+}
+
+/* Dump Balancer info */
+static void rdo_balancer_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_balancer_t *bal,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (balancer_params[j]) {
+ if (apr_fnmatch(ce[i].key, balancer_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (balancer_params[j]) {
+ if (!strcasecmp(ce[i].key, balancer_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_balancer_info_print(m, wcm, bal, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (balancer_params[j]) {
+ if (apr_fnmatch(ce[i].key, balancer_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_balancer_info_print(j, 1, bal, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (balancer_params[j]) {
+ if (!strcasecmp(ce[i].key, balancer_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_balancer_info_print(j, 1, bal, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static int balancer_exist(const char *value, mmdb_balancer_t **bp)
+{
+ apr_uint32_t next = 0;
+ mmdb_balancer_t *balancer;
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ while ((balancer = asmm_slot_next(balancer_db, &next))) {
+ if (strcasecmp(value, balancer->name))
+ continue;
+ *bp = balancer;
+ return 1;
+ }
+ return 0;
+}
+
+static apr_status_t rdo_balancer_config_do(int pi,
+ const char *value,
+ mmdb_balancer_t *bal,
+ request_rec *r)
+{
+ switch (pi) {
+ case 1: /* Status */
+ bal->status = mm_state_get(value);
+ break;
+ case 2: /* StickySession */
+ bal->sticky_session = MM_VAL_ONOFF(value);
+ break;
+ case 3: /* StickySessionCookie */
+ MM_SSAFE_COPY(bal->sticky_session_cookie, value);
+ break;
+ case 4: /* StickySessionPath */
+ MM_SSAFE_COPY(bal->sticky_session_path, value);
+ break;
+ case 5: /* StickySessionRemove */
+ bal->sticky_session_remove = MM_VAL_ONOFF(value);
+ break;
+ case 6: /* StickySessionForce */
+ bal->sticky_session_force = MM_VAL_ONOFF(value);
+ break;
+ case 7: /* TimeOut */
+ bal->timeout = APR_TIME_C(1000) * atoi(value);
+ break;
+ case 8: /* MaxFailoverAttempts */
+ bal->retries = atoi(value);
+ break;
+ case 9: /* AbortIfHeadersSend */
+ bal->abort_if_headers_send = MM_VAL_ONOFF(value);
+ break;
+ case 10: /* AbortIfResponseReceived */
+ bal->abort_if_response_get = MM_VAL_ONOFF(value);
+ break;
+ case 11: /* InterstageMethod */
+ bal->method= bal_get_method(value);
+ break;
+ }
+ return 0;
+}
+
+/* Configure Balancer */
+static int rdo_balancer_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ apr_uint32_t balancer_id,
+ mmdb_balancer_t *balancer,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (balancer_params[j]) {
+ if (!strcasecmp(ce[i].key, balancer_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_balancer_config_do(j, ce[i].val,
+ balancer, r))) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static void rdo_balancer_delete(apr_uint32_t balancer_id)
+{
+ apr_uint32_t next = 0;
+ mmdb_balancer_t *balancer;
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ while ((balancer = asmm_slot_next(balancer_db, &next))) {
+ if ((next - 1) == balancer_id) {
+ asmm_free(balancer_db, balancer);
+ break;
+ }
+ }
+}
+
+static apr_status_t create_balancer(mm_server_conf_t *cfg,
+ const char *name,
+ asmm_slotmem_t *balancer_db,
+ mmdb_balancer_t **balancer,
+ apr_uint32_t *balancer_id)
+{
+ /* Create _default_ balancer */
+ if (!(*balancer = asmm_salloc_ex(balancer_db, balancer_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY((*balancer)->name, name);
+ MM_SSAFE_COPY((*balancer)->sticky_session_cookie, MM_DEF_SESSION_C);
+ MM_SSAFE_COPY((*balancer)->sticky_session_path, MM_DEF_SESSION_P);
+ (*balancer)->sticky_session = 1;
+ (*balancer)->sticky_session_remove = 0;
+ (*balancer)->sticky_session_force = 0;
+ (*balancer)->abort_if_headers_send = 0;
+ (*balancer)->abort_if_response_get = 0;
+ (*balancer)->method = mm_balance_r;
+ (*balancer)->retries = 0; /* Unlimited */
+ (*balancer)->timeout = cfg->main_server->timeout;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_balancer(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int wcm;
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+ apr_uint32_t next = 0;
+ mmdb_balancer_t *balancer;
+
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ if (!balancer_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+#if MM_FORCE_DEFAULT_NAME_REQ
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty balancer name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+#else
+ name = MM_DEFAULT_NAME;
+#endif
+ }
+ wcm = apr_fnmatch_test(name);
+ while ((balancer = asmm_slot_next(balancer_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, balancer->name,
+ MM_FFNMATCH) != APR_SUCCESS)
+ continue;
+ }
+ else if (strcasecmp(name, balancer->name))
+ continue;
+ if (cmd_offset < ca->nelts) {
+ mm_resource_provider_t *mp =
mm_lookup_resource_provider(ce[cmd_offset].key);
+ if (mp) {
+ apr_status_t rc;
+ if (mp == this_provider) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] recursion not allowed:
%s",
+ mm_mcmp_command_name_get(cmd),
+ this_provider->name);
+ return APR_SUCCESS;
+ }
+ rc = (*mp->func)(cfg, cmd,
+ ce[cmd_offset].val, this_provider,
+ next - 1, balancer,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS) {
+ }
+ wdone++;
+ if (wcm)
+ continue;
+ else
+ break;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm) {
+ ap_rvputs(r, "@" MM_RES_BALANCER "/",
balancer->name, NULL);
+ if (cmd_offset < ca->nelts)
+ ap_rputs(": ", r);
+ else
+ ap_rputs(CRLF, r);
+ }
+ if (cmd_offset < ca->nelts)
+ rdo_balancer_info(cmd_table, cmd_offset, wcm, balancer, r);
+ break;
+ case mm_mcmp_enable:
+ balancer->status = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ balancer->status = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ balancer->status = mm_state_stopped;
+ break;
+ case mm_mcmp_delete:
+ if (balancer->status != mm_state_stopped) {
+ /* Balancer must be stopped before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Balancer not stopped: %s",
+ balancer->name);
+ return APR_SUCCESS;
+ }
+ else if (balancer->members || balancer->hosts) {
+ /* Balancer must be empty before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Balancer not empty: %s",
+ balancer->name);
+ return APR_SUCCESS;
+ }
+ else {
+ /* Delete Balancer entries */
+ if (strcmp(balancer->name, MM_DEFAULT_NAME)) {
+ /* Remove any dependant objects */
+ asmm_free(balancer_db, balancer);
+ }
+ else if (!wcm) {
+ mm_send_response_ex(r, mm_response_error,
+ MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0,
+ r->server,
+ "mod_manager: Cannot delete "
+ MM_DEFAULT_NAME " Balancer");
+ return APR_SUCCESS;
+ }
+ }
+ case mm_mcmp_config:
+ if (rdo_balancer_config(cfg, cmd_table, cmd_offset,
+ next - 1, balancer, r))
+ return APR_SUCCESS;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Balancer",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_status_t rv;
+ apr_uint32_t balancer_id;
+ /* Add new Balancer */
+ if ((rv = create_balancer(cfg, name, balancer_db,
+ &balancer, &balancer_id)) != APR_SUCCESS)
+ return rv;
+ /* Update Balancer from provided params */
+ rdo_balancer_config(cfg, cmd_table, cmd_offset,
+ balancer_id, balancer, r);
+ }
+ else {
+ mm_send_response_ex(r, mm_response_utype, 0, MM_RES_BALANCER "/",
+ name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown balancer: %s", name);
+ return APR_SUCCESS;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_balancer_init(mm_server_conf_t *cfg, apr_pool_t *pool)
+{
+ apr_uint32_t balancer_id;
+ mmdb_balancer_t *balancer;
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ if (!balancer_db)
+ return APR_ENOMEM;
+ /* Create _default_ balancer */
+ return create_balancer(cfg, MM_DEFAULT_NAME,
+ balancer_db,
+ &balancer,
+ &balancer_id);
+}
+
+static apr_status_t ini_balancer(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ return rdo_balancer_init(cfg, pool);
+ break;
+ case mm_resource_open:
+ case mm_resource_child_init:
+ case mm_resource_close:
+ /* Nothing to do for a Balancer */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t balancer_provider = {
+ MMDB_BALANCER,
+ MM_RES_BALANCER,
+ rdo_balancer,
+ ini_balancer,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_balancer(apr_pool_t *pool)
+{
+ this_provider = &balancer_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_balancer.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_cookie.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_cookie.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_cookie.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,212 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Cookie utility routines */
+#include "mm_cookie.h"
+
+#define COOKIE_SEPS ";"
+#define COOKIE_SEPC ';'
+#ifdef MM_COOKIE_SPEC_RFC
+#define COOKIE_SPEC "()<>@,;:\\\"/[]?={} \t"
+#else
+#define COOKIE_SPEC "()<>@,;:\\\"={} \t"
+#endif
+
+typedef enum {
+ MMC_COOKIE_COMMAND,
+ MMC_COOKIE_PATH,
+ MMC_COOKIE_VERSION,
+ MMC_COOKIE_DOMAIN,
+ MMC_COOKIE_COMMENT,
+ MMC_COOKIE_COMMENTURL,
+ MMC_COOKIE_MAXAGE,
+ MMC_COOKIE_EXPIRES,
+ MMC_COOKIE_PORT,
+ MMC_COOKIE_SECURE,
+ MMC_COOKIE_DISCARD,
+ MMC_COOKIE_LEN
+} mmc_cookie_av_e;
+
+static struct mmc_cookie_spec {
+ const char *name;
+ int param;
+ mmc_cookie_av_e av;
+} mmc_cookie_specs[] = {
+ { MMS_COOKIE_COMMAND, 1, MMC_COOKIE_COMMAND },
+ { MMS_COOKIE_PATH, 1, MMC_COOKIE_PATH },
+ { MMS_COOKIE_VERSION, 1, MMC_COOKIE_VERSION },
+ { MMS_COOKIE_DOMAIN, 1, MMC_COOKIE_DOMAIN },
+ { MMS_COOKIE_COMMENT, 1, MMC_COOKIE_COMMENT },
+ { MMS_COOKIE_COMMENTURL, 1, MMC_COOKIE_COMMENTURL},
+ { MMS_COOKIE_MAXAGE, 1, MMC_COOKIE_MAXAGE },
+ { MMS_COOKIE_EXPIRES, 1, MMC_COOKIE_EXPIRES },
+ { MMS_COOKIE_PORT, 1, MMC_COOKIE_PORT },
+ { MMS_COOKIE_SECURE, 0, MMC_COOKIE_SECURE },
+ { MMS_COOKIE_DISCARD, 0, MMC_COOKIE_DISCARD },
+ { NULL, 0, MMC_COOKIE_LEN }
+};
+
+static const char *mmc_true_str = "True";
+static const char *mmc_zero_str = "";
+
+static char *mmc_trim_str(char *str)
+{
+ char *p = str;
+
+ for (p = str; *p; p++); /* Find end of string */
+ for (p--; p >= str; p--) {
+ if (apr_isspace(*p))
+ *p = '\0'; /* Zap trailing blanks */
+ else
+ break;
+ }
+ while (apr_isspace(*str))
+ str++; /* Strip leading blanks */
+ return str;
+}
+
+static char *mmc_trim_unquote(char *str)
+{
+ char *p = str;
+
+ for (p = str; *p; p++); /* Find end of string */
+ for (p--; p >= str; p--) {
+ if (apr_isspace(*p))
+ *p = '\0'; /* Zap trailing blanks */
+ else
+ break;
+ }
+ while (apr_isspace(*str))
+ str++; /* Strip leading blanks */
+ if (*str == '"' && p != str && *p == '"')
{
+ *p = '\0';
+ str++;
+ }
+ return str;
+}
+
+static int mmc_name_valid(const char *cookie)
+{
+ const char *p = cookie;
+ while (*p) {
+ if (strchr(COOKIE_SPEC, *p))
+ return 0;
+ p++;
+ }
+ return 1;
+}
+
+static APR_INLINE int mmc_is_valid(int c)
+{
+ if (apr_isalnum(c) ||
+ c == '*' ||
+ c == '?' ||
+ c == '[')
+ return 1;
+ else
+ return 0;
+
+}
+/* Note: Parser doesn't allow embedded quotes inside quoted values.
+ */
+apr_status_t mmc_cookie_parse(apr_table_t *cookies, const char *cookie,
+ apr_pool_t *p)
+{
+ char *str, *tok, *state, *val;
+ int i;
+
+ while (*cookie && apr_isspace(*cookie))
+ cookie++;
+ if (*cookie == '\0')
+ return APR_EINVAL;
+
+ str = apr_pstrdup(p, cookie);
+ tok = apr_strtok(str, COOKIE_SEPS, &state);
+ while (tok != NULL) {
+ int dollar = 0;
+ int hasav = 0;
+ tok = mmc_trim_str(tok);
+ if (*tok == '$') {
+ tok++;
+ dollar = 1;
+ }
+ if ((val = strchr(tok, '='))) {
+ *val++ = '\0';
+ val = mmc_trim_unquote(val);
+ tok = mmc_trim_str(tok);
+ if (*val == '"') {
+ char *p;
+ /* We have embedded separator inside quotes */
+ *(state - 1) = COOKIE_SEPC;
+ if (!(state = strchr(state + 1, '"'))) {
+ /* Bad formating */
+ return APR_EINVAL;
+ }
+ if ((p = strchr(state + 1, COOKIE_SEPC))) {
+ *p++ = '\0';
+ state = p;
+ }
+ val = mmc_trim_unquote(val);
+ }
+ }
+ i = 0;
+ while (mmc_cookie_specs[i].name) {
+ if (!strcasecmp(tok, mmc_cookie_specs[i].name)) {
+ if (!val && mmc_cookie_specs[i].param)
+ return APR_EINVAL;
+ switch (mmc_cookie_specs[i].av) {
+ case MMC_COOKIE_SECURE:
+ case MMC_COOKIE_DISCARD:
+ apr_table_setn(cookies, mmc_cookie_specs[i].name,
+ mmc_true_str);
+ break;
+ default:
+ apr_table_setn(cookies, mmc_cookie_specs[i].name,
+ val);
+ break;
+ }
+ break;
+ }
+ i++;
+ }
+ if (i >= MMC_COOKIE_LEN) {
+ if (dollar) {
+ return APR_EINVAL;
+ }
+ else if (mmc_is_valid(*tok)) {
+ if (!mmc_name_valid(tok))
+ return APR_EINVAL;
+ if (!val) {
+ if ((val = strchr(tok, '/')))
+ *(val++) = '\0';
+ }
+ apr_table_addn(cookies, tok, val ? val : mmc_zero_str);
+ }
+ }
+ tok = apr_strtok(NULL, COOKIE_SEPS, &state);
+ }
+ return APR_SUCCESS;
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_cookie.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_cookie.h
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_cookie.h (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_cookie.h 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,83 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+#ifndef MM_COOKIE_H
+#define MM_COOKIE_H
+
+
+/**
+ * @file mmc_cookie.h
+ * @brief Manager cookie library
+ */
+/**
+ * @defgroup MM_COOKIE cookie routines
+ * @ingroup Manager
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_tables.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MMS_COOKIE_COMMAND "Command"
+
+/**
+ * RFC 2109 Cookie attributes
+ */
+#define MMS_COOKIE_PATH "Path"
+#define MMS_COOKIE_VERSION "Version"
+#define MMS_COOKIE_DOMAIN "Domain"
+#define MMS_COOKIE_COMMENT "Comment"
+#define MMS_COOKIE_COMMENTURL "CommentURL"
+#define MMS_COOKIE_MAXAGE "Max-Age"
+#define MMS_COOKIE_EXPIRES "Expires"
+#define MMS_COOKIE_PORT "Port"
+#define MMS_COOKIE_SECURE "Secure"
+#define MMS_COOKIE_DISCARD "Discard"
+
+/**
+ * Parse [Set-]Cookie: header accoring to the RFC 2109
+ * @param cookies Parsed cookies table
+ * @param cookie Input string to parse
+ * @param pool Pool to use
+ */
+apr_status_t mmc_cookie_parse(apr_table_t *cookies, const char *cookie,
+ apr_pool_t *p);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+#endif /* MM_COOKIE_H */
Property changes on: sandbox/aloha/httpd/modules/manager/mm_cookie.h
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_host.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_host.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_host.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,715 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Host object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+
+static const char *host_params[] = {
+ "",
+ "ServerName",
+ "ServerAlias",
+ "DocumentRoot",
+ "IsVirtual",
+ "KeepAlive",
+ "KeepAliveTimeout",
+ "MaxKeepAliveRequests",
+ "TimeOut",
+ "LimitRequestBody",
+ "Address",
+ "Port",
+ "Status",
+ NULL
+};
+
+static char *print_aliases(char *dst, int len, mmdb_hostlist_t *hostlist,
+ request_rec *r)
+{
+ int sep = 0;
+ apr_uint32_t next = 0;
+ mmdb_hostlist_t *alias;
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+ *dst = '\0';
+ while ((alias = asmm_slot_next(hostlist_db, &next))) {
+ /* Skip ourself */
+ if ((next - 1) == hostlist->selfref)
+ continue;
+ /* Check if this is alias */
+ if (alias->selfref != hostlist->selfref)
+ continue;
+ if (sep++) {
+ *(dst++) = ' ';
+ }
+ dst = apr_cpystrn(dst, alias->name, len);
+ len -= (strlen(alias->name) - 1);
+ }
+}
+
+static void rdo_host_info_print(int pi, int pp,
+ mmdb_host_t *host,
+ mmdb_hostlist_t *hostlist,
+ request_rec *r)
+{
+ char b[MM_BSIZE];
+
+ if (pp) {
+ ap_rvputs(r, host_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* ServerName */
+ ap_rvputs(r, hostlist->name, NULL);
+ break;
+ case 2: /* ServerAlias */
+ print_aliases(b, MM_BSIZE, hostlist, r);
+ MM_MAYBEQ_RPUTS(r, pp, b);
+ break;
+ case 3: /* DocumentRoot */
+ MM_MAYBEQ_RPUTS(r, pp, host->document_root);
+ break;
+ case 4: /* IsVirtual */
+ ap_rputs(MM_STR_BOOL(host->is_virtual), r);
+ break;
+ case 5: /* KeepAlive */
+ ap_rputs(MM_STR_ONOFF(host->keep_alive), r);
+ break;
+ case 6: /* KeepAliveTimeout */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
+ apr_time_as_msec(host->keep_alive_timeout));
+ break;
+ case 7: /* MaxKeepAliveRequests */
+ ap_rprintf(r, "%d", host->keep_alive_max);
+ break;
+ case 8: /* TimeOut */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
+ apr_time_as_msec(host->timeout));
+ break;
+ case 9: /* LimitRequestBody */
+ ap_rprintf(r, "%d", host->limit_req_line);
+ break;
+ case 10: /* Address */
+ ap_rvputs(r, host->address, NULL);
+ break;
+ case 11: /* Port */
+ ap_rprintf(r, "%d", host->port);
+ break;
+ case 12: /* Status */
+ ap_rputs(mm_state_name_get(host->status), r);
+ break;
+ }
+}
+
+/* Dump Host info */
+static void rdo_host_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_host_t *host,
+ mmdb_hostlist_t *hostlist,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (host_params[j]) {
+ if (apr_fnmatch(ce[i].key, host_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (host_params[j]) {
+ if (!strcasecmp(ce[i].key, host_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ if (m != 2 || host->is_virtual)
+ rdo_host_info_print(m, wcm, host, hostlist, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (host_params[j]) {
+ if (apr_fnmatch(ce[i].key, host_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_host_info_print(j, 1, host, hostlist, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (host_params[j]) {
+ if (!strcasecmp(ce[i].key, host_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_host_info_print(j, 1, host, hostlist, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static int host_exist(const char *value, mmdb_hostlist_t **hl)
+{
+ apr_uint32_t next = 0;
+ mmdb_hostlist_t *hostlist;
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+ while ((hostlist = asmm_slot_next(hostlist_db, &next))) {
+ if (strcasecmp(value, hostlist->name))
+ continue;
+ *hl = hostlist;
+ return 1;
+ }
+ return 0;
+}
+
+#define ALIASES_SEPS ", "
+
+static void add_aliases(mmdb_hostlist_t *hostlist, const char *value)
+{
+ int remove;
+ char *tok, *state;
+ char str[MM_BSIZE];
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+ apr_cpystrn(str, value, MM_BSIZE);
+ tok = apr_strtok(str, ALIASES_SEPS, &state);
+ while (tok != NULL) {
+ if (*tok == '-') {
+ tok++;
+ remove = 1;
+ }
+ else
+ remove = 0;
+ if (*tok) {
+ mmdb_hostlist_t *alias = NULL;
+ if (!host_exist(tok, &alias)) {
+ /* Add new ServerAlias */
+ if (!(alias = asmm_salloc(hostlist_db)))
+ return;
+ MM_SSAFE_COPY(alias->name, tok);
+ alias->host_id = hostlist->host_id;
+ /* Reference to VirtualHost */
+ alias->selfref = hostlist->selfref;
+ }
+ else if (remove && alias) {
+ asmm_free(hostlist_db, alias);
+ }
+ }
+ tok = apr_strtok(NULL, ALIASES_SEPS, &state);
+ }
+}
+
+static apr_status_t rdo_host_config_do(int pi,
+ const char *value,
+ mmdb_host_t *host,
+ mmdb_hostlist_t *hostlist,
+ request_rec *r)
+{
+ switch (pi) {
+ case 1: /* ServerName */
+ MM_SSAFE_COPY(hostlist->name, value);
+ break;
+ case 2: /* ServerAlias */
+ add_aliases(hostlist, value);
+ break;
+ case 3: /* DocumentRoot */
+ MM_SSAFE_COPY(host->document_root, value);
+ break;
+ case 4: /* IsVirtual */
+ ap_rputs(MM_STR_BOOL(host->is_virtual), r);
+ break;
+ case 5: /* KeepAlive */
+ host->keep_alive = MM_VAL_ONOFF(value);
+ break;
+ case 6: /* KeepAliveTimeout */
+ host->keep_alive_timeout = APR_TIME_C(1000) * atoi(value);
+ break;
+ case 7: /* MaxKeepAliveRequests */
+ host->keep_alive_max = atoi(value);
+ break;
+ case 8: /* TimeOut */
+ host->timeout = APR_TIME_C(1000) * atoi(value);
+ break;
+ case 9: /* LimitRequestBody */
+ host->limit_req_line = atoi(value);
+ break;
+ case 10: /* Address */
+ MM_SSAFE_COPY(host->address, value);
+ break;
+ case 11: /* Port */
+ host->port = atoi(value);
+ break;
+ case 12: /* Status */
+ host->status = mm_state_get(value);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+/* Configure Host */
+static int rdo_host_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ mmdb_host_t *host,
+ mmdb_hostlist_t *hostlist,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (host_params[j]) {
+ if (!strcasecmp(ce[i].key, host_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_host_config_do(j, ce[i].val,
+ host, hostlist, r))) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error, rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static void rdo_host_delete(asmm_slotmem_t *host_db,
+ asmm_slotmem_t *hostlist_db,
+ mmdb_host_t *host, apr_uint32_t host_id)
+{
+ apr_uint32_t next = 0;
+ mmdb_hostlist_t *hostlist;
+
+ /* Delete all HostList entries matching Host Id */
+ while ((hostlist = asmm_slot_next(hostlist_db, &next))) {
+ if (hostlist->host_id == host_id)
+ asmm_free(hostlist_db, hostlist);
+ }
+ asmm_free(host_db, host);
+}
+
+static apr_status_t rdo_host(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int wcm = 0;
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+ apr_uint32_t next = 0;
+ mmdb_host_t *host;
+ mmdb_hostlist_t *hostlist;
+
+ asmm_slotmem_t *host_db = mmdb_table_getn(MMDB_HOST);
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+ if (!host_db || !hostlist_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+#if MM_FORCE_DEFAULT_NAME_REQ
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty host name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+#else
+ name = MM_DEFAULT_NAME;
+#endif
+ }
+ if (*name != '~')
+ wcm = apr_fnmatch_test(name);
+ while ((hostlist = asmm_slot_next(hostlist_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, hostlist->name,
+ MM_FFNMATCH) != APR_SUCCESS)
+ continue;
+ }
+ else if (strcasecmp(name, hostlist->name))
+ continue;
+ /* Check if this is alias */
+ if ((next - 1) != hostlist->selfref) {
+ continue;
+ }
+ /* We have a matching record */
+ if (!(host = asmm_slot(host_db, hostlist->host_id))) {
+ /* HostList without Host record
+ * Corrupted database?
+ */
+ return APR_ESYMNOTFOUND;
+ }
+ if (cmd_offset < ca->nelts) {
+ mm_resource_provider_t *mp =
mm_lookup_resource_provider(ce[cmd_offset].key);
+ if (mp) {
+ apr_status_t rc;
+ if (mp == this_provider) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] recursion not allowed:
%s",
+ mm_mcmp_command_name_get(cmd),
+ this_provider->name);
+ return APR_SUCCESS;
+ }
+ rc = (*mp->func)(cfg, cmd,
+ ce[cmd_offset].val, this_provider,
+ hostlist->host_id, host,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS) {
+ }
+ wdone++;
+ if (wcm)
+ continue;
+ else
+ break;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm) {
+ ap_rvputs(r, "@" MM_RES_HOST "/",
hostlist->name, NULL);
+ if (cmd_offset < ca->nelts)
+ ap_rputs(": ", r);
+ else
+ ap_rputs(CRLF, r);
+ }
+ if (cmd_offset < ca->nelts)
+ rdo_host_info(cmd_table, cmd_offset, wcm,
+ host, hostlist, r);
+ break;
+ case mm_mcmp_enable:
+ host->status = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ host->status = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ host->status = mm_state_stopped;
+ break;
+ case mm_mcmp_delete:
+ if (host->status != mm_state_stopped) {
+ /* Host must be stopped before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Host not stopped: %s",
+ hostlist->name);
+ return APR_SUCCESS;
+ }
+ if (strcmp(hostlist->name, MM_DEFAULT_NAME)) {
+ /* Delete Host and HostList entries */
+ mmdb_balancer_t *pbal = NULL;
+ if (host->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ host->balancer_id);
+ rdo_host_delete(host_db, hostlist_db, host,
+ hostlist->host_id);
+ if (pbal && pbal->hosts)
+ pbal->hosts--;
+ }
+ else if (!wcm) {
+ mm_send_response_ex(r, mm_response_error,
+ MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0,
+ r->server,
+ "mod_manager: Cannot delete default Host");
+ return APR_SUCCESS;
+ }
+ case mm_mcmp_config:
+ if (prev && prev->id == MMDB_BALANCER) {
+ mmdb_balancer_t *nbal = (mmdb_balancer_t *)prev_rec;
+ if (prev_id != host->balancer_id) {
+ mmdb_balancer_t *pbal = NULL;
+ if (host->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ host->balancer_id);
+ /* Attach the Host to another Balancer */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "mod_manager: Host: %s assigned to"
+ " Balancer: %s",
+ hostlist->name, nbal->name);
+ host->balancer_id = prev_id;
+ nbal->hosts++;
+ if (pbal && pbal->hosts)
+ pbal->hosts--;
+ }
+ }
+ if (rdo_host_config(cfg, cmd_table, cmd_offset,
+ host, hostlist, r))
+ return APR_SUCCESS;
+ break;
+ case mm_mcmp_reset:
+ case mm_mcmp_exec:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Host",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_uint32_t host_id;
+ apr_uint32_t hostlist_id;
+ if (prev && prev->id != MMDB_BALANCER) {
+ mm_send_response_ex(r, mm_response_utype, 0, prev->name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: type %s in not valid root for Host: %s",
+ prev->name, name);
+ return APR_SUCCESS;
+ }
+ if (!prev) {
+ /* Use _default_ balancer */
+ prev_id = 0;
+ }
+
+ /* Add new VirtualHost */
+ if (!(hostlist = asmm_salloc_ex(hostlist_db, &hostlist_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(hostlist->name, name);
+
+ /* Create Host record */
+ if (!(host = asmm_salloc_ex(host_db, &host_id)))
+ return apr_get_os_error();
+ hostlist->host_id = host_id;
+ /* Self reference */
+ hostlist->selfref = hostlist_id;
+ /* New Host is always virtual */
+ host->is_virtual = 1;
+ host->balancer_id = prev_id;
+ /* Update Host from provided params */
+ rdo_host_config(cfg, cmd_table, cmd_offset, host, hostlist, r);
+ if (prev_rec) {
+ ((mmdb_balancer_t *)prev_rec)->hosts++;
+ }
+
+ }
+ else {
+ mm_send_response_ex(r, mm_response_utype, 0, MM_RES_HOST "/",
+ name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown host: %s", name);
+ return APR_SUCCESS;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ if (!prev)
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_host_init(mm_server_conf_t *cfg, apr_pool_t *pool)
+{
+ server_rec *s = cfg->main_server;
+ core_server_config *csc;
+ mmdb_host_t *host;
+ mmdb_hostlist_t *hostlist;
+ mmdb_hostlist_t *alias;
+ asmm_slotmem_t *host_db = mmdb_table_getn(MMDB_HOST);
+ asmm_slotmem_t *hostlist_db = mmdb_table_getn(MMDB_HOST_LIST);
+
+ if (!host_db || !hostlist_db)
+ return APR_ENOMEM;
+
+ while (s) {
+ apr_uint32_t host_id;
+ apr_uint32_t hostlist_id;
+ /* Create HostList record for each server_rec */
+ if (!(hostlist = asmm_salloc_ex(hostlist_db, &hostlist_id)))
+ return apr_get_os_error();
+ if (s->is_virtual) {
+ MM_SSAFE_COPY(hostlist->name, s->server_hostname);
+ }
+ else {
+ strcpy(hostlist->name, MM_DEFAULT_NAME);
+ }
+ /* Now create and populate Host record */
+ if (!(host = asmm_salloc_ex(host_db, &host_id)))
+ return apr_get_os_error();
+ hostlist->host_id = host_id;
+ hostlist->selfref = hostlist_id; /* Reference itself */
+
+ host->is_virtual = s->is_virtual;
+ host->keep_alive = s->keep_alive;
+ host->keep_alive_max = s->keep_alive_max;
+ host->limit_req_line = s->limit_req_line;
+ host->timeout = s->timeout;
+ host->keep_alive_timeout = s->keep_alive_timeout;
+ if (s->server_scheme &&
+ (strcmp(s->server_scheme, "https") == 0)) {
+ strcpy(host->scheme, "https");
+ }
+ else {
+ strcpy(host->scheme, "http");
+ }
+ if (s->addrs) {
+ char *ip;
+ apr_sockaddr_ip_get(&ip, s->addrs->host_addr);
+ MM_SSAFE_COPY(host->address, ip);
+ host->port = s->addrs->host_addr->port;
+ }
+
+ csc = (core_server_config *)ap_get_module_config(s->module_config,
+ &core_module);
+ MM_SSAFE_COPY(host->document_root, csc->ap_document_root);
+
+ if (!s->is_virtual) {
+ if (!(alias = asmm_salloc(hostlist_db)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(alias->name, s->server_hostname);
+ alias->host_id = host_id;
+ alias->selfref = hostlist_id;
+ }
+ /* Look for ServerAlias */
+ if (s->names) {
+ int i;
+ for (i = 0; i < s->names->nelts; i++) {
+ const char *a = ((char **)s->names->elts)[i];
+ if (!a || !*a)
+ continue;
+ if (!(alias = asmm_salloc(hostlist_db)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(alias->name, a);
+ alias->host_id = host_id;
+ alias->selfref = hostlist_id;
+ }
+ }
+ /* Look for ServerAliasMatch */
+ if (s->wild_names) {
+ int i;
+ for (i = 0; i < s->wild_names->nelts; i++) {
+ const char *a = ((char **)s->wild_names->elts)[i];
+ if (!a || !*a)
+ continue;
+ if (!(alias = asmm_salloc(hostlist_db)))
+ return apr_get_os_error();
+ apr_cpystrn(&alias->name[1], a, sizeof(alias->name) - 1);
+ alias->name[0] = '~';
+ alias->host_id = host_id;
+ alias->selfref = hostlist_id;
+ }
+ }
+ s = s->next;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_host(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ return rdo_host_init(cfg, pool);
+ break;
+ case mm_resource_open:
+ case mm_resource_child_init:
+ case mm_resource_close:
+ /* Nothing to do for a Host */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t host_provider = {
+ MMDB_HOST,
+ MM_RES_HOST,
+ rdo_host,
+ ini_host,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_host(apr_pool_t *pool)
+{
+ this_provider = &host_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_host.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_manager.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_manager.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_manager.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,371 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+
+static const char *manager_params[] = {
+ "",
+ "ProtocolVersion",
+ "ServerId",
+ "Advertise",
+ "AdvertiseMode",
+ "Status",
+ "Strict",
+ "CaseInsensitive",
+ "SecurityKey",
+ NULL
+};
+
+static void rdo_manager_info_print(int pi, int pp,
+ mm_server_conf_t *cfg,
+ request_rec *r)
+{
+ mmdb_manager_t *m = (mmdb_manager_t *)this_provider->context;
+ if (pp) {
+ ap_rvputs(r, manager_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* ProtocolVersion */
+ ap_rputs(MM_MCMP_VERSION_STRING, r);
+ break;
+ case 2: /* ServerId */
+ ap_rvputs(r, m->srvid + 1, NULL);
+ break;
+ case 3: /* Advertise */
+ ap_rputs(MM_STR_ONOFF(m->advertise), r);
+ break;
+ case 4: /* AdvertiseMode */
+ switch (m->advertise_mode) {
+ case mm_advertise_off:
+ ap_rputs("Off", r);
+ break;
+ case mm_advertise_on:
+ ap_rputs("On", r);
+ break;
+ case mm_advertise_status:
+ ap_rputs("Status", r);
+ break;
+ }
+ break;
+ case 5: /* Status */
+ ap_rprintf(r, "%d", m->status);
+ break;
+ case 6: /* Strict */
+ ap_rputs(MM_STR_ONOFF(m->strict), r);
+ break;
+ case 7: /* CaseInsensitive */
+ ap_rputs(MM_STR_ONOFF(m->case_blind), r);
+ break;
+ case 8: /* SecurityKey */
+ {
+ int i, c = 0;
+ for (i = 0; i < APR_MD5_DIGESTSIZE; i++)
+ c += m->ssalt[i];
+ ap_rputs(MM_STR_ONOFF(c), r);
+ }
+ break;
+ }
+}
+
+/* Dump Manager info */
+static void rdo_manager_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ mm_server_conf_t *cfg,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+ const char *param = NULL;
+ const char *value = NULL;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (manager_params[j]) {
+ if (apr_fnmatch(ce[i].key, manager_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (manager_params[j]) {
+ if (!strcasecmp(ce[i].key, manager_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_manager_info_print(m, 0, cfg, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ /* Multiple params */
+ int sep = 0;
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (manager_params[j]) {
+ if (apr_fnmatch(ce[i].key, manager_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_manager_info_print(j, 1, cfg, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (manager_params[j]) {
+ if (!strcasecmp(ce[i].key, manager_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_manager_info_print(j, 1, cfg, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static apr_status_t rdo_manager_config_do(int pi,
+ const char *value,
+ request_rec *r)
+{
+ mmdb_manager_t *m = (mmdb_manager_t *)this_provider->context;
+
+ switch (pi) {
+ case 6: /* Strict */
+ m->strict = MM_VAL_ONOFF(value);
+ break;
+ case 7: /* CaseInsensitive */
+ m->case_blind = MM_VAL_ONOFF(value);
+ break;
+ case 8: /* SecurityKey */
+ {
+ apr_md5_ctx_t mc;
+ apr_md5_init(&mc);
+ apr_md5_update(&mc, value, strlen(value));
+ apr_md5_final(m->ssalt, &mc);
+ }
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+/* Configure Manager */
+static int rdo_manager_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (manager_params[j]) {
+ if (!strcasecmp(ce[i].key, manager_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_manager_config_do(j, ce[i].val, r)) != APR_SUCCESS) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static apr_status_t rdo_manager(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ mmdb_manager_t *m = (mmdb_manager_t *)this_provider->context;
+ switch (cmd) {
+ case mm_mcmp_info:
+ rdo_manager_info(cmd_table, cmd_offset, cfg, r);
+ break;
+ case mm_mcmp_enable:
+ if (!m->advertise) {
+ m->type = MM_ADVERTISE_SERVER;
+ m->status = HTTP_OK;
+ }
+ break;
+ case mm_mcmp_disable:
+ if (m->advertise) {
+ m->type = MM_ADVERTISE_STATUS;
+ m->status = HTTP_SERVICE_UNAVAILABLE;
+ }
+ break;
+ case mm_mcmp_stop:
+ m->advertise = 0;
+ break;
+ case mm_mcmp_reset:
+ m->status = 0;
+ break;
+ case mm_mcmp_config:
+ if (rdo_manager_config(cfg, cmd_table, cmd_offset, r))
+ return APR_SUCCESS;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Manager",
+ mm_mcmp_command_name_get(cmd));
+ break;
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_manager_init(mm_server_conf_t *cfg)
+{
+ apr_status_t rv;
+ asmm_slotmem_t *manager_db = NULL;
+ mmdb_manager_t *manager = NULL;
+
+ manager_db = mmdb_table_getn(MMDB_MANAGER);
+ if (!(manager = asmm_salloc(manager_db))) {
+ rv = apr_get_os_error();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, cfg->main_server,
+ "mod_manager: database alloc for Manager");
+ return rv;
+ }
+ apr_uuid_get(&manager->suuid);
+ manager->srvid[0] = '/';
+ apr_uuid_format(&manager->srvid[1], &manager->suuid);
+ this_provider->context = manager;
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_manager_child_init(mm_server_conf_t *cfg)
+{
+ apr_status_t rv;
+ asmm_slotmem_t *manager_db = NULL;
+ mmdb_manager_t *manager = NULL;
+
+ manager_db = mmdb_table_getn(MMDB_MANAGER);
+ if (!(manager = asmm_slot(manager_db, 0))) {
+ rv = apr_get_os_error();
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, cfg->main_server,
+ "mod_manager: database record for Manager");
+ return rv;
+ }
+ this_provider->context = manager;
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_manager(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ return rdo_manager_init(cfg);
+ break;
+ case mm_resource_open:
+ case mm_resource_child_init:
+ return rdo_manager_child_init(cfg);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a Manager */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t manager_provider = {
+ MMDB_MANAGER,
+ MM_RES_MANAGER,
+ rdo_manager,
+ ini_manager,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_manager(apr_pool_t *pool)
+{
+ this_provider = &manager_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_manager.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_member.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_member.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_member.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,766 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Node object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+static int server_limit = 0;
+static int thread_limit = 0;
+static int max_clients = 0;
+static int max_childs = 0;
+static int max_requests_per_child = 0;
+static int max_threads_per_child = 0;
+
+static const char *member_params[] = {
+ "",
+ "Balancer",
+ "Type",
+ "Address",
+ "Port",
+ "Route",
+ "Domain",
+ "Ping",
+ "MaxConnections",
+ "MinConnections",
+ "MaxClients",
+ "TTL",
+ "LF",
+ "Distance",
+ "Activation",
+ "FlushMode",
+ "FlushTimeout",
+ /* Statistical data */
+ "State",
+ "Error",
+ "Busy",
+ "Connected",
+ "Elected",
+ "StickySessions",
+ "ClientErrors",
+ "NodeErrors",
+ "Trace",
+ "TraceErrors",
+ "Readed",
+ "Transferred",
+ NULL
+};
+
+static const char *get_balancer_name(apr_uint32_t id)
+{
+ mmdb_balancer_t *balancer;
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ if ((balancer = asmm_slot(balancer_db, id))) {
+ return balancer->name;
+ }
+ return NULL;
+}
+
+static const char *get_flush_name(mm_flush_mode_e mode)
+{
+ switch(mode) {
+ case mm_flush_wait:
+ return "T";
+ break;
+ case mm_flush_auto:
+ return "A";
+ break;
+ }
+ return "N";
+}
+
+static mm_flush_mode_e get_flush_mode(const char *mode)
+{
+ switch(apr_toupper(*mode)) {
+ case 'T':
+ return mm_flush_wait;
+ break;
+ case 'A':
+ return mm_flush_auto;
+ break;
+ }
+ return mm_flush_none;
+}
+
+static apr_status_t add_app_members(apr_uint32_t member_id,
+ apr_uint32_t balancer_id)
+{
+ apr_uint32_t napp = 0;
+ apr_uint32_t nhost = 0;
+ mmdb_host_t *host;
+ mmdb_app_t *app;
+ mmdb_memberapp_t *memberapp;
+ asmm_slotmem_t *host_db = mmdb_table_getn(MMDB_HOST);
+ asmm_slotmem_t *app_db = mmdb_table_getn(MMDB_APPLICATION);
+ asmm_slotmem_t *memberapp_db = mmdb_table_getn(MMDB_MEMBERAPP);
+
+ while ((host = asmm_slot_next(host_db, &nhost))) {
+ if (host->balancer_id != balancer_id)
+ continue;
+ napp = 0;
+ while ((app = asmm_slot_next(app_db, &napp))) {
+ if (app->host_id != (nhost - 1))
+ continue;
+ if (!(memberapp = asmm_salloc(memberapp_db)))
+ return apr_get_os_error();
+ memberapp->app_id = napp - 1;
+ memberapp->member_id = member_id;
+ memberapp->state = app->state;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static void del_app_members(apr_uint32_t member_id)
+{
+ apr_uint32_t next = 0;
+ mmdb_memberapp_t *memberapp;
+ asmm_slotmem_t *memberapp_db = mmdb_table_getn(MMDB_MEMBERAPP);
+
+ while ((memberapp = asmm_slot_next(memberapp_db, &next))) {
+ if (memberapp->member_id != member_id)
+ continue;
+ asmm_free(memberapp_db, memberapp);
+ }
+}
+
+
+static void rdo_member_info_print(int pi, int pp,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ char buf[512];
+ const char *p;
+
+ if (pp) {
+ ap_rvputs(r, member_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* Balancer */
+ ap_rvputs(r, get_balancer_name(mem->balancer_id), NULL);
+ break;
+ case 2: /* Type */
+ ap_rputs(mm_protocol_name_get(mem->type), r);
+ break;
+ case 3: /* Address */
+ ap_rvputs(r, mem->address, NULL);
+ break;
+ case 4: /* Port */
+ ap_rprintf(r, "%u", mem->port);
+ break;
+ case 5: /* Route */
+ ap_rvputs(r, mem->route, NULL);
+ break;
+ case 6: /* Domain */
+ ap_rvputs(r, mem->domain, NULL);
+ break;
+ case 7: /* Ping */
+ ap_rprintf(r, "%u", mem->ping);
+ break;
+ case 8: /* MaxConnections */
+ ap_rprintf(r, "%u", mem->max_conn);
+ break;
+ case 9: /* MinConnections */
+ ap_rprintf(r, "%u", mem->min_conn);
+ break;
+ case 10: /* MaxClients */
+ ap_rprintf(r, "%u", mem->max_clients);
+ break;
+ case 11: /* TTL */
+ ap_rprintf(r, "%u", mem->ttl);
+ break;
+ case 12: /* LF */
+ ap_rprintf(r, "%u", mem->lf);
+ break;
+ case 13: /* Distance */
+ ap_rprintf(r, "%u", mem->distance);
+ break;
+ case 14: /* Activation */
+ ap_rputs(mm_state_name_get(mem->activation), r);
+ break;
+ case 15: /* FlushMode */
+ ap_rputs(get_flush_name(mem->flush), r);
+ break;
+ case 16: /* FlushTimeout */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
apr_time_as_msec(mem->flush_wait));
+ break;
+ case 17: /* State */
+ ap_rputs(mm_state_name_get(mem->state), r);
+ break;
+ case 18: /* Error */
+ if (!(p = mm_strerror(mem->err))) {
+ if (!(p = apr_strerror(mem->err, buf, sizeof(buf))))
+ p = "Unknown Error";
+ }
+ if (pp)
+ ap_rprintf(r, "\"%d: %s\"", mem->err, p);
+ else
+ ap_rprintf(r, "%d: %s", mem->err, p);
+ break;
+ case 19: /* Busy */
+ ap_rprintf(r, "%u", mem->busy);
+ break;
+ case 20: /* Connected */
+ ap_rprintf(r, "%u", mem->connected);
+ break;
+ case 21: /* Elected */
+ ap_rprintf(r, "%u", mem->elected);
+ break;
+ case 22: /* StickySessions */
+ ap_rprintf(r, "%u", mem->ssessions);
+ break;
+ case 23: /* ClientErrors */
+ ap_rprintf(r, "%u", mem->err_client);
+ break;
+ case 24: /* NodeErrors */
+ ap_rprintf(r, "%u", mem->err_node);
+ break;
+ case 25: /* Trace */
+ ap_rprintf(r, "%u", mem->trace);
+ break;
+ case 26: /* TraceErrors */
+ ap_rprintf(r, "%u", mem->err_trace);
+ break;
+ case 27: /* Readed */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->readed);
+ break;
+ case 28: /* Transferred */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->transferred);
+ break;
+ }
+}
+
+/* Dump Member info */
+static void rdo_member_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (member_params[j]) {
+ if (apr_fnmatch(ce[i].key, member_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_member_info_print(m, wcm, mem, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (member_params[j]) {
+ if (apr_fnmatch(ce[i].key, member_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_member_info_print(j, 1, mem, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_member_info_print(j, 1, mem, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static apr_status_t rdo_member_config_do(int pi,
+ const char *value,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ int i;
+
+ switch (pi) {
+ case 2: /* Type */
+ if (mem->state == mm_state_stopped)
+ mem->type = mm_protocol_get(value);
+ else
+ return MME_EPERM;
+ break;
+ case 3: /* Address */
+ if (mem->state == mm_state_stopped)
+ MM_SSAFE_COPY(mem->address, value);
+ else
+ return MME_EPERM;
+ break;
+ case 4: /* Port */
+ if (mem->state == mm_state_stopped)
+ mem->port = atoi(value);
+ else
+ return MME_EPERM;
+ break;
+ case 5: /* Route */
+ MM_SSAFE_COPY(mem->route, value);
+ break;
+ case 6: /* Domain */
+ MM_SSAFE_COPY(mem->domain, value);
+ break;
+ case 7: /* Ping */
+ mem->ping = atoi(value);
+ break;
+ case 8: /* MaxConnections */
+ i = atoi(value);
+ if (i < 1 || i > max_threads_per_child)
+ return MME_EINVAL;
+ else
+ mem->max_conn = i;
+ break;
+ case 9: /* MinConnections */
+ i = atoi(value);
+ if (i < 1 || i > (int)mem->max_conn)
+ return MME_EINVAL;
+ else
+ mem->min_conn = i;
+ break;
+ case 10: /* MaxClients */
+ i = atoi(value);
+ if (i < 1 || i > max_clients)
+ return MME_EINVAL;
+ else
+ mem->max_clients = i;
+ break;
+ case 11: /* TTL */
+ mem->ttl = atoi(value);
+ break;
+ case 12: /* LF */
+ mem->lf = atoi(value);
+ break;
+ case 13: /* Distance */
+ mem->distance = atoi(value);
+ break;
+ case 14: /* Activation */
+ mem->activation = mm_state_get(value);
+ break;
+ case 15: /* FlushMode */
+ mem->flush = get_flush_mode(value);
+ break;
+ case 16: /* FlushTimeout */
+ mem->flush_wait = atoi(value) * APR_TIME_C(1000);
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+/* Configure Member */
+static int rdo_member_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ apr_uint32_t member_id,
+ mmdb_member_t *member,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_member_config_do(j, ce[i].val,
+ member, r)) != APR_SUCCESS) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static apr_status_t rdo_member(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int wcm;
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+ apr_uint32_t next = 0;
+ mmdb_member_t *member;
+
+ asmm_slotmem_t *member_db = mmdb_table_getn(MMDB_MEMBER);
+
+ if (!member_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty member name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ }
+ wcm = apr_fnmatch_test(name);
+ while ((member = asmm_slot_next(member_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, member->name,
+ MM_FFNMATCH) != APR_SUCCESS)
+ continue;
+ }
+ else if (strcasecmp(name, member->name))
+ continue;
+ if (cmd_offset < ca->nelts) {
+ mm_resource_provider_t *mp =
mm_lookup_resource_provider(ce[cmd_offset].key);
+ if (mp) {
+ apr_status_t rc;
+ if (mp == this_provider) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] recursion not allowed:
%s",
+ mm_mcmp_command_name_get(cmd),
+ this_provider->name);
+ return APR_SUCCESS;
+ }
+ rc = (*mp->func)(cfg, cmd,
+ ce[cmd_offset].val, this_provider,
+ next - 1, member,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS) {
+ }
+ wdone++;
+ if (wcm)
+ continue;
+ else
+ break;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm) {
+ ap_rvputs(r, "@" MM_RES_MEMBER "/",
member->name, NULL);
+ if (cmd_offset < ca->nelts)
+ ap_rputs(": ", r);
+ else
+ ap_rputs(CRLF, r);
+ }
+ if (cmd_offset < ca->nelts)
+ rdo_member_info(cmd_table, cmd_offset, wcm, member, r);
+ break;
+ case mm_mcmp_enable:
+ member->state = mm_state_active;
+ member->activation = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ member->state = mm_state_disabled;
+ member->activation = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ member->state = mm_state_stopped;
+ member->activation = mm_state_stopped;
+ break;
+ case mm_mcmp_reset:
+ /* Reset statistical data */
+ member->elected = 0;
+ member->ssessions = 0;
+ member->err_client = 0;
+ member->err_node = 0;
+ member->err_trace = 0;
+ member->trace = 0;
+ member->readed = 0;
+ member->transferred = 0;
+ break;
+ case mm_mcmp_delete:
+ if (member->state != mm_state_stopped) {
+ /* Member must be stopped before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Member not stopped: %s",
+ member->name);
+ return APR_SUCCESS;
+ }
+ else {
+ /* Delete Member entry */
+ mmdb_balancer_t *pbal = NULL;
+ if (member->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ member->balancer_id);
+ del_app_members(next - 1);
+ asmm_free(member_db, member);
+ if (pbal && pbal->members)
+ pbal->members--;
+ }
+ break;
+ case mm_mcmp_config:
+ if (prev && prev->id == MMDB_BALANCER) {
+ mmdb_balancer_t *nbal = (mmdb_balancer_t *)prev_rec;
+ if (prev_id != member->balancer_id) {
+ mmdb_balancer_t *pbal = NULL;
+ if (member->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ member->balancer_id);
+ /* Attach the Member to another Balancer */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "mod_manager: Member: %s assigned to "
+ "Balancer: %s",
+ member->name, nbal->name);
+ member->balancer_id = prev_id;
+ nbal->members++;
+ if (pbal && pbal->members)
+ pbal->members--;
+ }
+ }
+ if (rdo_member_config(cfg, cmd_table, cmd_offset,
+ next - 1, member, r))
+ return APR_SUCCESS;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Balancer",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_uint32_t member_id;
+ if (prev && prev->id != MMDB_BALANCER) {
+ mm_send_response_ex(r, mm_response_utype, 0, prev->name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: type %s in not balancer for "
+ "Member: %s",
+ prev->name, name);
+ return APR_SUCCESS;
+ }
+ if (!prev) {
+ /* Use _default_ balancer */
+ prev_id = 0;
+ }
+ /* Add new Member */
+ if (!(member = asmm_salloc_ex(member_db, &member_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(member->name, name);
+ member->balancer_id = prev_id;
+ member->state = mm_state_stopped;
+ member->activation = mm_state_stopped;
+ member->lf = 1;
+ member->max_conn = max_threads_per_child;
+ member->min_conn = max_threads_per_child;
+ member->max_clients = max_clients;
+ /* Update Member from provided params */
+ if (rdo_member_config(cfg, cmd_table, cmd_offset,
+ member_id, member, r)) {
+ /* There was an error during initial config
+ * Delete member we created
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: failed creating member: %s",
+ name);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ }
+ if (!member->route[0])
+ strcpy(member->route, member->name);
+ if (!member->address[0])
+ strcpy(member->address, MM_DEFAULT_ADDRESS);
+ if (member->type == mm_protocol_unknown)
+ member->type = MM_DEFAULT_PROTOCOL;
+ if (!member->port) {
+ switch (member->type) {
+ case mm_protocol_ajp:
+ member->port = MM_DEFAULT_AJP_PORT;
+ break;
+ case mm_protocol_http:
+ member->port = MM_DEFAULT_HTTP_PORT;
+ break;
+ case mm_protocol_https:
+ member->port = MM_DEFAULT_HTTPS_PORT;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error,
+ MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Unknown protocol %d for "
+ "Member: %s",
+ member->type, member->name);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ break;
+ }
+ }
+ if (member->min_conn > member->max_conn)
+ member->min_conn = member->max_conn;
+ member->state = mm_state_stopped;
+ /* Add Applications linked to the Member's Balancer */
+ if (add_app_members(member_id, member->balancer_id) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: adding MemberApplication for: %s",
+ member->name);
+ del_app_members(member_id);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ }
+ if (prev_rec) {
+ ((mmdb_balancer_t *)prev_rec)->members++;
+ }
+ }
+ else {
+ mm_send_response_ex(r, mm_response_utype, 0, MM_RES_MEMBER "/",
+ name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown member: %s", name);
+ return APR_SUCCESS;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ if (!prev)
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_member_init(mm_server_conf_t *cfg)
+{
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests_per_child);
+ ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_childs);
+ if (max_childs < 1)
+ max_childs = 1;
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
+ if (max_threads_per_child < 1)
+ max_threads_per_child = 1;
+ max_clients = max_childs * max_threads_per_child;
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_member(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ case mm_resource_open:
+ case mm_resource_child_init:
+ return rdo_member_init(cfg);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a Member */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t member_provider = {
+ MMDB_MEMBER,
+ MM_RES_MEMBER,
+ rdo_member,
+ ini_member,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_member(apr_pool_t *pool)
+{
+ this_provider = &member_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_member.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_module.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_module.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_module.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,1449 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+#define CORE_PRIVATE
+
+#include "mm_api.h"
+#include "mm_cookie.h"
+#include "mod_core.h"
+#include "scoreboard.h"
+#include "mod_status.h"
+#include "mod_ssl.h"
+#include "util_script.h"
+
+#ifndef MAX
+#define MAX(x,y) ((x) >= (y) ? (x) : (y))
+#endif
+
+#define MM_SRVCONF(p) ap_get_module_config((p)->server->module_config, \
+ &manager_module)
+#define MM_GETCONF(s) ap_get_module_config((s)->module_config, \
+ &manager_module)
+
+/*
+ * Declare ourselves so the configuration routines can find and know us.
+ * We'll fill it in at the end of the module.
+ */
+module AP_MODULE_DECLARE_DATA manager_module;
+
+
+/*
+ * Server global data
+ */
+typedef struct mm_global_data_t {
+ int generation;
+ char *database_path;
+ void *database;
+ apr_pool_t *ppool;
+ apr_pool_t *cpool;
+} mm_global_data_t;
+
+static const char *mm_handler_name = MM_HANDLER_NAME;
+/*
+ * Global data instance
+ * For parent, registered in process pool
+ * For child, registered in child pool
+ */
+static mm_global_data_t *mmgd = NULL;
+static server_rec *mmsr = NULL;
+
+/* Global Database slots */
+static mmdb_manager_t *mmdb_manager_rec = NULL;
+static apr_global_mutex_t *mm_manager_mutex = NULL;
+
+/*
+ * Server private data
+ */
+static int mm_generation = 0;
+static apr_time_t mm_child_started = 0;
+static pid_t mm_parent_pid = -1;
+
+/*
+ * Global configuration
+ */
+static int mm_manager_strict = 0;
+static int mm_advertise_set = 0;
+static int mm_advertise_run = 0;
+static char *mm_database_root = NULL;
+static char *mm_lock_filename = NULL;
+static char *mm_advertise_adrs = NULL;
+static char *mm_advertise_adsi = NULL;
+static char *mm_advertise_srvm = NULL;
+static char *mm_advertise_srvs = NULL;
+static char *mm_advertise_srvi = NULL;
+
+static char *mm_advertise_skey = NULL;
+
+
+static mm_advertise_srv_t mm_advs_server;
+
+
+/* Advertise is by default turned off */
+static apr_port_t mm_advertise_port = MM_DEFAULT_ADVPORT;
+static apr_port_t mm_advertise_srvp = 0;
+static mm_advertise_e mm_advertise_mode = mm_advertise_off;
+static apr_interval_time_t mm_advertise_freq = MM_DEFAULT_ADV_FREQ;
+static mm_mcmp_command_e mcmp_command_type = mm_mcmp_unknown;
+
+
+/* Parent and child manager thread statuses */
+static volatile int is_mp_running = 0;
+static volatile int is_mc_running = 0;
+static volatile int is_mp_created = 0;
+static volatile int is_mc_created = 0;
+
+/* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
+ * IPv4 match-any-address, 0.0.0.0. */
+#define IS_INADDR_ANY(addr) ((addr)->family == APR_INET && \
+ (addr)->sa.sin.sin_addr.s_addr == INADDR_ANY)
+
+/* Evaluates to true if the (apr_sockaddr_t *) addr argument is the
+ * IPv6 match-any-address, [::]. */
+#define IS_IN6ADDR_ANY(addr) ((addr)->family == APR_INET6 && \
+ IN6_IS_ADDR_UNSPECIFIED(&(addr)->sa.sin6.sin6_addr))
+
+#define MMDB_DIR_MODE (APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE | \
+ APR_FPROT_GREAD | APR_FPROT_GWRITE | APR_FPROT_GEXECUTE)
+
+static const char *mm_advertise_str[] = {
+ "Off",
+ "Status",
+ "On"
+};
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Server helper routines. */
+/* */
+/*--------------------------------------------------------------------------*/
+static apr_status_t mm_manager_dolock()
+{
+ if (mm_manager_mutex)
+ return apr_global_mutex_lock(mm_manager_mutex);
+ else
+ return APR_SUCCESS;
+}
+
+static apr_status_t mm_manager_unlock()
+{
+ if (mm_manager_mutex)
+ return apr_global_mutex_unlock(mm_manager_mutex);
+ else
+ return APR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Server configuration data. */
+/* */
+/*--------------------------------------------------------------------------*/
+static void *mm_create_server_config(apr_pool_t *p, server_rec *s)
+{
+ mm_server_conf_t *mmsc = apr_pcalloc(p, sizeof(mm_server_conf_t));
+
+ mmsc->pool = p;
+ mmsc->handle = MM_DEFAULT_HANDLE;
+ mmsc->server = s;
+ if (!s->is_virtual) {
+ mmsc->handle_set = 1;
+ mmsr = s;
+ }
+ mmsc->main_server = mmsr;
+ return mmsc;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Merge server configuration data. */
+/* */
+/*--------------------------------------------------------------------------*/
+static void *mm_merge_server_config(apr_pool_t *p, void *base, void *over)
+{
+ mm_server_conf_t *mmsc = apr_pcalloc(p, sizeof(mm_server_conf_t));
+ mm_server_conf_t *mmsb = (mm_server_conf_t *)base;
+ mm_server_conf_t *mmso = (mm_server_conf_t *)over;
+
+ mmsc->status = mmso->status_set ? mmso->status : mmsb->status;
+ mmsc->handle = mmso->handle_set ? mmso->handle : mmsb->handle;
+ mmsc->status_set = mmso->status_set || mmsb->status_set;
+ mmsc->handle_set = mmso->handle_set || mmsb->handle_set;
+ mmsc->pool = p;
+ mmsc->server = mmsb->server;
+ mmsc->main_server = mmsr;
+
+ return mmsc;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* ManagerStatus directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_status(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ mm_server_conf_t *mmsc = MM_SRVCONF(cmd);
+
+ if (strcasecmp(arg, "Off") == 0)
+ mmsc->status = mm_status_off;
+ else if (strcasecmp(arg, "On") == 0)
+ mmsc->status = mm_status_on;
+ else if (strcasecmp(arg, "Full") == 0)
+ mmsc->status = mm_status_full;
+ else
+ return "ManagerStatus must be one of: Off | On | Full";
+
+ mmsc->status_set = 1;
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* ManagerDatabaseRoot directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_dbroot(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+
+ if (mm_database_root != NULL)
+ return "Duplicate ManagerDatabaseRoot directives are not allowed";
+
+ /* we need an absolute path (ap_server_root_relative does the ap_pstrdup) */
+ mm_database_root = ap_server_root_relative(cmd->pool, arg);
+ if (mm_database_root == NULL)
+ return "Invalid ManagerDatabaseRoot name";
+ if (mm_database_root[strlen(mm_database_root) - 1] == '/')
+ mm_database_root[strlen(mm_database_root) - 1] = '\0';
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* ManagerHandle directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_handle(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ apr_size_t sl;
+ mm_server_conf_t *mmsc = MM_SRVCONF(cmd);
+
+ if (*arg == '/') {
+ sl = strlen(arg);
+ if (arg[sl - 1] == '/')
+ --sl;
+ mmsc->handle = apr_pstrndup(cmd->pool, arg, sl);
+ }
+ else {
+ if (!strcasecmp(arg, "Off"))
+ mmsc->handle = NULL;
+ else if (!strcasecmp(arg, "On")) {
+ if (!cmd->path || *(cmd->path) != '/')
+ return "ManagerHandle On must be declared inside
<Location>";
+ sl = strlen(cmd->path);
+ if (sl > 1 && cmd->path[sl - 1] == '/')
+ --sl;
+ mmsc->handle = apr_pstrndup(cmd->pool, cmd->path, sl);
+ }
+ }
+ mmsc->handle_set = 1;
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* ServerAdvertise directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_advertise_m(cmd_parms *cmd, void *dummy,
+ const char *arg, const char *opt)
+{
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+
+ if (strcasecmp(arg, "Off") == 0)
+ mm_advertise_mode = mm_advertise_off;
+ else if (strcasecmp(arg, "On") == 0)
+ mm_advertise_mode = mm_advertise_on;
+ else
+ return "ServerAdvertise must be Off or On";
+ if (opt) {
+ const char *p = strstr(opt, "://");
+ if (p) {
+ mm_advertise_srvm = apr_pstrndup(cmd->pool, opt, p - opt);
+ opt = p + 3;
+ }
+ if (apr_parse_addr_port(&mm_advertise_srvs,
+ &mm_advertise_srvi,
+ &mm_advertise_srvp,
+ opt, cmd->pool) != APR_SUCCESS ||
+ !mm_advertise_srvs ||
+ !mm_advertise_srvp)
+ return "Invalid ServerAdvertise Address";
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* ManagerStrictParser directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_parse_strict(cmd_parms *cmd, void *dummy,
+ int flag)
+{
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+
+ mm_manager_strict = flag;
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* AdvertiseGroup directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_advertise_g(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+ if (mm_advertise_set)
+ return "Duplicate AdvertiseGroup directives are not allowed";
+
+ if (apr_parse_addr_port(&mm_advertise_adrs,
+ &mm_advertise_adsi,
+ &mm_advertise_port,
+ arg, cmd->pool) != APR_SUCCESS)
+ return "Invalid AdvertiseGroup address";
+ if (!mm_advertise_adrs)
+ return "Missing Ip part from AdvertiseGroup address";
+ if (!mm_advertise_port)
+ mm_advertise_port = MM_DEFAULT_ADVPORT;
+ mm_advertise_set = 1;
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* AdvertiseFrequency directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_advertise_f(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ apr_time_t s, u = 0;
+ const char *p;
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+ if ((p = strchr(arg, '.')) || (p = strchr(arg, ',')))
+ u = atoi(p + 1);
+
+ s = atoi(arg);
+ mm_advertise_freq = s * APR_USEC_PER_SEC + u * APR_TIME_C(1000);
+ if (mm_advertise_freq == 0)
+ return "Invalid AdvertiseFrequency value";
+
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* AdvertiseSecurityKey directive */
+/* */
+/*--------------------------------------------------------------------------*/
+static const char *mm_cmd_advertise_k(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ const char *errs = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+ if (errs != NULL)
+ return errs;
+ mm_advertise_skey = apr_pstrdup(cmd->pool, arg);
+ return NULL;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Manager Status module provider. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_status_hook(request_rec *r, int flags)
+{
+ mm_server_conf_t *mmsc = MM_SRVCONF(r);
+
+ if (flags & AP_STATUS_SHORT || mmsc->status == mm_status_off)
+ return OK;
+
+ ap_rputs("<hr />\n<h1>Manager Status</h1>\n", r);
+ ap_rputs("<table border=\"0\">\n", r);
+ ap_rvputs(r, "<tr><td>Database Root:</td><td>",
+ mm_database_root ? mm_database_root : "-",
+ "</td></tr>\n", NULL);
+ ap_rvputs(r, "<tr><td>Database Path:</td><td>",
+ mmgd->database_path ? mmgd->database_path : "-",
+ "</td></tr>\n", NULL);
+ ap_rvputs(r, "<tr><td>Handle Uri:</td><td>",
+ mmsc->handle ? mmsc->handle : "-",
+ "</td></tr>\n", NULL);
+ ap_rvputs(r, "<tr><td>ServerAdvertise:</td><td>",
+ mm_advertise_str[mm_advertise_mode],
+ "</td></tr>\n", NULL);
+ ap_rputs("</table>\n", r);
+ if (mmsc->status != mm_status_full)
+ return OK;
+
+ /* TODO: Add more statistical data
+ * for Full status.
+ */
+
+ return OK;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Pre config hook. */
+/* Hook our status provider to Status module */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_pre_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
+ apr_pool_t *ptemp)
+{
+ APR_OPTIONAL_HOOK(ap, status_hook, mm_status_hook,
+ NULL, NULL, APR_HOOK_MIDDLE);
+ mm_callback_initialize(pconf);
+
+ return OK;
+}
+
+static void * APR_THREAD_FUNC mm_mp_thread(apr_thread_t *thd, void *data)
+{
+ int f_time = 1;
+ apr_interval_time_t a_step = 0;
+ server_rec *s = (server_rec *)data;
+ is_mp_created = 1;
+
+ while (is_mp_running) {
+ apr_sleep(MM_TM_RESOLUTION);
+ if (!is_mp_running)
+ break;
+ if (mm_advertise_run) {
+ a_step += MM_TM_RESOLUTION;
+ if (a_step >= mm_advertise_freq || f_time) {
+ /* Run advertise */
+ mm_advertise_callback_run(mmdb_manager_rec->advertise_mode,
+ mmdb_manager_rec,
+ mm_advertise_server_cb);
+ a_step = 0;
+ f_time = 0;
+ }
+ }
+ if (!is_mp_running)
+ break;
+ /* Maintain database.
+ * Add new memory segments if requested from client
+ */
+ mmdb_maintain(s);
+ /* TODO: Implement actual work for parent thread */
+ if (!is_mp_running)
+ break;
+ }
+ is_mp_created = 0;
+ return NULL;
+}
+
+static void * APR_THREAD_FUNC mm_mc_thread(apr_thread_t *thd, void *data)
+{
+ int step = 0;
+ server_rec *s = (server_rec *)data;
+ is_mc_created = 1;
+
+ while (is_mc_running) {
+ apr_sleep(MM_TM_RESOLUTION);
+ if (!is_mc_running)
+ break;
+ if (++step >= MM_TM_MAINTAIN_STEP) {
+ mm_maintain_callback_run(mm_maintain_full);
+ step = 0;
+ }
+ else
+ mm_maintain_callback_run(mm_maintain_step);
+ /* TODO: Implement actual work for client thread */
+ if (!is_mc_running)
+ break;
+ }
+ is_mc_created = 0;
+ return NULL;
+}
+
+static apr_status_t mm_pconfig_cleanup(void *data);
+
+static apr_status_t mm_process_cleanup(void *data)
+{
+ int advertise_run = mm_advertise_run;
+
+ is_mp_running = 0;
+ mm_advertise_run = 0;
+ if (advertise_run && mmdb_manager_rec->advertise) {
+ mmdb_manager_rec->type = MM_ADVERTISE_STATUS;
+ mmdb_manager_rec->status = HTTP_FORBIDDEN;
+ mm_advertise_callback_run(mm_advertise_status, mmdb_manager_rec,
+ mm_advertise_server_cb);
+ }
+ if (is_mp_created) {
+ apr_sleep(1000);
+ /* Wait for the parent maintenance thread to finish */
+ while (is_mp_created) {
+ apr_sleep(MM_TM_RESOLUTION);
+ }
+ }
+ if (advertise_run && mmdb_manager_rec->advertise) {
+ mmdb_manager_rec->type = MM_ADVERTISE_STATUS;
+ mmdb_manager_rec->status = HTTP_GONE;
+ mm_advertise_callback_run(mm_advertise_status, mmdb_manager_rec,
+ mm_advertise_server_cb);
+ mma_group_leave();
+ }
+ /* We don't need the post_config cleanup to run,
+ */
+ apr_pool_cleanup_kill(mmgd->cpool, mmgd, mm_pconfig_cleanup);
+ if (mmgd->database_path) {
+ mmdb_close();
+ apr_dir_remove(mmgd->database_path, NULL);
+ }
+ mmgd = NULL;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t mm_pconfig_cleanup(void *data)
+{
+ int advertise_run = mm_advertise_run;
+
+ is_mp_running = 0;
+ mm_advertise_run = 0;
+ if (advertise_run && mmdb_manager_rec->advertise) {
+ mmdb_manager_rec->type = MM_ADVERTISE_STATUS;
+ mmdb_manager_rec->status = HTTP_FORBIDDEN;
+ mm_advertise_callback_run(mm_advertise_status, mmdb_manager_rec,
+ mm_advertise_server_cb);
+ }
+
+ if (is_mp_created) {
+ apr_sleep(1000);
+ /* Wait for the parent maintenance thread to finish */
+ while (is_mp_created) {
+ apr_sleep(MM_TM_RESOLUTION);
+ }
+ }
+ if (advertise_run && mmdb_manager_rec->advertise) {
+ mmdb_manager_rec->type = MM_ADVERTISE_STATUS;
+ mmdb_manager_rec->status = HTTP_LOCKED;
+ mm_advertise_callback_run(mm_advertise_status, mmdb_manager_rec,
+ mm_advertise_server_cb);
+ mma_group_leave();
+ }
+ if (mmgd) {
+ /* Remove the process_cleanup.
+ * We need to reattach again because the
+ * module can be reloaded on different address
+ */
+ apr_pool_cleanup_kill(mmgd->ppool, mmgd, mm_process_cleanup);
+ }
+ return APR_SUCCESS;
+}
+
+
+static apr_status_t mm_cconfig_cleanup(void *data)
+{
+
+ is_mc_running = 0;
+
+ while (is_mc_created) {
+ /* Wait for the child maintenance thread to finish */
+ apr_sleep(MM_TM_RESOLUTION);
+ }
+ if (mmgd->database_path) {
+ mmdb_close();
+ }
+ return APR_SUCCESS;
+}
+
+/* Server advertise data provider */
+static apr_status_t advertise_server(mm_advertise_e mode, void *context,
+ char *data, apr_size_t size)
+{
+ apr_size_t n = 0;
+ mm_advertise_srv_t *s = (mm_advertise_srv_t *)context;
+ if (mode == mm_advertise_status)
+ return APR_SUCCESS;
+ n = apr_snprintf(data, size,
+ "X-Manager-Address: %s:%u" CRLF
+ "X-Manager-Url: %s" CRLF
+ "X-Manager-Protocol: %s" CRLF
+ "X-Manager-Version: " MM_MCMP_VERSION_STRING CRLF
+ "X-Manager-Host: %s" CRLF,
+ s->address, s->port,
+ s->handle,
+ s->protocol,
+ s->server->server_hostname);
+ if (n >= size)
+ return APR_EOF;
+ else
+ return APR_SUCCESS;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Post config hook. */
+/* Create management thread in parent and initializes Manager */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_post_config_hook(apr_pool_t *pconf, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ apr_status_t rv;
+ const char *pk = "manager_init_module_tag";
+ const char *lk = "manager_gmutex_name_tag";
+ apr_pool_t *pproc = s->process->pool;
+ apr_thread_t *tp;
+ mm_server_conf_t *mmsc = MM_GETCONF(s);
+#if !defined(WIN32)
+ mode_t mmode;
+#endif
+
+ apr_pool_userdata_get((void *)&mmgd, pk, pproc);
+ if (!mmgd) {
+ if (!(mmgd = apr_pcalloc(pproc, sizeof(mm_global_data_t))))
+ return apr_get_os_error();
+ apr_pool_create(&mmgd->ppool, pproc);
+ apr_pool_userdata_set(mmgd, pk, apr_pool_cleanup_null, pproc);
+ /* First time config phase -- skip. */
+ return OK;
+ }
+#if defined(WIN32)
+ {
+ const char *ppid = getenv("AP_PARENT_PID");
+ if (ppid) {
+ mm_parent_pid = atol(ppid);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "[%" APR_PID_T_FMT " - %" APR_PID_T_FMT
+ "] in child post config hook",
+ getpid(), mm_parent_pid);
+ return OK;
+ }
+ }
+#endif
+
+ /* Initialize parent data */
+ if (!mm_database_root)
+ mm_database_root = ap_server_root_relative(pconf, MM_DEFAULT_DBROOT);
+ if (!mm_lock_filename)
+ mm_lock_filename = apr_pstrcat(pconf, mm_database_root,
+ MM_LOCK_NAME, NULL);
+
+ apr_pool_userdata_get((void *)&mm_manager_mutex, lk, pproc);
+ if (!mm_manager_mutex) {
+ if ((rv = apr_global_mutex_create(&mm_manager_mutex,
+ mm_lock_filename,
+ APR_LOCK_DEFAULT,
+ pproc)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: could not create global mutex: %s",
+ mm_lock_filename);
+ return rv;
+
+ }
+#ifdef AP_NEED_SET_MUTEX_PERMS
+ rv = unixd_set_global_mutex_perms(mm_manager_mutex);
+ if (rv != APR_SUCCESS) {
+ apr_global_mutex_destroy(mm_manager_mutex);
+ mm_manager_mutex = NULL;
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: could not modify global mutex: %s",
+ mm_lock_filename);
+ return rv;
+ }
+#endif
+ apr_pool_userdata_set(mm_manager_mutex, lk, apr_pool_cleanup_null, pproc);
+ }
+ if (!mmgd->database_path) {
+#if !defined(WIN32)
+ mmode = umask(022);
+#endif
+ mmgd->database_path = ap_append_pid(pproc, mm_database_root, "/");
+ rv = apr_dir_make(mmgd->database_path, APR_FPROT_OS_DEFAULT, pconf);
+ if (rv != APR_SUCCESS) {
+ if (!APR_STATUS_IS_EEXIST(rv)) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: could not create database root
%s.",
+ mmgd->database_path);
+ return rv;
+ }
+ }
+ }
+#if !defined(WIN32)
+ /* Allow attaching from child processes
+ * when parent is running as root
+ */
+ umask(0);
+#endif
+ if ((rv = mmdb_create(mmgd->database_path, pproc)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: could not create database at %s",
+ mmgd->database_path);
+ return rv;
+ }
+ else
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "mod_manager: shared memory database created at %s",
+ mmgd->database_path);
+#if !defined(WIN32)
+ umask(mmode);
+#endif
+ /* Init database */
+ if (mmgd->generation)
+ mm_run_resource_providers(mmsc, mm_resource_open, pproc);
+ else
+ mm_run_resource_providers(mmsc, mm_resource_init, pproc);
+ if (!(mmdb_manager_rec = asmm_slot(mmdb_table_getn(MMDB_MANAGER), 0))) {
+ rv = apr_get_os_error();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: Manager database record");
+ return rv;
+ }
+
+ if (!mmgd->generation) {
+ /* Favor dynamic configuration */
+ mmdb_manager_rec->strict = mm_manager_strict;
+ if (mm_advertise_skey) {
+ apr_md5_ctx_t mc;
+ apr_md5_init(&mc);
+ apr_md5_update(&mc, mm_advertise_skey, strlen(mm_advertise_skey));
+ apr_md5_final(mmdb_manager_rec->ssalt, &mc);
+ }
+ }
+
+ /* Check if we have advertise set */
+ if (mm_advertise_mode != mm_advertise_off && mm_advertise_set)
+ mm_advertise_run = 1;
+
+ /* Figure out the advertise address if not set */
+ if (mm_advertise_run && !mm_advertise_srvs) {
+ /* Figure out the Listening address */
+ ap_listen_rec *lr;
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ if (!lr->active)
+ continue;
+ if (IS_INADDR_ANY(lr->bind_addr))
+ continue;
+#if APR_HAVE_IPV6
+ if (IS_IN6ADDR_ANY(lr->bind_addr))
+ continue;
+#endif
+ apr_sockaddr_ip_get(&mm_advertise_srvs, lr->bind_addr);
+ mm_advertise_srvp = lr->bind_addr->port;
+ mm_advertise_srvm = (char *)lr->protocol;
+ if (mm_advertise_srvs &&
+ !strcmp(mm_advertise_srvs, "127.0.0.1") &&
+ !strcmp(mm_advertise_srvs, "::1")) {
+ mm_advertise_srvs = NULL;
+ continue;
+ }
+ else
+ break;
+ }
+ if (!mm_advertise_srvs) {
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ if (!lr->active)
+ continue;
+ if (IS_INADDR_ANY(lr->bind_addr)) {
+ apr_sockaddr_ip_get(&mm_advertise_srvs, lr->bind_addr);
+ mm_advertise_srvp = lr->bind_addr->port;
+ break;
+ }
+ }
+ }
+ if (!mm_advertise_srvs) {
+ /* Use the first one, and hope the admin configured
+ * httpd correctly.
+ */
+ apr_sockaddr_ip_get(&mm_advertise_srvs, ap_listeners->bind_addr);
+ mm_advertise_srvp = ap_listeners->bind_addr->port;
+ mm_advertise_srvm = (char *)ap_listeners->protocol;
+ }
+ }
+ if (mm_advertise_run) {
+ rv = mma_group_join(mm_advertise_adrs, mm_advertise_port, pconf);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+ "mod_manager: multicast join failed for %s:%d.",
+ mm_advertise_adrs, mm_advertise_port);
+ mm_advertise_run = 0;
+ }
+ }
+ memset(&mm_advs_server, 0, sizeof(mm_advertise_srv_t));
+
+ if (mm_advertise_run) {
+ server_rec *su = s;
+ server_rec *sr = s;
+ /* Setup Advertise info data */
+ if (mmsc->handle && !strcmp(mmsc->handle, MM_DEFAULT_HANDLE)) {
+ while (sr->next) {
+ mm_server_conf_t *mc = MM_GETCONF(sr->next);
+ sr = sr->next;
+ if (mc->handle_set && mc->handle) {
+ mmsc = mc;
+ su = sr;
+ break;
+ }
+ }
+ }
+ mmdb_manager_rec->advertise_mode = mm_advertise_mode;
+ mmdb_manager_rec->type = MM_ADVERTISE_SERVER;
+ mm_advs_server.address = mm_advertise_srvs;
+ mm_advs_server.port = mm_advertise_srvp;
+ mm_advs_server.protocol = mm_advertise_srvm;
+ mm_advs_server.server = su;
+ if (mmsc->handle_set && mmsc->handle)
+ mm_advs_server.handle = mmsc->handle;
+ else
+ mm_advs_server.handle = mmdb_manager_rec->srvid;
+ mm_register_advertise_callback(pconf, &mm_advs_server,
+ advertise_server);
+ }
+ mmdb_manager_rec->status = HTTP_OK;
+ mmdb_manager_rec->advertise = mm_advertise_run;
+ mmdb_manager_rec->generation = mmgd->generation;
+ /* Create parent management thread */
+ is_mp_running = 1;
+ rv = apr_thread_create(&tp, NULL, mm_mp_thread, s, pconf);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: parent apr_thread_create");
+ return rv;
+ }
+ apr_thread_detach(tp);
+
+ /* Create cleanup pool that will be destroyed first
+ * in future use new apr_pool_pre_cleanup_register from APR 1.3
+ */
+ apr_pool_create(&mmgd->cpool, pconf);
+ apr_pool_cleanup_register(mmgd->cpool, mmgd, mm_pconfig_cleanup,
+ apr_pool_cleanup_null);
+ if (mmgd->generation++) {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,
+ "Manager/%d reinitialized for process %" APR_PID_T_FMT,
+ MM_MMN, getpid());
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, s,
+ "Manager/%d initialized for process %" APR_PID_T_FMT,
+ MM_MMN, getpid());
+ }
+
+ apr_pool_cleanup_register(mmgd->ppool, mmgd, mm_process_cleanup,
+ apr_pool_cleanup_null);
+ return OK;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Child init hook. */
+/* Create management thread in child and initializes Manager in child */
+/* */
+/*--------------------------------------------------------------------------*/
+static void mm_child_init_hook(apr_pool_t *p, server_rec *s)
+{
+ apr_status_t rv;
+ apr_pool_t *cp;
+ apr_thread_t *tp;
+ mm_server_conf_t *mmsc = MM_GETCONF(s);
+
+#if !defined(WIN32)
+ /* Win32 parent pid was determined in
+ * post config hook.
+ * Use getppid() for posix.
+ */
+ mm_parent_pid = getppid();
+#endif
+ if (mm_parent_pid == -1) {
+#if !defined(WIN32)
+ rv = apr_get_os_error();
+#else
+ rv = APR_EBADF;
+#endif
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: parent pid");
+ return;
+ }
+ mm_child_started = apr_time_now();
+ /* Initialize child data */
+ if (!mmgd)
+ mmgd = apr_pcalloc(p, sizeof(mm_global_data_t));
+
+ if (!mm_database_root)
+ mm_database_root = ap_server_root_relative(p, MM_DEFAULT_DBROOT);
+ mm_lock_filename = apr_pstrcat(p, mm_database_root, MM_LOCK_NAME, NULL);
+ if ((rv = apr_global_mutex_child_init(&mm_manager_mutex,
+ mm_lock_filename,
+ p)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: could not open global mutex: %s",
+ mm_lock_filename);
+ return;
+ }
+ mmgd->database_path = apr_psprintf(p, "%s/%" APR_PID_T_FMT,
+ mm_database_root, mm_parent_pid);
+ if ((rv = mmdb_open(mmgd->database_path, p)) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, NULL,
+ "mod_manager: could not open database at %s.",
+ mmgd->database_path);
+ mmgd->database_path = NULL;
+ return;
+ }
+ /* Init database */
+ mm_run_resource_providers(mmsc, mm_resource_child_init, p);
+ if (!(mmdb_manager_rec = asmm_slot(mmdb_table_getn(MMDB_MANAGER), 0))) {
+ rv = apr_get_os_error();
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: Manager database record missing");
+ return;
+ }
+ /* Remember generation so we can check later
+ * if we are dormant child process.
+ */
+ mm_generation = mmdb_manager_rec->generation;
+ /* Create parent management thread */
+ is_mc_running = 1;
+ rv = apr_thread_create(&tp, NULL, mm_mc_thread, s, p);
+ if (rv != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
+ "mod_manager: child apr_thread_create");
+ return;
+ }
+ apr_thread_detach(tp);
+ apr_pool_create(&cp, p);
+ apr_pool_cleanup_register(cp, s, mm_cconfig_cleanup,
+ apr_pool_cleanup_null);
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+ "initialized child %" APR_PID_T_FMT
+ " from parent process %" APR_PID_T_FMT,
+ getpid(), mm_parent_pid);
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Post read request handler hook. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_post_read_request_hook(request_rec *r)
+{
+ const char *path_cmd = NULL;
+ mm_server_conf_t *mmsc = MM_SRVCONF(r);
+
+ if (!is_mc_running)
+ return DECLINED;
+
+ return DECLINED;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Translate name handler hook. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_translate_name_hook(request_rec *r)
+{
+ const char *path_cmd = NULL;
+ mm_server_conf_t *mmsc = MM_SRVCONF(r);
+
+ if (!is_mc_running)
+ return DECLINED;
+
+ return DECLINED;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Map to storage handler hook. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_map_to_storage_hook(request_rec *r)
+{
+ const char *path_cmd = NULL;
+ mm_server_conf_t *mmsc = MM_SRVCONF(r);
+
+ if (!is_mc_running)
+ return DECLINED;
+
+ if (mmdb_manager_rec->generation != mm_generation) {
+ /* XXX: See if this can actually happen or not */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: generation missmatch detected -- "
+ "declining map to storage.");
+ return DECLINED;
+ }
+
+
+ if (mmsc->handle_set && mmsc->handle && mmsc->server ==
r->server &&
+ !strncmp(r->uri, mmsc->handle, strlen(mmsc->handle))) {
+ /* Check if we have /foo or /foo/ */
+ if (r->uri[strlen(mmsc->handle)] == '\0' ||
+ r->uri[strlen(mmsc->handle)] == '/') {
+ r->handler = mm_handler_name;
+ return OK;
+ }
+ }
+ else if (!strncmp(r->uri, mmdb_manager_rec->srvid,
+ APR_UUID_FORMATTED_LENGTH)) {
+ if (r->uri[APR_UUID_FORMATTED_LENGTH + 1] == '\0' ||
+ r->uri[APR_UUID_FORMATTED_LENGTH + 1] == '/') {
+ r->handler = mm_handler_name;
+ return OK;
+ }
+ }
+
+ /* Stage 1: Find the Host */
+
+ /* Stage 2: Find the Application */
+
+ /* Stage 3: Find the Balancer */
+
+ return DECLINED;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Manager request handler hook. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_handler_manager(request_rec *r)
+{
+ apr_status_t rc;
+ int status = OK;
+ int pi = 0;
+ const char *cmd = NULL;
+ const char *header = NULL;
+ const apr_array_header_t *ca;
+ apr_table_entry_t *ce;
+ apr_table_t *ctb;
+ mm_server_conf_t *mmsc = MM_SRVCONF(r);
+
+ ap_set_content_type(r, "text/plain");
+ /*
+ * If we're only supposed to send header information (HEAD request), we're
+ * already there.
+ */
+ if (r->header_only) {
+ return OK;
+ }
+
+ if (mmsc->handle_set && mmsc->handle)
+ pi = ap_find_path_info(mmsc->handle, r->uri);
+ else
+ pi = ap_find_path_info(mmdb_manager_rec->srvid, r->uri);
+ if (pi > 0) {
+ cmd = r->uri + pi + 1;
+ if (!strlen(cmd))
+ cmd = NULL;
+ }
+ ctb = apr_table_make(r->pool, 15);
+ apr_table_setn(ctb, MMS_COOKIE_COMMAND, "");
+ /* Parse Header */
+ if ((header = apr_table_get(r->headers_in, MM_RESHEADER_NAME))) {
+ if ((rc = mmc_cookie_parse(ctb, header, r->pool)) != APR_SUCCESS) {
+ /* Deal with error in parser */
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: parsing " MM_RESHEADER_NAME
+ " header: %s", header);
+ mm_send_response_ex(r, mm_response_error, rc, NULL);
+ return OK;
+ }
+ }
+ /* Parse Query arguments */
+ if (r->args) {
+ if ((status = ap_unescape_url_keep2f(r->args)) != OK) {
+ /* Deal with error in query arguments */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: unescaping request arguments: %s",
+ r->args);
+ return OK;
+ }
+ if ((rc = mmc_cookie_parse(ctb, r->args, r->pool)) != APR_SUCCESS) {
+ /* Deal with error in parser */
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: parsing request arguments: %s",
+ r->args);
+ mm_send_response_ex(r, mm_response_error, rc, NULL);
+ return OK;
+ }
+ }
+ /* Always favor the path info command */
+ if (cmd)
+ apr_table_setn(ctb, MMS_COOKIE_COMMAND, cmd);
+ else if ((header = apr_table_get(r->headers_in, MM_CMDHEADER_NAME)))
+ apr_table_setn(ctb, MMS_COOKIE_COMMAND, header);
+
+ cmd = apr_table_get(ctb, MMS_COOKIE_COMMAND);
+ if (*cmd == '\0') {
+ /* No command present.
+ * Report Protocol version and exit
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: " MMS_COOKIE_COMMAND " not
present");
+ mm_send_response_ex(r, mm_response_version, 0, NULL);
+ return OK;
+ }
+ if ((mcmp_command_type = mm_mcmp_command_get(cmd)) == mm_mcmp_unknown) {
+ /* Unknown command detected.
+ * Report Protocol version and exit
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown " MMS_COOKIE_COMMAND ":
%s", cmd);
+ mm_send_response_ex(r, mm_response_version, 0, NULL);
+ return OK;
+ }
+ apr_table_unset(ctb, MMS_COOKIE_COMMAND);
+ if (mcmp_command_type != mm_mcmp_info) {
+ /* Lock the database for commands
+ * that can change the database
+ */
+ if ((rc = mm_manager_dolock()) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
+ "mod_manager: locking database");
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
+ }
+ /* Run parser */
+ ca = apr_table_elts(ctb);
+ ce = (apr_table_entry_t *)ca->elts;
+ if (ca->nelts) {
+ /* The first key should be ResourceType
+ * and val is ResourceType name
+ */
+ const char *rt = ce[0].key;
+ const char *rn = ce[0].val;
+ mm_resource_provider_t *rp;
+
+ if (apr_fnmatch_test(rt)) {
+ int rcnt = 0;
+ mm_resource_list_t *rl;
+ rl = mm_list_resource_providers(r->pool);
+ if (!rl) {
+ /* We should have at least one resouce
+ */
+ mm_send_response_ex(r, mm_response_version, 0, NULL);
+ goto cleanup;
+ }
+ while ((rp = rl->provider) != NULL) {
+ int exe_provider = 1;
+ if (rp->id == MMDB_SERVER || rp->id == MMDB_MANAGER) {
+ ap_rvputs(r, "@", rp->name, NULL);
+ if (ca->nelts > 1)
+ ap_rputs(": ", r);
+ else {
+ ap_rputs(CRLF, r);
+ exe_provider = 0;
+ }
+ }
+ if (rp->id == MMDB_APPLICATION)
+ exe_provider = 0;
+ if (exe_provider &&
+ apr_fnmatch(rt, rp->name, MM_FFNMATCH) == APR_SUCCESS) {
+ /* We have a matching resource type */
+ rc = (*rp->func)(mmsc,
+ mcmp_command_type,
+ rn, NULL, 0, NULL,
+ ctb, 1, r);
+ if (rc != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: resource provider: %s",
+ rp->name);
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ goto cleanup;
+ }
+ rcnt++;
+ }
+ if (!rl->next)
+ break;
+ rl = rl->next;
+ }
+ if (!rcnt) {
+ /* No Resources matches.
+ * Report Unknown resource type and exit
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: no resource matches : %s", rt);
+ mm_send_response_ex(r, mm_response_utype, 0, rt, NULL);
+ goto cleanup;
+ }
+ }
+ else if (!(rp = mm_lookup_resource_provider(rt))) {
+ /* Unknown resource detected.
+ * Report Unknown resource type and exit
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown resource type : %s", rt);
+ mm_send_response_ex(r, mm_response_utype, 0, rt, NULL);
+ goto cleanup;
+ }
+ else {
+ rc = (*rp->func)(mmsc, mcmp_command_type,
+ rn, NULL, 0, NULL, ctb, 1, r);
+ if (rc != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server,
+ "mod_manager: resource provider: %s",
+ rp->name);
+ status = HTTP_INTERNAL_SERVER_ERROR;
+ goto cleanup;
+ }
+ }
+ }
+ else {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: missing resource type");
+ }
+ /* Update the advertise mode */
+ if (mmdb_manager_rec->advertise_mode != mm_advertise_off) {
+ mmdb_manager_rec->type = MM_ADVERTISE_STATUS;
+ mmdb_manager_rec->status = HTTP_OK;
+ mmdb_manager_rec->advertise_mode = mm_advertise_status;
+ }
+cleanup:
+ if (mcmp_command_type != mm_mcmp_info) {
+ /* Unlock the Manager */
+ mm_manager_unlock();
+ }
+ return status;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Request handler hook. */
+/* */
+/*--------------------------------------------------------------------------*/
+static int mm_handler_hook(request_rec *r)
+{
+ if (!is_mc_running)
+ return DECLINED;
+ if (mmdb_manager_rec->generation != mm_generation) {
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: generation missmatch detected -- "
+ "declining request.");
+ return DECLINED;
+ }
+ /* Is this for us? */
+ if (!strcasecmp(r->handler, mm_handler_name))
+ return mm_handler_manager(r);
+
+ return DECLINED;
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* List of directives specific to our module. */
+/* */
+/*--------------------------------------------------------------------------*/
+static const command_rec mm_cmds[] =
+{
+ AP_INIT_TAKE1(
+ "ManagerStatus", /* directive name */
+ mm_cmd_status, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Manager status to one of: On | Off | Full"
+ ),
+ AP_INIT_TAKE1(
+ "ManagerDatabaseRoot", /* directive name */
+ mm_cmd_dbroot, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Path where the Manager database will be created"
+ ),
+ AP_INIT_TAKE1(
+ "ManagerHandle", /* directive name */
+ mm_cmd_handle, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF|ACCESS_CONF, /* where available */
+ "Uri on which the Manager will handle directives."
+ ),
+ AP_INIT_FLAG(
+ "ManagerParseStrict", /* directive name */
+ mm_cmd_parse_strict, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "On for strict command parsing mode"
+ ),
+ AP_INIT_TAKE12(
+ "ServerAdvertise", /* directive name */
+ mm_cmd_advertise_m, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Server advertise mode: On | Off [Address]"
+ ),
+ AP_INIT_TAKE1(
+ "AdvertiseGroup", /* directive name */
+ mm_cmd_advertise_g, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Multicast group address"
+ ),
+ AP_INIT_TAKE1(
+ "AdvertiseFrequency", /* directive name */
+ mm_cmd_advertise_f, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Advertise frequency in seconds[.miliseconds]"
+ ),
+ AP_INIT_TAKE1(
+ "AdvertiseSecurityKey", /* directive name */
+ mm_cmd_advertise_k, /* config action routine */
+ NULL, /* argument to include in call */
+ RSRC_CONF, /* where available */
+ "Advertise security key"
+ ),
+ {NULL}
+
+};
+
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* Which functions are responsible for which hooks in the server. */
+/* */
+/*--------------------------------------------------------------------------*/
+static void mm_register_hooks(apr_pool_t *p)
+{
+
+ /* Fixup before and translate and after mod_rewrite.
+ */
+ static const char *const after_rewrite[] = { "mod_rewrite.c", NULL};
+ static const char *const before_rewrite[] = { "mod_rewrite.c", NULL};
+ static const char *const before_proxy[] = { "mod_proxy.c", NULL};
+
+ /* Only the mpm_winnt has child init hook handler.
+ * Make sure that we are called after the mpm child init handler
+ * initializes.
+ */
+ static const char *const after_mpm[] = { "mpm_winnt.c", NULL};
+
+ /* Pre config handling
+ */
+ ap_hook_pre_config(mm_pre_config_hook,
+ NULL,
+ NULL,
+ APR_HOOK_MIDDLE);
+
+ /* Post config handling
+ */
+ ap_hook_post_config(mm_post_config_hook,
+ NULL,
+ NULL,
+ APR_HOOK_LAST);
+
+ /* Child init hook
+ */
+ ap_hook_child_init(mm_child_init_hook,
+ after_mpm,
+ NULL,
+ APR_HOOK_MIDDLE);
+
+ /* Request handler hook
+ */
+ ap_hook_handler(mm_handler_hook,
+ NULL,
+ NULL,
+ APR_HOOK_MIDDLE);
+
+ /* Translate name handler hook
+ */
+ ap_hook_translate_name(mm_translate_name_hook,
+ after_rewrite,
+ NULL,
+ APR_HOOK_FIRST);
+
+ /* Post read request handler hook
+ */
+ ap_hook_post_read_request(mm_post_read_request_hook,
+ NULL,
+ before_proxy,
+ APR_HOOK_FIRST);
+
+ /* Map to storage handler hook
+ */
+ ap_hook_map_to_storage(mm_map_to_storage_hook,
+ NULL,
+ NULL,
+ APR_HOOK_FIRST);
+
+ /* Register resource objecst
+ */
+ mm_register_resource_manager(p);
+ mm_register_resource_server(p);
+ mm_register_resource_app_pool(p);
+ mm_register_resource_balancer(p);
+ mm_register_resource_host(p);
+ mm_register_resource_member(p);
+ mm_register_resource_application(p);
+
+}
+
+/*--------------------------------------------------------------------------*/
+/* */
+/* The list of callback routines and data structures that provide */
+/* the static hooks into our module from the other parts of the server. */
+/* */
+/*--------------------------------------------------------------------------*/
+module AP_MODULE_DECLARE_DATA manager_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* per-directory config creator */
+ NULL, /* dir config merger */
+ mm_create_server_config, /* server config creator */
+ mm_merge_server_config, /* server config merger */
+ mm_cmds, /* command table */
+ mm_register_hooks /* set up other request processing hooks */
+};
Property changes on: sandbox/aloha/httpd/modules/manager/mm_module.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_node.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_node.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_node.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,766 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Node object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+static int server_limit = 0;
+static int thread_limit = 0;
+static int max_clients = 0;
+static int max_childs = 0;
+static int max_requests_per_child = 0;
+static int max_threads_per_child = 0;
+
+static const char *member_params[] = {
+ "",
+ "Balancer",
+ "Type",
+ "Address",
+ "Port",
+ "Route",
+ "Domain",
+ "Ping",
+ "MaxConnections",
+ "MinConnections",
+ "MaxClients",
+ "TTL",
+ "LF",
+ "Distance",
+ "Activation",
+ "FlushMode",
+ "FlushTimeout",
+ /* Statistical data */
+ "State",
+ "Error",
+ "Busy",
+ "Connected",
+ "Elected",
+ "StickySessions",
+ "ClientErrors",
+ "NodeErrors",
+ "Trace",
+ "TraceErrors",
+ "Readed",
+ "Transferred",
+ NULL
+};
+
+static const char *get_balancer_name(apr_uint32_t id)
+{
+ mmdb_balancer_t *balancer;
+ asmm_slotmem_t *balancer_db = mmdb_table_getn(MMDB_BALANCER);
+
+ if ((balancer = asmm_slot(balancer_db, id))) {
+ return balancer->name;
+ }
+ return NULL;
+}
+
+static const char *get_flush_name(mm_flush_mode_e mode)
+{
+ switch(mode) {
+ case mm_flush_wait:
+ return "T";
+ break;
+ case mm_flush_auto:
+ return "A";
+ break;
+ }
+ return "N";
+}
+
+static mm_flush_mode_e get_flush_mode(const char *mode)
+{
+ switch(apr_toupper(*mode)) {
+ case 'T':
+ return mm_flush_wait;
+ break;
+ case 'A':
+ return mm_flush_auto;
+ break;
+ }
+ return mm_flush_none;
+}
+
+static apr_status_t add_app_members(apr_uint32_t member_id,
+ apr_uint32_t balancer_id)
+{
+ apr_uint32_t napp = 0;
+ apr_uint32_t nhost = 0;
+ mmdb_host_t *host;
+ mmdb_app_t *app;
+ mmdb_memberapp_t *memberapp;
+ asmm_slotmem_t *host_db = mmdb_table_getn(MMDB_HOST);
+ asmm_slotmem_t *app_db = mmdb_table_getn(MMDB_APPLICATION);
+ asmm_slotmem_t *memberapp_db = mmdb_table_getn(MMDB_MEMBERAPP);
+
+ while ((host = asmm_slot_next(host_db, &nhost))) {
+ if (host->balancer_id != balancer_id)
+ continue;
+ napp = 0;
+ while ((app = asmm_slot_next(app_db, &napp))) {
+ if (app->host_id != (nhost - 1))
+ continue;
+ if (!(memberapp = asmm_salloc(memberapp_db)))
+ return apr_get_os_error();
+ memberapp->app_id = napp - 1;
+ memberapp->member_id = member_id;
+ memberapp->state = app->state;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static void del_app_members(apr_uint32_t member_id)
+{
+ apr_uint32_t next = 0;
+ mmdb_memberapp_t *memberapp;
+ asmm_slotmem_t *memberapp_db = mmdb_table_getn(MMDB_MEMBERAPP);
+
+ while ((memberapp = asmm_slot_next(memberapp_db, &next))) {
+ if (memberapp->member_id != member_id)
+ continue;
+ asmm_free(memberapp_db, memberapp);
+ }
+}
+
+
+static void rdo_member_info_print(int pi, int pp,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ char buf[512];
+ const char *p;
+
+ if (pp) {
+ ap_rvputs(r, member_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* Balancer */
+ ap_rvputs(r, get_balancer_name(mem->balancer_id), NULL);
+ break;
+ case 2: /* Type */
+ ap_rputs(mm_protocol_name_get(mem->type), r);
+ break;
+ case 3: /* Address */
+ ap_rvputs(r, mem->address, NULL);
+ break;
+ case 4: /* Port */
+ ap_rprintf(r, "%u", mem->port);
+ break;
+ case 5: /* Route */
+ ap_rvputs(r, mem->route, NULL);
+ break;
+ case 6: /* Domain */
+ ap_rvputs(r, mem->domain, NULL);
+ break;
+ case 7: /* Ping */
+ ap_rprintf(r, "%u", mem->ping);
+ break;
+ case 8: /* MaxConnections */
+ ap_rprintf(r, "%u", mem->max_conn);
+ break;
+ case 9: /* MinConnections */
+ ap_rprintf(r, "%u", mem->min_conn);
+ break;
+ case 10: /* MaxClients */
+ ap_rprintf(r, "%u", mem->max_clients);
+ break;
+ case 11: /* TTL */
+ ap_rprintf(r, "%u", mem->ttl);
+ break;
+ case 12: /* LF */
+ ap_rprintf(r, "%u", mem->lf);
+ break;
+ case 13: /* Distance */
+ ap_rprintf(r, "%u", mem->distance);
+ break;
+ case 14: /* Activation */
+ ap_rputs(mm_state_name_get(mem->activation), r);
+ break;
+ case 15: /* FlushMode */
+ ap_rputs(get_flush_name(mem->flush), r);
+ break;
+ case 16: /* FlushTimeout */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
apr_time_as_msec(mem->flush_wait));
+ break;
+ case 17: /* State */
+ ap_rputs(mm_state_name_get(mem->state), r);
+ break;
+ case 18: /* Error */
+ if (!(p = mm_strerror(mem->err))) {
+ if (!(p = apr_strerror(mem->err, buf, sizeof(buf))))
+ p = "Unknown Error";
+ }
+ if (pp)
+ ap_rprintf(r, "\"%d: %s\"", mem->err, p);
+ else
+ ap_rprintf(r, "%d: %s", mem->err, p);
+ break;
+ case 19: /* Busy */
+ ap_rprintf(r, "%u", mem->busy);
+ break;
+ case 20: /* Connected */
+ ap_rprintf(r, "%u", mem->connected);
+ break;
+ case 21: /* Elected */
+ ap_rprintf(r, "%u", mem->elected);
+ break;
+ case 22: /* StickySessions */
+ ap_rprintf(r, "%u", mem->ssessions);
+ break;
+ case 23: /* ClientErrors */
+ ap_rprintf(r, "%u", mem->err_client);
+ break;
+ case 24: /* NodeErrors */
+ ap_rprintf(r, "%u", mem->err_node);
+ break;
+ case 25: /* Trace */
+ ap_rprintf(r, "%u", mem->trace);
+ break;
+ case 26: /* TraceErrors */
+ ap_rprintf(r, "%u", mem->err_trace);
+ break;
+ case 27: /* Readed */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->readed);
+ break;
+ case 28: /* Transferred */
+ ap_rprintf(r, "%" APR_UINT64_T_FMT, mem->transferred);
+ break;
+ }
+}
+
+/* Dump Member info */
+static void rdo_member_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (member_params[j]) {
+ if (apr_fnmatch(ce[i].key, member_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_member_info_print(m, wcm, mem, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (member_params[j]) {
+ if (apr_fnmatch(ce[i].key, member_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_member_info_print(j, 1, mem, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_member_info_print(j, 1, mem, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static apr_status_t rdo_member_config_do(int pi,
+ const char *value,
+ mmdb_member_t *mem,
+ request_rec *r)
+{
+ int i;
+
+ switch (pi) {
+ case 2: /* Type */
+ if (mem->state == mm_state_stopped)
+ mem->type = mm_protocol_get(value);
+ else
+ return MME_EPERM;
+ break;
+ case 3: /* Address */
+ if (mem->state == mm_state_stopped)
+ MM_SSAFE_COPY(mem->address, value);
+ else
+ return MME_EPERM;
+ break;
+ case 4: /* Port */
+ if (mem->state == mm_state_stopped)
+ mem->port = atoi(value);
+ else
+ return MME_EPERM;
+ break;
+ case 5: /* Route */
+ MM_SSAFE_COPY(mem->route, value);
+ break;
+ case 6: /* Domain */
+ MM_SSAFE_COPY(mem->domain, value);
+ break;
+ case 7: /* Ping */
+ mem->ping = atoi(value);
+ break;
+ case 8: /* MaxConnections */
+ i = atoi(value);
+ if (i < 1 || i > max_threads_per_child)
+ return MME_EINVAL;
+ else
+ mem->max_conn = i;
+ break;
+ case 9: /* MinConnections */
+ i = atoi(value);
+ if (i < 1 || i > (int)mem->max_conn)
+ return MME_EINVAL;
+ else
+ mem->min_conn = i;
+ break;
+ case 10: /* MaxClients */
+ i = atoi(value);
+ if (i < 1 || i > max_clients)
+ return MME_EINVAL;
+ else
+ mem->max_clients = i;
+ break;
+ case 11: /* TTL */
+ mem->ttl = atoi(value);
+ break;
+ case 12: /* LF */
+ mem->lf = atoi(value);
+ break;
+ case 13: /* Distance */
+ mem->distance = atoi(value);
+ break;
+ case 14: /* Activation */
+ mem->activation = mm_state_get(value);
+ break;
+ case 15: /* FlushMode */
+ mem->flush = get_flush_mode(value);
+ break;
+ case 16: /* FlushTimeout */
+ mem->flush_wait = atoi(value) * APR_TIME_C(1000);
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+/* Configure Member */
+static int rdo_member_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ apr_uint32_t member_id,
+ mmdb_member_t *member,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else {
+ while (member_params[j]) {
+ if (!strcasecmp(ce[i].key, member_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_member_config_do(j, ce[i].val,
+ member, r)) != APR_SUCCESS) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static apr_status_t rdo_member(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int wcm;
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+ apr_uint32_t next = 0;
+ mmdb_member_t *member;
+
+ asmm_slotmem_t *member_db = mmdb_table_getn(MMDB_MEMBER);
+
+ if (!member_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty member name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ }
+ wcm = apr_fnmatch_test(name);
+ while ((member = asmm_slot_next(member_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, member->name,
+ MM_FFNMATCH) != APR_SUCCESS)
+ continue;
+ }
+ else if (strcasecmp(name, member->name))
+ continue;
+ if (cmd_offset < ca->nelts) {
+ mm_resource_provider_t *mp =
mm_lookup_resource_provider(ce[cmd_offset].key);
+ if (mp) {
+ apr_status_t rc;
+ if (mp == this_provider) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] recursion not allowed:
%s",
+ mm_mcmp_command_name_get(cmd),
+ this_provider->name);
+ return APR_SUCCESS;
+ }
+ rc = (*mp->func)(cfg, cmd,
+ ce[cmd_offset].val, this_provider,
+ next - 1, member,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS) {
+ }
+ wdone++;
+ if (wcm)
+ continue;
+ else
+ break;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm) {
+ ap_rvputs(r, MM_RES_MEMBER "/", member->name, NULL);
+ if (cmd_offset < ca->nelts)
+ ap_rputs(": ", r);
+ else
+ ap_rputs(CRLF, r);
+ }
+ if (cmd_offset < ca->nelts)
+ rdo_member_info(cmd_table, cmd_offset, wcm, member, r);
+ break;
+ case mm_mcmp_enable:
+ member->state = mm_state_active;
+ member->activation = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ member->state = mm_state_disabled;
+ member->activation = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ member->state = mm_state_stopped;
+ member->activation = mm_state_stopped;
+ break;
+ case mm_mcmp_reset:
+ /* Reset statistical data */
+ member->elected = 0;
+ member->ssessions = 0;
+ member->err_client = 0;
+ member->err_node = 0;
+ member->err_trace = 0;
+ member->trace = 0;
+ member->readed = 0;
+ member->transferred = 0;
+ break;
+ case mm_mcmp_delete:
+ if (member->state != mm_state_stopped) {
+ /* Member must be stopped before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Member not stopped: %s",
+ member->name);
+ return APR_SUCCESS;
+ }
+ else {
+ /* Delete Member entry */
+ mmdb_balancer_t *pbal = NULL;
+ if (member->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ member->balancer_id);
+ del_app_members(next - 1);
+ asmm_free(member_db, member);
+ if (pbal && pbal->members)
+ pbal->members--;
+ }
+ break;
+ case mm_mcmp_config:
+ if (prev && prev->id == MMDB_BALANCER) {
+ mmdb_balancer_t *nbal = (mmdb_balancer_t *)prev_rec;
+ if (prev_id != member->balancer_id) {
+ mmdb_balancer_t *pbal = NULL;
+ if (member->balancer_id)
+ pbal = asmm_slot(mmdb_table_getn(MMDB_MEMBER),
+ member->balancer_id);
+ /* Attach the Member to another Balancer */
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "mod_manager: Member: %s assigned to "
+ "Balancer: %s",
+ member->name, nbal->name);
+ member->balancer_id = prev_id;
+ nbal->members++;
+ if (pbal && pbal->members)
+ pbal->members--;
+ }
+ }
+ if (rdo_member_config(cfg, cmd_table, cmd_offset,
+ next - 1, member, r))
+ return APR_SUCCESS;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Balancer",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_uint32_t member_id;
+ if (prev && prev->id != MMDB_BALANCER) {
+ mm_send_response_ex(r, mm_response_utype, 0, prev->name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: type %s in not balancer for "
+ "Member: %s",
+ prev->name, name);
+ return APR_SUCCESS;
+ }
+ if (!prev) {
+ /* Use _default_ balancer */
+ prev_id = 0;
+ }
+ /* Add new Member */
+ if (!(member = asmm_salloc_ex(member_db, &member_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY(member->name, name);
+ member->balancer_id = prev_id;
+ member->state = mm_state_stopped;
+ member->activation = mm_state_stopped;
+ member->lf = 1;
+ member->max_conn = max_threads_per_child;
+ member->min_conn = max_threads_per_child;
+ member->max_clients = max_clients;
+ /* Update Member from provided params */
+ if (rdo_member_config(cfg, cmd_table, cmd_offset,
+ member_id, member, r)) {
+ /* There was an error during initial config
+ * Delete member we created
+ */
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: failed creating member: %s",
+ name);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ }
+ if (!member->route[0])
+ strcpy(member->route, member->name);
+ if (!member->address[0])
+ strcpy(member->address, MM_DEFAULT_ADDRESS);
+ if (member->type == mm_protocol_unknown)
+ member->type = MM_DEFAULT_PROTOCOL;
+ if (!member->port) {
+ switch (member->type) {
+ case mm_protocol_ajp:
+ member->port = MM_DEFAULT_AJP_PORT;
+ break;
+ case mm_protocol_http:
+ member->port = MM_DEFAULT_HTTP_PORT;
+ break;
+ case mm_protocol_https:
+ member->port = MM_DEFAULT_HTTPS_PORT;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error,
+ MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: Unknown protocol %d for "
+ "Member: %s",
+ member->type, member->name);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ break;
+ }
+ }
+ if (member->min_conn > member->max_conn)
+ member->min_conn = member->max_conn;
+ member->state = mm_state_stopped;
+ /* Add Applications linked to the Member's Balancer */
+ if (add_app_members(member_id, member->balancer_id) != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
+ "mod_manager: adding MemberApplication for: %s",
+ member->name);
+ del_app_members(member_id);
+ asmm_free(member_db, member);
+ return APR_SUCCESS;
+ }
+ if (prev_rec) {
+ ((mmdb_balancer_t *)prev_rec)->members++;
+ }
+ }
+ else {
+ mm_send_response_ex(r, mm_response_utype, 0, MM_RES_MEMBER "/",
+ name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown member: %s", name);
+ return APR_SUCCESS;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ if (!prev)
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_member_init(mm_server_conf_t *cfg)
+{
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests_per_child);
+ ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_childs);
+ if (max_childs < 1)
+ max_childs = 1;
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
+ if (max_threads_per_child < 1)
+ max_threads_per_child = 1;
+ max_clients = max_childs * max_threads_per_child;
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_member(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ case mm_resource_open:
+ case mm_resource_child_init:
+ return rdo_member_init(cfg);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a Member */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t member_provider = {
+ MMDB_MEMBER,
+ MM_RES_MEMBER,
+ rdo_member,
+ ini_member,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_member(apr_pool_t *pool)
+{
+ this_provider = &member_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_node.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_pool.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_pool.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_pool.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,504 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager ApplicationPool object resource routines */
+#include "mm_api.h"
+
+static mm_resource_provider_t *this_provider = NULL;
+static int server_limit = 0;
+static int thread_limit = 0;
+static int max_clients = 0;
+static int max_childs = 0;
+static int max_requests_per_child = 0;
+static int max_threads_per_child = 0;
+
+static const char *app_pool_params[] = {
+ "",
+ "Status",
+ "Busy",
+ "Concurrency",
+ "TimeOut",
+ "Applications",
+ NULL
+};
+
+static void rdo_app_pool_info_print(int pi, int pp,
+ mmdb_app_pool_t *ap,
+ request_rec *r)
+{
+ if (pp) {
+ ap_rvputs(r, app_pool_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* Status */
+ ap_rputs(mm_state_name_get(ap->status), r);
+ break;
+ case 2: /* Busy */
+ ap_rprintf(r, "%d", ap->busy);
+ break;
+ case 3: /* Concurrency */
+ ap_rprintf(r, "%d", ap->concurrency);
+ break;
+ case 4: /* TimeOut */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
apr_time_as_msec(ap->timeout));
+ break;
+ case 5: /* Applications */
+ ap_rprintf(r, "%d", ap->applications);
+ break;
+ }
+}
+
+/* Dump ApplicationPool info */
+static void rdo_app_pool_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ int wcm,
+ mmdb_app_pool_t *bal,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (app_pool_params[j]) {
+ if (apr_fnmatch(ce[i].key, app_pool_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (app_pool_params[j]) {
+ if (!strcasecmp(ce[i].key, app_pool_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_app_pool_info_print(m, wcm, bal, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ int sep = 0;
+ /* Multiple params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (app_pool_params[j]) {
+ if (apr_fnmatch(ce[i].key, app_pool_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_app_pool_info_print(j, 1, bal, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (app_pool_params[j]) {
+ if (!strcasecmp(ce[i].key, app_pool_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_app_pool_info_print(j, 1, bal, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static int app_pool_exist(const char *value, mmdb_app_pool_t **ap)
+{
+ apr_uint32_t next = 0;
+ mmdb_app_pool_t *app_pool;
+ asmm_slotmem_t *app_pool_db = mmdb_table_getn(MMDB_APP_POOL);
+
+ while ((app_pool = asmm_slot_next(app_pool_db, &next))) {
+ if (strcasecmp(value, app_pool->name))
+ continue;
+ *ap = app_pool;
+ return 1;
+ }
+ return 0;
+}
+
+static apr_status_t rdo_app_pool_config_do(int pi,
+ const char *value,
+ mmdb_app_pool_t *ap,
+ request_rec *r)
+{
+ switch (pi) {
+ case 1: /* Status */
+ ap->status = mm_state_get(value);
+ break;
+ case 3: /* Concurrency */
+ ap->concurrency = atoi(value);
+ break;
+ case 4: /* TimeOut */
+ ap->timeout = APR_TIME_C(1000) * atoi(value);
+ break;
+ default:
+ return MME_EPERM;
+ break;
+ }
+ return 0;
+}
+
+/* Configure Balancer */
+static int rdo_app_pool_config(mm_server_conf_t *cfg,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ apr_uint32_t app_pool_id,
+ mmdb_app_pool_t *app_pool,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j;
+ apr_status_t rc;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ /* Wildchar params not allowed for config */
+ continue;
+ }
+ else if (!strcasecmp(ce[i].key, MM_RES_APPLICATION)) {
+ /* Configure Application for this ApplicationPool
+ * Add resource if it doesn't exist and link it
+ * to this ApplicationPool
+ */
+ mm_resource_provider_t *mp = mm_lookup_resource_provider(ce[i].key);
+ if (mp) {
+ rc = (*mp->func)(cfg, mm_mcmp_config,
+ ce[i].val, this_provider,
+ app_pool_id, app_pool,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS)
+ return 1;
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EEXIST, r->server,
+ "mod_manager: resource provider: %s",
+ mp->name);
+ return 1;
+ }
+ break;
+ }
+ else {
+ while (app_pool_params[j]) {
+ if (!strcasecmp(ce[i].key, app_pool_params[j])) {
+ if (!ce[i].val || !*(ce[i].val)) {
+ /* Empty value */
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL,
+ NULL);
+ return 1;
+ }
+ if ((rc = rdo_app_pool_config_do(j, ce[i].val,
+ app_pool, r))) {
+ /* Parameter value error */
+ mm_send_response_ex(r, mm_response_error,
+ rc, NULL);
+ return 1;
+ }
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ return 0;
+}
+
+static apr_status_t create_app_pool(mm_server_conf_t *cfg,
+ const char *name,
+ asmm_slotmem_t *app_pool_db,
+ mmdb_app_pool_t **app_pool,
+ apr_uint32_t *app_pool_id)
+{
+ /* Create ApplicationPool */
+ if (!(*app_pool = asmm_salloc_ex(app_pool_db, app_pool_id)))
+ return apr_get_os_error();
+ MM_SSAFE_COPY((*app_pool)->name, name);
+
+ (*app_pool)->concurrency = max_clients;
+ (*app_pool)->timeout = cfg->main_server->timeout;
+ (*app_pool)->status = mm_state_active;
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_app_pool(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ int wdone = 0;
+ int wcm;
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+ apr_uint32_t next = 0;
+ mmdb_app_pool_t *app_pool;
+ asmm_slotmem_t *app_pool_db = mmdb_table_getn(MMDB_APP_POOL);
+
+ if (!app_pool_db)
+ return APR_ENOMEM;
+ if (!name || !*name) {
+#if MM_FORCE_DEFAULT_NAME_REQ
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] empty ApplicationPool name",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+#else
+ name = MM_DEFAULT_NAME;
+#endif
+ }
+ wcm = apr_fnmatch_test(name);
+ while ((app_pool = asmm_slot_next(app_pool_db, &next))) {
+ if (wcm) {
+ if (apr_fnmatch(name, app_pool->name,
+ MM_FFNMATCH) != APR_SUCCESS)
+ continue;
+ }
+ else if (strcasecmp(name, app_pool->name))
+ continue;
+ if (cmd_offset < ca->nelts) {
+ mm_resource_provider_t *mp =
mm_lookup_resource_provider(ce[cmd_offset].key);
+ if (mp) {
+ apr_status_t rc;
+ if (mp == this_provider) {
+ mm_send_response_ex(r, mm_response_error, MME_EINVAL, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] recursion not allowed:
%s",
+ mm_mcmp_command_name_get(cmd),
+ this_provider->name);
+ return APR_SUCCESS;
+ }
+ rc = (*mp->func)(cfg, cmd,
+ ce[cmd_offset].val, this_provider,
+ next - 1, app_pool,
+ cmd_table, cmd_offset + 1, r);
+ if (rc != APR_SUCCESS) {
+ }
+ wdone++;
+ if (wcm)
+ continue;
+ else
+ break;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ if (wcm) {
+ ap_rvputs(r, "@" MM_RES_APP_POOL "/",
app_pool->name, NULL);
+ if (cmd_offset < ca->nelts)
+ ap_rputs(": ", r);
+ else
+ ap_rputs(CRLF, r);
+ }
+ if (cmd_offset < ca->nelts)
+ rdo_app_pool_info(cmd_table, cmd_offset, wcm, app_pool, r);
+ break;
+ case mm_mcmp_enable:
+ app_pool->status = mm_state_active;
+ break;
+ case mm_mcmp_disable:
+ app_pool->status = mm_state_disabled;
+ break;
+ case mm_mcmp_stop:
+ app_pool->status = mm_state_stopped;
+ break;
+ case mm_mcmp_delete:
+ if (app_pool->status != mm_state_stopped) {
+ /* ApplicationPool must be stopped before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: ApplicationPool not stopped:
%s",
+ app_pool->name);
+ return APR_SUCCESS;
+ }
+ else if (app_pool->applications) {
+ /* ApplicationPool must be empty before */
+ mm_send_response_ex(r, mm_response_error, MME_EBUSY, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: ApplicationPool not empty: %s",
+ app_pool->name);
+ return APR_SUCCESS;
+ }
+ else {
+ /* Delete ApplicationPool entries */
+ if (strcmp(app_pool->name, MM_DEFAULT_NAME)) {
+ /* TODO: Remove any dependent objects */
+ asmm_free(app_pool_db, app_pool);
+ }
+ else if (!wcm) {
+ mm_send_response_ex(r, mm_response_error,
+ MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0,
+ r->server,
+ "mod_manager: Cannot delete "
+ MM_DEFAULT_NAME " ApplicationPool");
+ return APR_SUCCESS;
+ }
+ }
+ case mm_mcmp_config:
+ if (rdo_app_pool_config(cfg, cmd_table, cmd_offset,
+ next - 1, app_pool, r))
+ return APR_SUCCESS;
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for "
+ "ApplicationPool",
+ mm_mcmp_command_name_get(cmd));
+ return APR_SUCCESS;
+ break;
+ }
+ wdone++;
+ if (!wcm)
+ break;
+ }
+ if (!wdone) {
+ if (cmd == mm_mcmp_config && !wcm) {
+ apr_status_t rv;
+ apr_uint32_t app_pool_id;
+ /* Add new ApplicationPool */
+ if ((rv = create_app_pool(cfg, name, app_pool_db,
+ &app_pool, &app_pool_id)) != APR_SUCCESS)
+ return rv;
+ /* Update ApplicationPool from provided params */
+ rdo_app_pool_config(cfg, cmd_table, cmd_offset,
+ app_pool_id, app_pool, r);
+ }
+ else {
+ mm_send_response_ex(r, mm_response_utype, 0, MM_RES_APP_POOL "/",
+ name, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: unknown ApplicationPool: %s", name);
+ return APR_SUCCESS;
+ }
+ }
+ switch (cmd) {
+ case mm_mcmp_info:
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t rdo_app_pool_init(mm_server_conf_t *cfg, int child,
+ apr_pool_t *pool)
+{
+ apr_uint32_t app_pool_id;
+ mmdb_app_pool_t *app_pool;
+ asmm_slotmem_t *app_pool_db;
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests_per_child);
+ ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_childs);
+ if (max_childs < 1)
+ max_childs = 1;
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
+ if (max_threads_per_child < 1)
+ max_threads_per_child = 1;
+ max_clients = max_childs * max_threads_per_child;
+
+ if (child)
+ return APR_SUCCESS;
+ if (!(app_pool_db = mmdb_table_getn(MMDB_APP_POOL)))
+ return APR_ENOMEM;
+ /* Create _default_ ApplicationPool */
+ return create_app_pool(cfg, MM_DEFAULT_NAME,
+ app_pool_db,
+ &app_pool,
+ &app_pool_id);
+}
+
+static apr_status_t ini_app_pool(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ return rdo_app_pool_init(cfg, 0, pool);
+ break;
+ case mm_resource_open:
+ case mm_resource_child_init:
+ return rdo_app_pool_init(cfg, 1, pool);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a ApplicationPool */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t app_pool_provider = {
+ MMDB_APP_POOL,
+ MM_RES_APP_POOL,
+ rdo_app_pool,
+ ini_app_pool,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_app_pool(apr_pool_t *pool)
+{
+ this_provider = &app_pool_provider;
+ mm_register_resource_provider(pool, this_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_pool.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_server.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_server.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_server.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,374 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager Server object resource routines */
+#include "mm_api.h"
+
+static const char *server_params[] = {
+ "",
+ "ServerName",
+ "ServerRoot",
+ "ServerVersion",
+ "ServerVersionNumber",
+ "ServerBuilt",
+ "ServerArchitecture",
+ "ServerProcessing",
+ "ServerPlatform",
+ "ThreadsPerChild",
+ "MaxRequestsPerChild",
+ "MaxClients",
+ "Listen",
+ "ListenBackLog",
+ "CurrentTime",
+ "RestartTime",
+ "ServerUpTime",
+ "AccessCount",
+ "BytesServed",
+ "Busy",
+ "LimitRequestFields",
+ "LimitRequestFieldSize",
+ "ConfigurationFile",
+ NULL
+};
+
+static int server_limit = 0;
+static int thread_limit = 0;
+static int max_clients = 0;
+static int max_childs = 0;
+static int max_requests_per_child = 0;
+static int max_threads_per_child = 0;
+
+static apr_off_t get_scoreboard_access()
+{
+ int i, j;
+ worker_score *ws;
+ apr_off_t ac = 0;
+
+ for (i = 0; i < server_limit; i++) {
+ for (j = 0; j < thread_limit; j++) {
+ ws = ap_get_scoreboard_worker(i, j);
+ ac += ws->access_count;
+ }
+ }
+ return ac;
+}
+
+static apr_off_t get_scoreboard_bserved()
+{
+ int i, j;
+ worker_score *ws;
+ apr_off_t bs = 0;
+
+ for (i = 0; i < server_limit; i++) {
+ for (j = 0; j < thread_limit; j++) {
+ ws = ap_get_scoreboard_worker(i, j);
+ bs += ws->bytes_served;
+ }
+ }
+ return bs;
+}
+
+static int get_scoreboard_busy()
+{
+ int i, j, r;
+ worker_score *ws;
+ process_score *ps;
+ int busy = 0;
+
+ for (i = 0; i < server_limit; i++) {
+ ps = ap_get_scoreboard_process(i);
+ if (!ps->quiescing && ps->pid) {
+ for (j = 0; j < thread_limit; j++) {
+ ws = ap_get_scoreboard_worker(i, j);
+ r = ws->status;
+ if (r != SERVER_DEAD &&
+ r != SERVER_STARTING &&
+ r != SERVER_READY &&
+ r != SERVER_IDLE_KILL)
+ busy++;
+ }
+ }
+ }
+ return busy;
+}
+
+static void print_listeners(request_rec *r)
+{
+ int cnt = 0;
+ ap_listen_rec *lr;
+
+ for (lr = ap_listeners; lr; lr = lr->next)
+ cnt++;
+ if (cnt > 1)
+ ap_rputs("\"", r);
+
+ cnt = 0;
+ for (lr = ap_listeners; lr; lr = lr->next) {
+ char *addr;
+ apr_sockaddr_ip_get(&addr, lr->bind_addr);
+ if (cnt++)
+ ap_rputs(" ", r);
+ ap_rprintf(r, "%s:%u", addr, lr->bind_addr->port);
+ }
+ if (cnt > 1)
+ ap_rputs("\"", r);
+
+}
+
+
+static void rdo_server_info_print(int pi, int pp,
+ mm_server_conf_t *cfg,
+ request_rec *r)
+{
+ char b[APR_RFC822_DATE_LEN] = "";
+
+ if (pp) {
+ ap_rvputs(r, server_params[pi], "=", NULL);
+ }
+ switch (pi) {
+ case 1: /* ServerName */
+ MM_MAYBEQ_RPUTS(r, pp, cfg->main_server->server_hostname);
+ break;
+ case 2: /* ServerRoot */
+ MM_MAYBEQ_RPUTS(r, pp, ap_server_root);
+ break;
+ case 3: /* ServerVersion */
+ MM_MAYBEQ_RPUTS(r, pp, ap_get_server_description());
+ break;
+ case 4: /* ServerVersionNumber */
+ ap_rprintf(r, "%u.%u", MODULE_MAGIC_NUMBER_MAJOR,
+ MODULE_MAGIC_NUMBER_MINOR);
+ break;
+ case 5: /* ServerBuilt */
+ MM_MAYBEQ_RPUTS(r, pp, ap_get_server_built());
+ break;
+ case 6: /* ServerArchitecture */
+ ap_rprintf(r, "%ld-bit", 8 * (long) sizeof(void *));
+ break;
+ case 7: /* ServerProcessing */
+ ap_rputs(MPM_NAME, r);
+ break;
+ case 8: /* ServerPlatform */
+ ap_rputs(PLATFORM, r);
+ break;
+ case 9: /* ThreadsPerChild */
+ ap_rprintf(r, "%d", max_threads_per_child);
+ break;
+ case 10: /* MaxRequestsPerChild */
+ ap_rprintf(r, "%d", max_requests_per_child);
+ break;
+ case 11: /* MaxClients */
+ ap_rprintf(r, "%d", max_clients);
+ break;
+ case 12: /* Listen */
+ print_listeners(r);
+ break;
+ case 13: /* ListenBackLog */
+ /* For now use compile-time setting */
+ ap_rprintf(r, "%d", DEFAULT_LISTENBACKLOG);
+ break;
+ case 14: /* CurrentTime */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
apr_time_as_msec(apr_time_now()));
+ break;
+ case 15: /* RestartTime */
+ ap_rprintf(r, "%" APR_TIME_T_FMT,
+ apr_time_as_msec(ap_scoreboard_image->global->restart_time));
+ break;
+ case 16: /* ServerUpTime */
+ ap_rprintf(r, "%" APR_TIME_T_FMT, apr_time_as_msec(apr_time_now()
-
+ ap_scoreboard_image->global->restart_time));
+ break;
+ case 17: /* AccessCount */
+ ap_rprintf(r, "%" APR_OFF_T_FMT, get_scoreboard_access());
+ break;
+ case 18: /* BytesServed */
+ ap_rprintf(r, "%" APR_OFF_T_FMT, get_scoreboard_bserved());
+ break;
+ case 19: /* Busy */
+ ap_rprintf(r, "%d", get_scoreboard_busy());
+ break;
+ case 20: /* LimitRequestFields */
+ ap_rprintf(r, "%d", cfg->main_server->limit_req_fields);
+ break;
+ case 21: /* LimitRequestFieldSize */
+ ap_rprintf(r, "%d", cfg->main_server->limit_req_fieldsize);
+ break;
+ case 22: /* ConfigurationFile */
+ MM_MAYBEQ_RPUTS(r, pp, ap_conftree->filename);
+ break;
+ }
+}
+
+/* Dump server info */
+static void rdo_server_info(apr_table_t *cmd_table,
+ int cmd_offset,
+ mm_server_conf_t *cfg,
+ request_rec *r)
+{
+ int cnt = 0;
+ int i, j, m = 0;
+ const char *param = NULL;
+ const char *value = NULL;
+
+ const apr_array_header_t *ca = apr_table_elts(cmd_table);
+ apr_table_entry_t *ce = (apr_table_entry_t *)ca->elts;
+
+ /* Step 1: Figure out the number of requested params */
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (server_params[j]) {
+ if (apr_fnmatch(ce[i].key, server_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ cnt++;
+ }
+ j++;
+ }
+ }
+ else {
+ while (server_params[j]) {
+ if (!strcasecmp(ce[i].key, server_params[j])) {
+ m = j;
+ cnt++;
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (!cnt) {
+ /* No params. Just print OK */
+ mm_send_response_ex(r, mm_response_ok, 0, NULL);
+ }
+ else if (cnt == 1 && m) {
+ /* Single param */
+ rdo_server_info_print(m, 0, cfg, r);
+ ap_rputs(CRLF, r);
+ }
+ else {
+ /* Multiple params */
+ int sep = 0;
+ for (i = cmd_offset; i < ca->nelts; i++) {
+ j = 1;
+ if (apr_fnmatch_test(ce[i].key)) {
+ while (server_params[j]) {
+ if (apr_fnmatch(ce[i].key, server_params[j],
+ MM_FFNMATCH) == APR_SUCCESS) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_server_info_print(j, 1, cfg, r);
+ }
+ j++;
+ }
+ }
+ else {
+ while (server_params[j]) {
+ if (!strcasecmp(ce[i].key, server_params[j])) {
+ if (sep++)
+ ap_rputs("; ", r);
+ rdo_server_info_print(j, 1, cfg, r);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ if (sep)
+ ap_rputs(CRLF, r);
+ }
+}
+
+static apr_status_t rdo_server_init(mm_server_conf_t *cfg)
+{
+
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
+ ap_mpm_query(AP_MPMQ_HARD_LIMIT_DAEMONS, &server_limit);
+ ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests_per_child);
+ ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_childs);
+ if (max_childs < 1)
+ max_childs = 1;
+ ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
+ if (max_threads_per_child < 1)
+ max_threads_per_child = 1;
+ max_clients = max_childs * max_threads_per_child;
+ return APR_SUCCESS;
+}
+
+
+static apr_status_t rdo_server(mm_server_conf_t *cfg,
+ mm_mcmp_command_e cmd,
+ const char *name,
+ mm_resource_provider_t *prev,
+ apr_uint32_t prev_id,
+ void *prev_rec,
+ apr_table_t *cmd_table,
+ int cmd_offset,
+ request_rec *r)
+{
+ switch (cmd) {
+ case mm_mcmp_info:
+ rdo_server_info(cmd_table, cmd_offset, cfg, r);
+ break;
+ default:
+ mm_send_response_ex(r, mm_response_error, MME_EPERM, NULL);
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,
+ "mod_manager: [%s] not allowed for Server",
+ mm_mcmp_command_name_get(cmd));
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t ini_server(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ switch (op) {
+ case mm_resource_init:
+ case mm_resource_open:
+ case mm_resource_child_init:
+ return rdo_server_init(cfg);
+ break;
+ case mm_resource_close:
+ /* Nothing to do for a Server */
+ break;
+ }
+ return APR_SUCCESS;
+}
+
+static mm_resource_provider_t server_provider = {
+ MMDB_SERVER,
+ MM_RES_SERVER,
+ rdo_server,
+ ini_server,
+ NULL
+};
+
+/* Exported register function */
+void mm_register_resource_server(apr_pool_t *pool)
+{
+ mm_register_resource_provider(pool, &server_provider);
+}
Property changes on: sandbox/aloha/httpd/modules/manager/mm_server.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/mm_util.c
===================================================================
--- sandbox/aloha/httpd/modules/manager/mm_util.c (rev 0)
+++ sandbox/aloha/httpd/modules/manager/mm_util.c 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,997 @@
+/*
+ * ModManager - JBoss Aloha
+ *
+ * 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 Mladen Turk
+ */
+
+/* Manager utility routines */
+#include "mm_api.h"
+
+#ifdef AP_NEED_SET_MUTEX_PERMS
+#include "unixd.h"
+#endif
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for getpid() */
+#endif
+
+#if HAVE_SYS_SEM_H
+#include <sys/shm.h>
+#if !defined(SHM_R)
+#define SHM_R 0400
+#endif
+#if !defined(SHM_W)
+#define SHM_W 0200
+#endif
+#endif
+
+/** A list of advertise callbacks */
+typedef struct mm_advetrisecb_t mm_advetrisecb_t;
+struct mm_advetrisecb_t {
+ /** The next callback in the list */
+ struct mm_advetrisecb_t *next;
+ /** General purpose storage */
+ const void *data;
+ /** Callback function */
+ mm_advertisefn_t *callback;
+};
+
+/** A list of maintenance callbacks */
+typedef struct mm_maintaincb_t mm_maintaincb_t;
+struct mm_maintaincb_t {
+ /** The next callback in the list */
+ struct mm_maintaincb_t *next;
+ /** General purpose storage */
+ const void *data;
+ /** Callback function */
+ mm_maintainfn_t *callback;
+};
+
+/* Internal case insensitive string hash table */
+typedef struct mm_hash_node_t mm_hash_node_t;
+struct mm_hash_node_t {
+ mm_hash_node_t *next;
+ const void *data;
+ unsigned int ikey;
+ char key[1];
+};
+
+typedef struct mm_hash_t mm_hash_t;
+struct mm_hash_t {
+ apr_pool_t *pool;
+ unsigned int size;
+ mm_hash_node_t **nodes;
+ apr_array_header_t *nlist;
+};
+
+/* Private data */
+static apr_pool_t *mm_register_pool = NULL;
+static mm_advetrisecb_t *mm_advertise_cb = NULL;
+static mm_maintaincb_t *mm_maintain_cb = NULL;
+static mm_hash_t *mm_resource_hash = NULL;
+
+/* Advertise sockets */
+static apr_socket_t *mma_mgroup_socket = NULL;
+static apr_socket_t *mma_listen_socket = NULL;
+static apr_sockaddr_t *mma_mgroup_sa = NULL;
+static apr_sockaddr_t *mma_listen_sa = NULL;
+
+/* Advertise sequence number */
+static volatile apr_uint64_t mma_sequence = 0;
+
+/*
+ * ---------------------------------------------------------------------
+ * begin of hash
+ * ---------------------------------------------------------------------
+ */
+
+/* Make hash size always as 0xFF value */
+#define DEFAULT_HASH_SIZE 256
+
+static unsigned int strhash(const char *string)
+{
+ unsigned int hash = 0;
+
+ while (*string) {
+ hash = hash * 33 + apr_tolower(*string);
+ string ++;
+ }
+ return hash;
+}
+
+static mm_hash_t *hash_create(apr_size_t size, apr_pool_t *pool)
+{
+ mm_hash_t *h;
+ if (!size)
+ size = DEFAULT_HASH_SIZE;
+ else
+ size = APR_ALIGN_DEFAULT(size);
+ h = apr_palloc(pool, sizeof(mm_hash_t));
+ h->nodes = apr_pcalloc(pool, sizeof(mm_hash_node_t *) * size);
+ h->nlist = apr_array_make(pool, size, sizeof(mm_hash_node_t *));
+ h->size = size;
+ h->pool = pool;
+ return h;
+}
+
+static void *hash_insert(mm_hash_t *ht, const char *key, const void *data)
+{
+ unsigned int ikey;
+ unsigned int hkey;
+ mm_hash_node_t **node;
+
+ if (!ht || !key)
+ return NULL;
+ ikey = strhash(key);
+ hkey = ikey % ht->size;
+ if (!ht->nodes[hkey]) {
+ ht->nodes[hkey] = apr_palloc(ht->pool, sizeof(mm_hash_node_t) +
+ strlen(key));
+ strcpy(ht->nodes[hkey]->key, key);
+ ht->nodes[hkey]->ikey = ikey;
+ ht->nodes[hkey]->data = data;
+ ht->nodes[hkey]->next = NULL;
+ node = (mm_hash_node_t **)apr_array_push(ht->nlist);
+ *node = ht->nodes[hkey];
+ }
+ else {
+ mm_hash_node_t *p;
+ for (p = ht->nodes[hkey]; p; p = p->next) {
+ if (p->ikey == ikey && !strcasecmp(p->key, key)) {
+ void *org = (void *)p->data;
+ p->data = data;
+ return org;
+ }
+ }
+ p = apr_palloc(ht->pool, sizeof(mm_hash_node_t) + strlen(key));
+ strcpy(p->key, key);
+ p->ikey = ikey;
+ p->data = data;
+ p->next = ht->nodes[hkey];
+ ht->nodes[hkey] = p;
+ node = (mm_hash_node_t **)apr_array_push(ht->nlist);
+ *node = ht->nodes[hkey];
+ }
+ return NULL;
+}
+
+
+static void *hash_find(mm_hash_t *ht, const char *key)
+{
+ unsigned int ikey;
+ unsigned int hkey;
+
+ if (!ht || !key)
+ return NULL;
+ ikey = strhash(key);
+ hkey = ikey % ht->size;
+
+ if (!ht->nodes[hkey])
+ return NULL;
+ else {
+ mm_hash_node_t *p;
+ for (p = ht->nodes[hkey]; p; p = p->next) {
+ if (p->ikey == ikey && !strcasecmp(p->key, key)) {
+ return (void *)p->data;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void hash_foreach(mm_hash_t *ht, apr_pool_t *pool, void *opaque,
+ void (*callback)(apr_pool_t *, void *, const char *, void *))
+{
+ int i;
+
+ if (!ht || !ht->nlist->nelts)
+ return;
+ for (i = ht->nlist->nelts - 1; i >= 0; i--) {
+ mm_hash_node_t *p = ((mm_hash_node_t **)ht->nlist->elts)[i];
+ (*callback)(pool, opaque, p->key, (void *)p->data);
+ }
+}
+
+void mm_callback_initialize(apr_pool_t *pool)
+{
+ mm_register_pool = pool;
+}
+
+#define MM_ADVERTISE_SERVER_FMT \
+ "HTTP/1.0 %s" CRLF \
+ "Date: %s" CRLF \
+ "Digest: %s" CRLF \
+ "Server: %s" CRLF
+
+static const char *hex = "0123456789abcdef";
+
+apr_status_t mm_advertise_server_cb(void *cd, const char *data)
+{
+ char buf[MM_BSIZE];
+ char dat[APR_RFC822_DATE_LEN];
+ unsigned char msig[APR_MD5_DIGESTSIZE];
+ unsigned char ssig[APR_MD5_DIGESTSIZE * 2 + 1];
+ const char *asl;
+ char *p = buf;
+ int i, c = 0;
+ apr_size_t l = MM_BSIZE - 8;
+ apr_size_t n = 0;
+ apr_md5_ctx_t md;
+
+ mmdb_manager_t *m = (mmdb_manager_t *)cd;
+
+ mma_sequence++;
+ ap_recent_rfc822_date(dat, apr_time_now());
+ asl = ap_get_status_line(m->status);
+
+ /* Create MD5 digest
+ * salt + date + srvid
+ */
+ apr_md5_init(&md);
+ apr_md5_update(&md, m->ssalt, APR_MD5_DIGESTSIZE);
+ apr_md5_update(&md, dat, strlen(dat));
+ apr_md5_update(&md, m->srvid + 1, strlen(m->srvid + 1));
+ apr_md5_final(msig, &md);
+ /* Convert MD5 digest to hex string */
+ for (i = 0; i < APR_MD5_DIGESTSIZE; i++) {
+ ssig[c++] = hex[msig[i] >> 4];
+ ssig[c++] = hex[msig[i] & 0x0F];
+ }
+ ssig[c] = '\0';
+ n = apr_snprintf(p, l, MM_ADVERTISE_SERVER_FMT,
+ asl, dat, ssig, m->srvid + 1);
+ if (m->type == MM_ADVERTISE_SERVER) {
+ l -= n;
+ if (data && *data) {
+ apr_cpystrn(p + n, data, l);
+ n = strlen(buf);
+ }
+ }
+ strcat(p, CRLF);
+ n += 2;
+ return apr_socket_sendto(mma_mgroup_socket,
+ mma_mgroup_sa, 0, buf, &n);
+}
+
+apr_status_t mm_advertise_callback_run(mm_advertise_e mode, void *context,
+ apr_status_t (*callback)(void *, const char *))
+{
+ apr_status_t rv = APR_SUCCESS;
+ mm_advetrisecb_t *c = mm_advertise_cb;
+ char data[MM_BSIZE] = "";
+ char *p = data;
+ apr_size_t n = 0;
+ apr_size_t l = MM_BSIZE - 128;
+
+ while (c) {
+ /* Accumulate data from all callbacks */
+ rv = (*c->callback)(mode, (void *)c->data, p + n, l);
+ if (rv != APR_SUCCESS)
+ break;
+ if ((c = c->next)) {
+ n = strlen(data);
+ l -= n;
+ }
+ }
+ if (rv == APR_SUCCESS)
+ rv = (*callback)(context, data);
+ return rv;
+}
+
+apr_status_t mm_maintain_callback_run(mm_maintain_e mode)
+{
+ apr_status_t rv = APR_SUCCESS;
+ mm_maintaincb_t *c = mm_maintain_cb;
+ while (c) {
+ /* Make sure all callbacks are run,
+ * but preserve the error codes.
+ */
+ apr_status_t rc = (*c->callback)(mode, (void *)c->data);
+ if (rc != APR_SUCCESS)
+ rv = rc;
+ c = c->next;
+ }
+ return rv;
+}
+
+MANAGER_DECLARE(void) mm_register_advertise_callback(apr_pool_t *pool,
+ const void *context,
+ mm_advertisefn_t *callback)
+{
+ mm_advetrisecb_t *c;
+ if (!mm_register_pool)
+ mm_register_pool = pool;
+ c = apr_palloc(mm_register_pool, sizeof(mm_advetrisecb_t));
+ c->data = context;
+ c->callback = callback;
+ c->next = mm_advertise_cb;
+ mm_advertise_cb = c;
+}
+
+MANAGER_DECLARE(void) mm_register_maintain_callback(apr_pool_t *pool,
+ const void *data,
+ mm_maintainfn_t *callback)
+{
+ mm_maintaincb_t *c;
+ if (!mm_register_pool)
+ mm_register_pool = pool;
+ c = apr_palloc(mm_register_pool, sizeof(mm_maintaincb_t));
+ c->data = data;
+ c->callback = callback;
+ c->next = mm_maintain_cb;
+ mm_maintain_cb = c;
+}
+
+MANAGER_DECLARE(void) mm_register_resource_provider(apr_pool_t *pool,
+ mm_resource_provider_t *provider)
+{
+ if (!mm_resource_hash)
+ mm_resource_hash = hash_create(0, pool);
+ hash_insert(mm_resource_hash, provider->name, provider);
+}
+
+MANAGER_DECLARE(mm_resource_provider_t *)mm_lookup_resource_provider(
+ const char *name)
+{
+ return hash_find(mm_resource_hash, name);
+}
+
+static void reslist_cb(apr_pool_t *pool, void *p,
+ const char *key, void *data)
+{
+ mm_resource_list_t *re;
+ mm_resource_list_t **rl = (mm_resource_list_t **)p;
+ re = apr_palloc(pool, sizeof(mm_resource_list_t));
+ re->provider = data;
+ re->next = *rl;
+ *rl = re;
+}
+
+MANAGER_DECLARE(mm_resource_list_t *)mm_list_resource_providers(
+ apr_pool_t *pool)
+{
+ mm_resource_list_t *rl = NULL;
+ hash_foreach(mm_resource_hash, pool, (void *)&rl, reslist_cb);
+ return rl;
+}
+
+struct ri_cb {
+ mm_server_conf_t *sc;
+ mm_resource_op_e op;
+};
+
+static void resinit_cb(apr_pool_t *pool, void *p,
+ const char *key, void *data)
+{
+ struct ri_cb *cb = p;
+ mm_resource_provider_t *rp = data;
+ (*rp->init)(cb->sc, cb->op, pool);
+}
+
+MANAGER_DECLARE(void)mm_run_resource_providers(mm_server_conf_t *cfg,
+ mm_resource_op_e op,
+ apr_pool_t *pool)
+{
+ struct ri_cb cb;
+ cb.sc = cfg;
+ cb.op = op;
+ hash_foreach(mm_resource_hash, pool, (void *)&cb, resinit_cb);
+}
+
+const char *mm_strerror(apr_status_t s)
+{
+ switch (s) {
+ case MME_EPERM:
+ return "Operation not permitted";
+ break;
+ case MME_EINTR:
+ return "Interrupted function call";
+ break;
+ case MME_EBUSY:
+ return "Device or resource busy";
+ break;
+ case MME_ENODEV:
+ return "No such device";
+ break;
+ case MME_EINVAL:
+ return "Invalid Argument";
+ break;
+ case MME_ENOTCONN:
+ return "Not connected";
+ break;
+ }
+ return NULL;
+}
+
+void mm_send_response_ex(request_rec *r, mm_respose_type_e type,
+ apr_status_t s, ...)
+{
+ int vc = 0;
+ char buf[512];
+ const char *p, *line;
+ va_list vl;
+
+ va_start(vl, s);
+
+
+ switch (type) {
+ case mm_response_ok:
+ while ((line = va_arg(vl, const char *)) != NULL) {
+ ap_rputs(line, r);
+ vc++;
+ }
+ if (!vc)
+ ap_rputs("OK", r);
+ ap_rputs(CRLF, r);
+ break;
+ case mm_response_error:
+ if (!(p = mm_strerror(s))) {
+ if (!(p = apr_strerror(s, buf, sizeof(buf))))
+ p = "Unknown Error";
+ }
+ ap_rprintf(r, "?Error: %d; %s" CRLF, s, p);
+ break;
+ case mm_response_version:
+ ap_rputs("?MCMP/" MM_MCMP_VERSION_STRING CRLF, r);
+ break;
+ case mm_response_utype:
+ ap_rputs("?Unknown-Type: ", r);
+ while ((line = va_arg(vl, const char *)) != NULL)
+ ap_rputs(line, r);
+ ap_rputs(CRLF, r);
+ break;
+ case mm_response_uparam:
+ ap_rputs("?Unknown-Parameter: ", r);
+ while ((line = va_arg(vl, const char *)) != NULL)
+ ap_rputs(line, r);
+ ap_rputs(CRLF, r);
+ break;
+ }
+ va_end(vl);
+}
+
+static struct mm_command_spec {
+ const char *name;
+ mm_mcmp_command_e nval;
+} mm_commands_spec[] = {
+ { MM_MCMP_INFO, mm_mcmp_info },
+ { MM_MCMP_CONFIG, mm_mcmp_config },
+ { MM_MCMP_DISABLE, mm_mcmp_disable },
+ { MM_MCMP_ENABLE, mm_mcmp_enable },
+ { MM_MCMP_STOP, mm_mcmp_stop },
+ { MM_MCMP_DELETE, mm_mcmp_delete },
+ { MM_MCMP_EXEC, mm_mcmp_exec },
+ { MM_MCMP_RESET, mm_mcmp_reset },
+ { NULL, 0 }
+};
+
+
+mm_mcmp_command_e mm_mcmp_command_get(const char *cmd)
+{
+ int i = 0;
+ while (mm_commands_spec[i].name) {
+ if (!strcasecmp(cmd, mm_commands_spec[i].name))
+ return mm_commands_spec[i].nval;
+ i++;
+ }
+ return mm_mcmp_unknown;
+}
+
+const char *mm_mcmp_command_name_get(mm_mcmp_command_e cmd)
+{
+ int i = 0;
+ while (mm_commands_spec[i].name) {
+ if (mm_commands_spec[i].nval == cmd)
+ return mm_commands_spec[i].name;
+ i++;
+ }
+ return "(Unknown)";
+}
+
+apr_status_t mma_group_join(const char *addr, apr_port_t port,
+ apr_pool_t *pool)
+{
+ apr_status_t rv;
+
+ if ((rv = apr_sockaddr_info_get(&mma_mgroup_sa, addr,
+ APR_INET, port,
+ APR_UNSPEC, pool)) != APR_SUCCESS)
+ return rv;
+ if ((rv = apr_socket_create(&mma_mgroup_socket,
+ mma_mgroup_sa->family,
+ SOCK_DGRAM,
+ APR_PROTO_UDP,
+ pool)) != APR_SUCCESS)
+ return rv;
+ if ((rv = apr_mcast_join(mma_mgroup_socket, mma_mgroup_sa,
+ NULL, NULL)) != APR_SUCCESS) {
+ apr_socket_close(mma_mgroup_socket);
+ return rv;
+ }
+ if ((rv = apr_mcast_hops(mma_mgroup_socket,
+ MM_ADVERTISE_HOPS)) != APR_SUCCESS) {
+ apr_mcast_leave(mma_mgroup_socket, mma_mgroup_sa,
+ NULL, NULL);
+ apr_socket_close(mma_mgroup_socket);
+ return rv;
+ }
+ return APR_SUCCESS;
+}
+
+void mma_group_leave()
+{
+ if (mma_mgroup_socket) {
+ apr_mcast_leave(mma_mgroup_socket, mma_mgroup_sa,
+ NULL, NULL);
+ apr_socket_close(mma_mgroup_socket);
+ mma_mgroup_socket = NULL;
+ }
+}
+
+typedef struct mmdb_table_desc_t mmdb_table_desc_t;
+struct mmdb_table_desc_t {
+ int id;
+ const char *name;
+ apr_uint32_t blksize;
+ apr_uint32_t nblocks;
+ apr_uint16_t flags;
+ apr_uint16_t maxsections;
+ asmm_slotmem_t *mem;
+ apr_global_mutex_t *lock;
+};
+
+static mmdb_table_desc_t mmdb_default_tables[] = {
+ { MMDB_MANAGER,
+ "Manager",
+ sizeof(mmdb_manager_t),
+ 1,
+ 0,
+ 0,
+ NULL,
+ NULL
+ },
+ { MMDB_HOST,
+ "Host",
+ sizeof(mmdb_host_t),
+ 64,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_HOST_LIST,
+ "HostList",
+ sizeof(mmdb_hostlist_t),
+ 256,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_APP_POOL,
+ "ApplicationPool",
+ sizeof(mmdb_app_pool_t),
+ 16,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_BALANCER,
+ "Balancer",
+ sizeof(mmdb_balancer_t),
+ 16,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_MEMBER,
+ "Member",
+ sizeof(mmdb_member_t),
+ 1,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_APPLICATION,
+ "Application",
+ sizeof(mmdb_app_t),
+ 64,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { MMDB_MEMBERAPP,
+ "MemberApplication",
+ sizeof(mmdb_memberapp_t),
+ 512,
+ ASMM_HAS_LOCK,
+ ASMM_UNLIMITED,
+ NULL,
+ NULL
+ },
+ { 0,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL,
+ NULL
+ }
+};
+
+static apr_global_mutex_t *mmdb_default_tables_lock = NULL;
+static mmdb_owner_instance = 0;
+
+apr_status_t mmdb_close()
+{
+ int i = 0;
+
+ if (mmdb_owner_instance && mmdb_default_tables_lock) {
+ apr_global_mutex_destroy(mmdb_default_tables_lock);
+ }
+ mmdb_default_tables_lock = NULL;
+
+ while (mmdb_default_tables[i].name) {
+ if (mmdb_owner_instance &&
+ mmdb_default_tables[i].lock &&
+ mmdb_default_tables[i].flags & ASMM_OWN_LOCK) {
+ apr_global_mutex_destroy(mmdb_default_tables[i].lock);
+ }
+ mmdb_default_tables[i].lock = NULL;
+ if (mmdb_default_tables[i].mem) {
+ asmm_slotmem_close(mmdb_default_tables[i].mem);
+ mmdb_default_tables[i].mem = NULL;
+ }
+ i++;
+ }
+ return APR_SUCCESS;
+}
+
+apr_status_t mmdb_create(const char *dbpath, apr_pool_t *pool)
+{
+ apr_status_t rv = APR_SUCCESS;
+ const char *pk = "manager_init_database_tag";
+ const char *lk = "manager_init_globlock_tag";
+ char fname[APR_PATH_MAX];
+ int i = 0;
+ mmdb_table_desc_t *database = NULL;
+
+
+ apr_pool_userdata_get((void *)&mmdb_default_tables_lock, lk, pool);
+ apr_pool_userdata_get((void *)&database, pk, pool);
+
+ mmdb_owner_instance = 1;
+ if (database) {
+ while (mmdb_default_tables[i].name) {
+ mmdb_default_tables[i].mem = database[i].mem;
+ mmdb_default_tables[i].lock = database[i].lock;
+ i++;
+ }
+ return APR_SUCCESS;
+ }
+
+ strcpy(fname, dbpath);
+ strcat(fname, "/_mm_lock");
+ if ((rv = apr_global_mutex_create(&mmdb_default_tables_lock,
+ fname,
+ APR_LOCK_DEFAULT,
+ pool)) != APR_SUCCESS)
+ return rv;
+#ifdef AP_NEED_SET_MUTEX_PERMS
+ rv = unixd_set_global_mutex_perms(mmdb_default_tables_lock);
+ if (rv != APR_SUCCESS) {
+ apr_global_mutex_destroy(mmdb_default_tables_lock);
+ mmdb_default_tables_lock = NULL;
+ return rv;
+ }
+#endif
+
+ while (mmdb_default_tables[i].name) {
+ sprintf(fname, "%s/_sm_%04d", dbpath, mmdb_default_tables[i].id);
+ rv = asmm_slotmem_create(&mmdb_default_tables[i].mem,
+ fname,
+ mmdb_default_tables[i].blksize,
+ mmdb_default_tables[i].nblocks,
+ mmdb_default_tables[i].flags,
+ mmdb_default_tables[i].maxsections,
+ pool);
+ if (rv != APR_SUCCESS) {
+ mmdb_default_tables[i].mem = NULL;
+ break;
+ }
+ if (mmdb_default_tables[i].flags & ASMM_OWN_LOCK) {
+ sprintf(fname, "%s/_mm_%04d", dbpath, mmdb_default_tables[i].id);
+ if ((rv = apr_global_mutex_create(&mmdb_default_tables[i].lock,
+ fname,
+ APR_LOCK_DEFAULT,
+ pool)) != APR_SUCCESS) {
+ asmm_slotmem_close(mmdb_default_tables[i].mem);
+ mmdb_default_tables[i].mem = NULL;
+ return rv;
+ }
+#ifdef AP_NEED_SET_MUTEX_PERMS
+ rv = unixd_set_global_mutex_perms(mmdb_default_tables[i].lock);
+ if (rv != APR_SUCCESS) {
+ asmm_slotmem_close(mmdb_default_tables[i].mem);
+ mmdb_default_tables[i].mem = NULL;
+ return rv;
+ }
+#endif
+ asmm_slotmem_lock_set(mmdb_default_tables[i].mem,
+ mmdb_default_tables[i].lock);
+ }
+ else if (mmdb_default_tables[i].flags & ASMM_HAS_LOCK)
+ asmm_slotmem_lock_set(mmdb_default_tables[i].mem,
+ mmdb_default_tables_lock);
+
+ i++;
+ }
+ apr_pool_userdata_set(mmdb_default_tables_lock,
+ lk, apr_pool_cleanup_null, pool);
+ apr_pool_userdata_set(apr_pmemdup(pool, mmdb_default_tables,
+ sizeof(mmdb_default_tables)),
+ pk, apr_pool_cleanup_null, pool);
+ return rv;
+}
+
+apr_status_t mmdb_open(const char *dbpath, apr_pool_t *pool)
+{
+ apr_status_t rv = APR_SUCCESS;
+ char fname[APR_PATH_MAX];
+ int i = 0;
+
+ mmdb_owner_instance = 0;
+ strcpy(fname, dbpath);
+ strcat(fname, "/_mm_lock");
+ if ((rv = apr_global_mutex_child_init(&mmdb_default_tables_lock,
+ fname,
+ pool)) != APR_SUCCESS)
+ return rv;
+ while (mmdb_default_tables[i].name) {
+ sprintf(fname, "%s/_sm_%04d", dbpath, mmdb_default_tables[i].id);
+ rv = asmm_slotmem_open(&mmdb_default_tables[i].mem,
+ fname,
+ pool);
+ if (rv != APR_SUCCESS) {
+ break;
+ }
+ if (mmdb_default_tables[i].flags & ASMM_OWN_LOCK) {
+ sprintf(fname, "%s/_mm_%04d", dbpath, mmdb_default_tables[i].id);
+ if ((rv = apr_global_mutex_child_init(&mmdb_default_tables[i].lock,
+ fname,
+ pool)) != APR_SUCCESS) {
+ asmm_slotmem_close(mmdb_default_tables[i].mem);
+ mmdb_default_tables[i].mem = NULL;
+ return rv;
+ }
+ asmm_slotmem_lock_set(mmdb_default_tables[i].mem,
+ mmdb_default_tables[i].lock);
+ }
+ else if (mmdb_default_tables[i].flags & ASMM_HAS_LOCK)
+ asmm_slotmem_lock_set(mmdb_default_tables[i].mem,
+ mmdb_default_tables_lock);
+ i++;
+ }
+ return rv;
+}
+
+asmm_slotmem_t *mmdb_table_get(const char *name)
+{
+ int i = 0;
+
+ while (mmdb_default_tables[i].name) {
+ if (!strcasecmp(mmdb_default_tables[i].name, name))
+ return mmdb_default_tables[i].mem;
+ i++;
+ }
+ return NULL;
+}
+
+asmm_slotmem_t *mmdb_table_getn(int id)
+{
+ int i = 0;
+
+ while (mmdb_default_tables[i].name) {
+ if (mmdb_default_tables[i].id == id)
+ return mmdb_default_tables[i].mem;
+ i++;
+ }
+ return NULL;
+}
+
+const char *mmdb_table_name_get(int id)
+{
+ int i = 0;
+
+ while (mmdb_default_tables[i].name) {
+ if (mmdb_default_tables[i].id == id)
+ return mmdb_default_tables[i].name;
+ i++;
+ }
+ return "unknown";
+}
+
+apr_status_t mmdb_maintain(server_rec *s)
+{
+ apr_status_t rv;
+ int i = 0;
+
+ while (mmdb_default_tables[i].name) {
+ rv = asmm_slotmem_maintain(mmdb_default_tables[i].mem);
+ if (rv != APR_SUCCESS)
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
+ "mod_manager: failed new section request for: %s",
+ mmdb_default_tables[i].name);
+ i++;
+ }
+ return APR_SUCCESS;
+}
+
+const char *mm_state_name_get(mm_state_e state)
+{
+ switch (state) {
+ case mm_state_active:
+ return "A";
+ break;
+ case mm_state_busy:
+ return "B";
+ break;
+ case mm_state_disabled:
+ return "D";
+ break;
+ case mm_state_idle:
+ return "I";
+ break;
+ case mm_state_stopped:
+ return "S";
+ break;
+ case mm_state_error:
+ return "E";
+ break;
+ }
+ return "X";
+}
+
+mm_state_e mm_state_get(const char *sstate)
+{
+
+ switch (apr_toupper(*sstate)) {
+ case 'A':
+ return mm_state_active;
+ break;
+ case 'B':
+ return mm_state_busy;
+ break;
+ case 'D':
+ return mm_state_disabled;
+ break;
+ case 'I':
+ return mm_state_idle;
+ break;
+ case 'S':
+ return mm_state_stopped;
+ break;
+ case 'E':
+ return mm_state_error;
+ break;
+ }
+ return mm_state_unknown;
+}
+
+mm_protocol_e mm_protocol_get(const char *protocol)
+{
+
+ if (!strcasecmp(protocol, "http"))
+ return mm_protocol_http;
+ else if (!strcasecmp(protocol, "https"))
+ return mm_protocol_https;
+ else if (!strcasecmp(protocol, "ajp"))
+ return mm_protocol_ajp;
+ else
+ return mm_protocol_unknown;
+}
+
+const char *mm_protocol_name_get(mm_protocol_e protocol)
+{
+ switch (protocol) {
+ case mm_protocol_ajp:
+ return "ajp";
+ break;
+ case mm_protocol_http:
+ return "http";
+ break;
+ case mm_protocol_https:
+ return "https";
+ break;
+ }
+ return "undefined";
+}
+
+apr_status_t mm_unixd_set_shm_perms(const char *fname)
+{
+#ifdef AP_NEED_SET_MUTEX_PERMS
+#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
+ struct shmid_ds shmbuf;
+ key_t shmkey;
+ int shmid;
+
+ shmkey = ftok(fname, 1);
+ if (shmkey == (key_t)-1) {
+ return errno;
+ }
+ if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) == -1) {
+ return errno;
+ }
+ shmbuf.shm_perm.uid = unixd_config.user_id;
+ shmbuf.shm_perm.gid = unixd_config.group_id;
+ shmbuf.shm_perm.mode = 0600;
+ if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
+ return errno;
+ }
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif
+#else
+ return APR_ENOTIMPL;
+#endif
+}
+
+#if defined (WIN32)
+void dbprintf(const char *format, ...)
+{
+ va_list args;
+ char buffer[4096];
+ int len;
+
+ va_start(args, format);
+ len = _vsnprintf(buffer, 4096, format, args);
+ va_end(args);
+ if (len > 0) {
+ char tid[4096 + 32];
+ sprintf(tid, "[%04d] %s", GetCurrentThreadId(), buffer);
+ OutputDebugString(tid);
+ }
+}
+#else
+void dbprintf(const char *format, ...)
+{
+ va_list args;
+ char buffer[4096];
+ int len;
+
+ va_start(args, format);
+ len = vsnprintf(buffer, 4096, format, args);
+ va_end(args);
+ if (len > 0) {
+ fprintf(stderr, "mod_manager: [%d\t%d] %s\n",
+ getpid(), getppid(), buffer);
+ fflush(stderr);
+ }
+}
+#endif
Property changes on: sandbox/aloha/httpd/modules/manager/mm_util.c
___________________________________________________________________
Name: svn:eol-style
+ native
Added: sandbox/aloha/httpd/modules/manager/modules.mk
===================================================================
--- sandbox/aloha/httpd/modules/manager/modules.mk (rev 0)
+++ sandbox/aloha/httpd/modules/manager/modules.mk 2008-05-28 15:50:29 UTC (rev 1632)
@@ -0,0 +1,5 @@
+mod_manager.la: mm_app.slo mm_asmm.slo mm_balancer.slo mm_cookie.slo mm_host.slo
mm_manager.slo mm_member.slo mm_module.slo mm_pool.slo mm_server.slo mm_util.slo
+ $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mm_app.lo mm_asmm.lo
mm_balancer.lo mm_cookie.lo mm_host.lo mm_manager.lo mm_member.lo mm_module.lo mm_pool.lo
mm_server.lo mm_util.lo $(MOD_MANAGER_LDADD)
+DISTCLEAN_TARGETS = modules.mk
+static =
+shared = mod_manager.la