/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ /*************************************************************************** * Description: Status worker, display and manages JK workers * * Author: Mladen Turk * * Author: Rainer Jung * * Version: $Revision: 562174 $ * ***************************************************************************/ #include "jk_pool.h" #include "jk_service.h" #include "jk_util.h" #include "jk_worker.h" #include "jk_status.h" #include "jk_mt.h" #include "jk_shm.h" #include "jk_ajp_common.h" #include "jk_lb_worker.h" #include "jk_ajp13_worker.h" #include "jk_ajp14_worker.h" #include "jk_connect.h" #include "jk_uri_worker_map.h" #define HUGE_BUFFER_SIZE (8*1024) /** * Command line reference: * cmd=list (default) display configuration * cmd=show display detailed configuration * cmd=edit form to change configuration * cmd=update commit update configuration * cmd=reset reset lb runtime states, or lb member runtime states * cmd=version show only software version * Query arguments: * re=n (refresh time in seconds, n=0: disabled) * w=worker (cmd should be executed for worker "worker") * sw=sub_worker (cmd should be executed for "sub_worker" of worker "worker") * from=lastcmd (the last viewing command was "lastcmd") * opt=option (changes meaning of edit and list/show) */ #define JK_STATUS_ARG_CMD "cmd" #define JK_STATUS_ARG_MIME "mime" #define JK_STATUS_ARG_FROM "from" #define JK_STATUS_ARG_REFRESH "re" #define JK_STATUS_ARG_WORKER "w" #define JK_STATUS_ARG_SUB_WORKER "sw" #define JK_STATUS_ARG_ATTRIBUTE "att" #define JK_STATUS_ARG_MULT_VALUE_BASE "val" #define JK_STATUS_ARG_OPTIONS "opt" #define JK_STATUS_ARG_OPTION_NO_MEMBERS 0x0001 #define JK_STATUS_ARG_OPTION_NO_MAPS 0x0002 #define JK_STATUS_ARG_OPTION_NO_LEGEND 0x0004 #define JK_STATUS_ARG_OPTION_NO_LB 0x0008 #define JK_STATUS_ARG_OPTION_NO_AJP 0x0010 #define JK_STATUS_ARG_OPTION_READ_ONLY 0x0020 #define JK_STATUS_ARG_LB_RETRIES ("lr") #define JK_STATUS_ARG_LB_RECOVER_TIME ("lt") #define JK_STATUS_ARG_LB_MAX_REPLY_TIMEOUTS ("lx") #define JK_STATUS_ARG_LB_STICKY ("ls") #define JK_STATUS_ARG_LB_STICKY_FORCE ("lf") #define JK_STATUS_ARG_LB_METHOD ("lm") #define JK_STATUS_ARG_LB_LOCK ("ll") #define JK_STATUS_ARG_LB_TEXT_RETRIES "Retries" #define JK_STATUS_ARG_LB_TEXT_RECOVER_TIME "Recover Wait Time" #define JK_STATUS_ARG_LB_TEXT_MAX_REPLY_TIMEOUTS "Max Reply Timeouts" #define JK_STATUS_ARG_LB_TEXT_STICKY "Sticky Sessions" #define JK_STATUS_ARG_LB_TEXT_STICKY_FORCE "Force Sticky Sessions" #define JK_STATUS_ARG_LB_TEXT_METHOD "LB Method" #define JK_STATUS_ARG_LB_TEXT_LOCK "Locking" #define JK_STATUS_ARG_LBM_ACTIVATION ("wa") #define JK_STATUS_ARG_LBM_FACTOR ("wf") #define JK_STATUS_ARG_LBM_ROUTE ("wn") #define JK_STATUS_ARG_LBM_REDIRECT ("wr") #define JK_STATUS_ARG_LBM_DOMAIN ("wc") #define JK_STATUS_ARG_LBM_DISTANCE ("wd") #define JK_STATUS_ARG_LBM_TEXT_ACTIVATION "Activation" #define JK_STATUS_ARG_LBM_TEXT_FACTOR "LB Factor" #define JK_STATUS_ARG_LBM_TEXT_ROUTE "Route" #define JK_STATUS_ARG_LBM_TEXT_REDIRECT "Redirect Route" #define JK_STATUS_ARG_LBM_TEXT_DOMAIN "Cluster Domain" #define JK_STATUS_ARG_LBM_TEXT_DISTANCE "Distance" #define JK_STATUS_CMD_UNKNOWN (0) #define JK_STATUS_CMD_LIST (1) #define JK_STATUS_CMD_SHOW (2) #define JK_STATUS_CMD_EDIT (3) #define JK_STATUS_CMD_UPDATE (4) #define JK_STATUS_CMD_RESET (5) #define JK_STATUS_CMD_VERSION (6) #define JK_STATUS_CMD_RECOVER (7) #define JK_STATUS_CMD_DEF (JK_STATUS_CMD_LIST) #define JK_STATUS_CMD_MAX (JK_STATUS_CMD_RECOVER) #define JK_STATUS_CMD_TEXT_UNKNOWN ("unknown") #define JK_STATUS_CMD_TEXT_LIST ("list") #define JK_STATUS_CMD_TEXT_SHOW ("show") #define JK_STATUS_CMD_TEXT_EDIT ("edit") #define JK_STATUS_CMD_TEXT_UPDATE ("update") #define JK_STATUS_CMD_TEXT_RESET ("reset") #define JK_STATUS_CMD_TEXT_VERSION ("version") #define JK_STATUS_CMD_TEXT_RECOVER ("recover") #define JK_STATUS_CMD_TEXT_DEF (JK_STATUS_CMD_TEXT_LIST) #define JK_STATUS_MIME_UNKNOWN (0) #define JK_STATUS_MIME_HTML (1) #define JK_STATUS_MIME_XML (2) #define JK_STATUS_MIME_TXT (3) #define JK_STATUS_MIME_PROP (4) #define JK_STATUS_MIME_DEF (JK_STATUS_MIME_HTML) #define JK_STATUS_MIME_MAX (JK_STATUS_MIME_PROP) #define JK_STATUS_MIME_TEXT_UNKNOWN ("unknown") #define JK_STATUS_MIME_TEXT_HTML ("html") #define JK_STATUS_MIME_TEXT_XML ("xml") #define JK_STATUS_MIME_TEXT_TXT ("txt") #define JK_STATUS_MIME_TEXT_PROP ("prop") #define JK_STATUS_MIME_TEXT_DEF (JK_STATUS_MIME_TEXT_HTML) #define JK_STATUS_MASK_ACTIVE 0x000000FF #define JK_STATUS_MASK_DISABLED 0x0000FF00 #define JK_STATUS_MASK_STOPPED 0x00FF0000 #define JK_STATUS_MASK_OK 0x00010101 #define JK_STATUS_MASK_IDLE 0x00020202 #define JK_STATUS_MASK_BUSY 0x00040404 #define JK_STATUS_MASK_RECOVER 0x00080808 #define JK_STATUS_MASK_ERROR 0x00101010 #define JK_STATUS_MASK_GOOD_DEF 0x0000000F #define JK_STATUS_MASK_BAD_DEF 0x00FF1010 #define JK_STATUS_WAIT_AFTER_UPDATE "3" #define JK_STATUS_REFRESH_DEF "10" #define JK_STATUS_ESC_CHARS ("<>?&") #define JK_STATUS_HEAD "\n" \ "JK Status Manager" #define JK_STATUS_COPYRIGHT "Copyright © 1999-2007, The Apache Software Foundation
" \ "Licensed under the " \ "Apache License, Version 2.0." #define JK_STATUS_HEND "\n\n" #define JK_STATUS_BEND "\n\n" #define JK_STATUS_XMLH "\n" #define JK_STATUS_NS_DEF "jk:" #define JK_STATUS_XMLNS_DEF "xmlns:jk=\"http://tomcat.apache.org\"" #define JK_STATUS_PREFIX_DEF "worker" #define JK_STATUS_FORM_START "
\n" #define JK_STATUS_FORM_HIDDEN_INT "\n" #define JK_STATUS_FORM_HIDDEN_STRING "\n" #define JK_STATUS_TABLE_HEAD_3_STRING "%s%s%s\n" #define JK_STATUS_TABLE_ROW_3_STRING "%s%s%s\n" #define JK_STATUS_SHOW_AJP_HEAD "" \ "Type" \ "Host" \ "Addr" \ "\n" #define JK_STATUS_SHOW_AJP_ROW "" \ "%s" \ "%s:%d" \ "%s" \ "\n" #define JK_STATUS_SHOW_LB_HEAD "" \ "Type" \ "" JK_STATUS_ARG_LB_TEXT_STICKY "" \ "" JK_STATUS_ARG_LB_TEXT_STICKY_FORCE "" \ "" JK_STATUS_ARG_LB_TEXT_RETRIES "" \ "" JK_STATUS_ARG_LB_TEXT_METHOD "" \ "" JK_STATUS_ARG_LB_TEXT_LOCK "" \ "" JK_STATUS_ARG_LB_TEXT_RECOVER_TIME "" \ "" JK_STATUS_ARG_LB_TEXT_MAX_REPLY_TIMEOUTS "" \ "\n" #define JK_STATUS_SHOW_LB_ROW "" \ "%s" \ "%s" \ "%s" \ "%d" \ "%s" \ "%s" \ "%d" \ "%d" \ "\n" #define JK_STATUS_SHOW_MEMBER_HEAD "" \ " NameType" \ "HostAddr" \ "ActState" \ "DFM" \ "VAcc" \ "ErrCERE" \ "WrRdBusyMax" \ "" JK_STATUS_ARG_LBM_TEXT_ROUTE "" \ "RRCdRs" \ "\n" #define JK_STATUS_SHOW_MEMBER_ROW "%s" \ "%s" \ "%s:%d" \ "%s" \ "%s" \ "%s" \ "%d" \ "%d" \ "%" JK_UINT64_T_FMT "" \ "%" JK_UINT64_T_FMT "" \ "%" JK_UINT64_T_FMT "" \ "%" JK_UINT32_T_FMT "" \ "%" JK_UINT32_T_FMT "" \ "%" JK_UINT32_T_FMT "" \ "%s" \ "%s" \ "%d" \ "%d" \ "%s" \ "%s" \ "%s" \ "%d/%d" \ "\n" typedef struct status_worker status_worker_t; struct status_endpoint { status_worker_t *worker; jk_map_t *req_params; char *msg; jk_endpoint_t endpoint; }; typedef struct status_endpoint status_endpoint_t; struct status_worker { jk_pool_t p; jk_pool_atom_t buf[TINY_POOL_SIZE]; const char *name; const char *css; const char *ns; const char *xmlns; const char *doctype; const char *prefix; int read_only; char **user_names; unsigned int num_of_users; int user_case_insensitive; jk_uint32_t good_mask; jk_uint32_t bad_mask; jk_worker_t worker; jk_worker_env_t *we; }; static const char *worker_type[] = { "unknown", "ajp12", "ajp13", "ajp14", "jni", "lb", "status", NULL }; static const char *headers_names[] = { "Content-Type", "Cache-Control", "Pragma", NULL }; static const char *cmd_type[] = { JK_STATUS_CMD_TEXT_UNKNOWN, JK_STATUS_CMD_TEXT_LIST, JK_STATUS_CMD_TEXT_SHOW, JK_STATUS_CMD_TEXT_EDIT, JK_STATUS_CMD_TEXT_UPDATE, JK_STATUS_CMD_TEXT_RESET, JK_STATUS_CMD_TEXT_VERSION, JK_STATUS_CMD_TEXT_RECOVER, NULL }; static const char *mime_type[] = { JK_STATUS_MIME_TEXT_UNKNOWN, JK_STATUS_MIME_TEXT_HTML, JK_STATUS_MIME_TEXT_XML, JK_STATUS_MIME_TEXT_TXT, JK_STATUS_MIME_TEXT_PROP, NULL }; #define HEADERS_NO_CACHE "no-cache", "no-cache", NULL static const char *headers_vhtml[] = { "text/html", HEADERS_NO_CACHE }; static const char *headers_vxml[] = { "text/xml", HEADERS_NO_CACHE }; static const char *headers_vtxt[] = { "text/plain", HEADERS_NO_CACHE }; static void jk_puts(jk_ws_service_t *s, const char *str) { if (str) s->write(s, str, (unsigned int)strlen(str)); else s->write(s, "(null)", 6); } static void jk_putv(jk_ws_service_t *s, ...) { va_list va; const char *str; va_start(va, s); while (1) { str = va_arg(va, const char *); if (str == NULL) break; s->write(s, str, (unsigned int)strlen(str)); } va_end(va); } static int jk_printf(jk_ws_service_t *s, const char *fmt, ...) { int rc = 0; va_list args; #ifdef NETWARE /* On NetWare, this can get called on a thread that has a limited stack so */ /* we will allocate and free the temporary buffer in this function */ char *buf; #else char buf[HUGE_BUFFER_SIZE]; #endif if (!s || !fmt) { return -1; } va_start(args, fmt); #ifdef NETWARE buf = (char *)malloc(HUGE_BUFFER_SIZE); if (NULL == buf) return -1; #endif rc = vsnprintf(buf, HUGE_BUFFER_SIZE, fmt, args); va_end(args); if (rc > 0) s->write(s, buf, rc); #ifdef NETWARE free(buf); #endif return rc; } static void jk_print_xml_start_elt(jk_ws_service_t *s, status_worker_t *w, int indentation, int close_tag, const char *name) { if (close_tag) { jk_printf(s, "%*s<%s%s>\n", indentation, "", w->ns, name); } else { jk_printf(s, "%*s<%s%s\n", indentation, "", w->ns, name); } } static void jk_print_xml_close_elt(jk_ws_service_t *s, status_worker_t *w, int indentation, const char *name) { jk_printf(s, "%*s\n", indentation, "", w->ns, name); } static void jk_print_xml_stop_elt(jk_ws_service_t *s, int indentation, int close_tag) { if (close_tag) { jk_printf(s, "%*s/>\n", indentation, ""); } else { jk_printf(s, "%*s>\n", indentation, ""); } } static void jk_print_xml_att_string(jk_ws_service_t *s, int indentation, const char *key, const char *value) { jk_printf(s, "%*s%s=\"%s\"\n", indentation, "", key, value ? value : ""); } static void jk_print_xml_att_int(jk_ws_service_t *s, int indentation, const char *key, int value) { jk_printf(s, "%*s%s=\"%d\"\n", indentation, "", key, value); } static void jk_print_xml_att_uint32(jk_ws_service_t *s, int indentation, const char *key, jk_uint32_t value) { jk_printf(s, "%*s%s=\"%" JK_UINT32_T_FMT "\"\n", indentation, "", key, value); } static void jk_print_xml_att_uint64(jk_ws_service_t *s, int indentation, const char *key, jk_uint64_t value) { jk_printf(s, "%*s%s=\"%" JK_UINT64_T_FMT "\"\n", indentation, "", key, value); } static void jk_print_prop_att_string(jk_ws_service_t *s, status_worker_t *w, const char *name, const char *key, const char *value) { if (name) { jk_printf(s, "%s.%s.%s=%s\n", w->prefix, name, key, value ? value : ""); } else { jk_printf(s, "%s.%s=%s\n", w->prefix, key, value ? value : ""); } } static void jk_print_prop_att_int(jk_ws_service_t *s, status_worker_t *w, const char *name, const char *key, int value) { if (name) { jk_printf(s, "%s.%s.%s=%d\n", w->prefix, name, key, value); } else { jk_printf(s, "%s.%s=%d\n", w->prefix, key, value); } } static void jk_print_prop_att_uint32(jk_ws_service_t *s, status_worker_t *w, const char *name, const char *key, jk_uint32_t value) { if (name) { jk_printf(s, "%s.%s.%s=%" JK_UINT32_T_FMT "\n", w->prefix, name, key, value); } else { jk_printf(s, "%s.%s=%" JK_UINT32_T_FMT "\n", w->prefix, key, value); } } static void jk_print_prop_att_uint64(jk_ws_service_t *s, status_worker_t *w, const char *name, const char *key, jk_uint64_t value) { if (name) { jk_printf(s, "%s.%s.%s=%" JK_UINT64_T_FMT "\n", w->prefix, name, key, value); } else { jk_printf(s, "%s.%s=%" JK_UINT64_T_FMT "\n", w->prefix, key, value); } } static void jk_print_prop_item_string(jk_ws_service_t *s, status_worker_t *w, const char *name, const char *list, int num, const char *key, const char *value) { if (name) { jk_printf(s, "%s.%s.%s.%d.%s=%s\n", w->prefix, name, list, num, key, value ? value : ""); } else { jk_printf(s, "%s.%s.%d.%s=%s\n", w->prefix, list, num, key, value ? value : ""); } } /* Actually APR's apr_strfsize */ static char *status_strfsize(jk_uint64_t size, char *buf) { const char ord[] = "KMGTPE"; const char *o = ord; unsigned int remain, siz; if (size < 973) { if (sprintf(buf, "%3d ", (int) size) < 0) return strcpy(buf, "****"); return buf; } do { remain = (unsigned int)(size & 0x03FF); size >>= 10; if (size >= 973) { ++o; continue; } siz = (unsigned int)(size & 0xFFFF); if (siz < 9 || (siz == 9 && remain < 973)) { if ((remain = ((remain * 5) + 256) / 512) >= 10) ++siz, remain = 0; if (sprintf(buf, "%d.%d%c", siz, remain, *o) < 0) return strcpy(buf, "****"); return buf; } if (remain >= 512) ++siz; if (sprintf(buf, "%3d%c", siz, *o) < 0) return strcpy(buf, "****"); return buf; } while (1); } static int status_rate(worker_record_t *wr, status_worker_t *w, jk_logger_t *l) { jk_uint32_t mask = 0; int activation = wr->s->activation; int state = wr->s->state; jk_uint32_t good = w->good_mask; jk_uint32_t bad = w->bad_mask; int rv = 0; switch (activation) { case JK_LB_ACTIVATION_ACTIVE: mask = JK_STATUS_MASK_ACTIVE; break; case JK_LB_ACTIVATION_DISABLED: mask = JK_STATUS_MASK_DISABLED; break; case JK_LB_ACTIVATION_STOPPED: mask = JK_STATUS_MASK_STOPPED; break; default: jk_log(l, JK_LOG_WARNING, "Status worker '%s' unknown activation type '%d'", w->name, activation); } switch (state) { case JK_LB_STATE_OK: mask &= JK_STATUS_MASK_OK; break; case JK_LB_STATE_IDLE: mask &= JK_STATUS_MASK_IDLE; break; case JK_LB_STATE_BUSY: mask &= JK_STATUS_MASK_BUSY; break; case JK_LB_STATE_ERROR: mask &= JK_STATUS_MASK_ERROR; break; case JK_LB_STATE_RECOVER: mask &= JK_STATUS_MASK_RECOVER; break; case JK_LB_STATE_FORCE: mask &= JK_STATUS_MASK_RECOVER; break; case JK_LB_STATE_PROBE: mask &= JK_STATUS_MASK_RECOVER; break; default: jk_log(l, JK_LOG_WARNING, "Status worker '%s' unknown state type '%d'", w->name, state); } if (mask&bad) rv = -1; else if (mask&good) rv = 1; else rv = 0; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' rating of activation '%s' and state '%s' for good '%08" JK_UINT32_T_HEX_FMT "' and bad '%08" JK_UINT32_T_HEX_FMT "' is %d", w->name, jk_lb_get_activation(wr, l), jk_lb_get_state(wr, l), good, bad, rv); return rv; } static jk_uint32_t status_get_single_rating(const char rating, jk_logger_t *l) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "rating retrieval for '%c'", rating); switch (rating) { case 'A': case 'a': return JK_STATUS_MASK_ACTIVE; case 'D': case 'd': return JK_STATUS_MASK_DISABLED; case 'S': case 's': return JK_STATUS_MASK_STOPPED; case 'O': case 'o': return JK_STATUS_MASK_OK; case 'I': case 'i': case 'N': case 'n': return JK_STATUS_MASK_IDLE; case 'B': case 'b': return JK_STATUS_MASK_BUSY; case 'R': case 'r': return JK_STATUS_MASK_RECOVER; case 'E': case 'e': return JK_STATUS_MASK_ERROR; default: jk_log(l, JK_LOG_WARNING, "Unknown rating type '%c'", rating); return 0; } } static jk_uint32_t status_get_rating(const char *rating, jk_logger_t *l) { int off = 0; jk_uint32_t mask = 0; while (rating[off] == ' ' || rating[off] == '\t' || rating[off] == '.') { off++; } mask = status_get_single_rating(rating[off], l); while (rating[off] != '\0' && rating[off] != '.') { off++; } if (rating[off] == '.') { off++; } if (rating[off] != '\0') { mask &= status_get_single_rating(rating[off], l); } if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "rating for '%s' is '%08" JK_UINT32_T_HEX_FMT "'", rating, mask); return mask; } static const char *status_worker_type(int t) { if (t < 0 || t > 6) t = 0; return worker_type[t]; } static int status_get_string(status_endpoint_t *p, const char *param, const char *def, const char **result, jk_logger_t *l) { int rv; *result = jk_map_get_string(p->req_params, param, NULL); if (*result) { rv = JK_TRUE; } else { *result = def; rv = JK_FALSE; } if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "retrieved string arg '%s' as '%s'%s", param, *result ? *result : "(null)", rv == JK_FALSE ? " (default)" : ""); return rv; } static int status_get_int(status_endpoint_t *p, const char *param, int def, jk_logger_t *l) { const char *arg; int rv = def; if (status_get_string(p, param, NULL, &arg, l) == JK_TRUE) { rv = atoi(arg); } return rv; } static int status_get_bool(status_endpoint_t *p, const char *param, int def, jk_logger_t *l) { const char *arg; if (status_get_string(p, param, NULL, &arg, l) == JK_TRUE) { return jk_get_bool_code(arg, def); } return def; } static const char *status_cmd_text(int cmd) { return cmd_type[cmd]; } static int status_cmd_int(const char *cmd) { if (!cmd) return JK_STATUS_CMD_DEF; if (!strcmp(cmd, JK_STATUS_CMD_TEXT_LIST)) return JK_STATUS_CMD_LIST; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_SHOW)) return JK_STATUS_CMD_SHOW; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_EDIT)) return JK_STATUS_CMD_EDIT; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_UPDATE)) return JK_STATUS_CMD_UPDATE; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_RESET)) return JK_STATUS_CMD_RESET; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_VERSION)) return JK_STATUS_CMD_VERSION; else if (!strcmp(cmd, JK_STATUS_CMD_TEXT_RECOVER)) return JK_STATUS_CMD_RECOVER; return JK_STATUS_CMD_UNKNOWN; } static const char *status_mime_text(int mime) { return mime_type[mime]; } static int status_mime_int(const char *mime) { if (!mime) return JK_STATUS_MIME_DEF; if (!strcmp(mime, JK_STATUS_MIME_TEXT_HTML)) return JK_STATUS_MIME_HTML; else if (!strcmp(mime, JK_STATUS_MIME_TEXT_XML)) return JK_STATUS_MIME_XML; else if (!strcmp(mime, JK_STATUS_MIME_TEXT_TXT)) return JK_STATUS_MIME_TXT; else if (!strcmp(mime, JK_STATUS_MIME_TEXT_PROP)) return JK_STATUS_MIME_PROP; return JK_STATUS_MIME_UNKNOWN; } static void status_start_form(jk_ws_service_t *s, status_endpoint_t *p, const char *method, int cmd, jk_logger_t *l) { int i; int sz; jk_map_t *m = p->req_params; if (method) jk_printf(s, JK_STATUS_FORM_START, method, s->req_uri); else return; if (cmd != JK_STATUS_CMD_UNKNOWN) { jk_printf(s, JK_STATUS_FORM_HIDDEN_STRING, JK_STATUS_ARG_CMD, status_cmd_text(cmd)); } sz = jk_map_size(m); for (i = 0; i < sz; i++) { const char *k = jk_map_name_at(m, i); const char *v = jk_map_value_at(m, i); if (strcmp(k, JK_STATUS_ARG_CMD) || cmd == JK_STATUS_CMD_UNKNOWN) { jk_printf(s, JK_STATUS_FORM_HIDDEN_STRING, k, v); } } } static void status_write_uri(jk_ws_service_t *s, status_endpoint_t *p, const char *text, int cmd, int mime, const char *worker, const char *sub_worker, unsigned int add_options, unsigned int rm_options, const char *attribute, jk_logger_t *l) { int i; int sz; int started = 0; int from; int prev; unsigned int opt = 0; const char *arg; jk_map_t *m = p->req_params; if (text) jk_puts(s, "req_uri); status_get_string(p, JK_STATUS_ARG_FROM, NULL, &arg, l); from = status_cmd_int(arg); status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l); prev = status_cmd_int(arg); if (cmd == JK_STATUS_CMD_UNKNOWN) { if (prev == JK_STATUS_CMD_UPDATE || prev == JK_STATUS_CMD_RESET || prev == JK_STATUS_CMD_RECOVER) { cmd = from; } } if (cmd != JK_STATUS_CMD_UNKNOWN) { jk_printf(s, "%s%s=%s", started ? "&" : "?", JK_STATUS_ARG_CMD, status_cmd_text(cmd)); if (cmd == JK_STATUS_CMD_EDIT || cmd == JK_STATUS_CMD_RESET || cmd == JK_STATUS_CMD_RECOVER) { jk_printf(s, "%s%s=%s", "&", JK_STATUS_ARG_FROM, status_cmd_text(prev)); } started=1; } if (mime != JK_STATUS_MIME_UNKNOWN) { jk_printf(s, "%s%s=%s", started ? "&" : "?", JK_STATUS_ARG_MIME, status_mime_text(mime)); started=1; } if (worker && worker[0]) { jk_printf(s, "%s%s=%s", started ? "&" : "?", JK_STATUS_ARG_WORKER, worker); started=1; } if (sub_worker && sub_worker[0]) { jk_printf(s, "%s%s=%s", started ? "&" : "?", JK_STATUS_ARG_SUB_WORKER, sub_worker); started=1; } if (attribute && attribute[0]) { jk_printf(s, "%s%s=%s", started ? "&" : "?", JK_STATUS_ARG_ATTRIBUTE, attribute); started=1; } sz = jk_map_size(m); for (i = 0; i < sz; i++) { const char *k = jk_map_name_at(m, i); const char *v = jk_map_value_at(m, i); if (!strcmp(k, JK_STATUS_ARG_CMD) && cmd != JK_STATUS_CMD_UNKNOWN) { continue; } if (!strcmp(k, JK_STATUS_ARG_MIME) && mime != JK_STATUS_MIME_UNKNOWN) { continue; } if (!strcmp(k, JK_STATUS_ARG_FROM)) { continue; } if (!strcmp(k, JK_STATUS_ARG_WORKER) && worker) { continue; } if (!strcmp(k, JK_STATUS_ARG_SUB_WORKER) && sub_worker) { continue; } if (!strcmp(k, JK_STATUS_ARG_ATTRIBUTE) && attribute) { continue; } if (!strcmp(k, JK_STATUS_ARG_ATTRIBUTE) && cmd != JK_STATUS_CMD_UPDATE && cmd != JK_STATUS_CMD_EDIT) { continue; } if (!strncmp(k, JK_STATUS_ARG_MULT_VALUE_BASE, 3) && cmd != JK_STATUS_CMD_UPDATE) { continue; } if (strlen(k) == 2 && (k[0] == 'l' || k[0] == 'w') && cmd != JK_STATUS_CMD_UPDATE) { continue; } if (!strcmp(k, JK_STATUS_ARG_OPTIONS)) { opt = atoi(v); continue; } jk_printf(s, "%s%s=%s", started ? "&" : "?", k, v); started=1; } if (opt | add_options | rm_options) jk_printf(s, "%s%s=%u", started ? "&" : "?", JK_STATUS_ARG_OPTIONS, (opt | add_options) & ~rm_options); if (text) jk_putv(s, "\">", text, "", NULL); } static int status_parse_uri(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { jk_map_t *m; status_worker_t *w = p->worker; #ifdef _REENTRANT char *lasts; #endif char *param; char *query; JK_TRACE_ENTER(l); if (!jk_map_alloc(&(p->req_params))) { jk_log(l, JK_LOG_ERROR, "Status worker '%s' could not alloc map for request parameters", w->name); JK_TRACE_EXIT(l); return JK_FALSE; } if (!s->query_string) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' query string is empty", w->name); JK_TRACE_EXIT(l); return JK_TRUE; } m = p->req_params; query = jk_pool_strdup(s->pool, s->query_string); if (!query) { jk_log(l, JK_LOG_ERROR, "Status worker '%s' could not copy string", w->name); JK_TRACE_EXIT(l); return JK_FALSE; } #ifdef _REENTRANT for (param = strtok_r(query, "&", &lasts); param; param = strtok_r(NULL, "&", &lasts)) { #else for (param = strtok(query, "&"); param; param = strtok(NULL, "&")) { #endif char *key = jk_pool_strdup(s->pool, param); char *value; if (!key) { jk_log(l, JK_LOG_ERROR, "Status worker '%s' could not copy string", w->name); JK_TRACE_EXIT(l); return JK_FALSE; } value = strchr(key, '='); if (value) { char *off; *value = '\0'; value++; /* XXX Depending on the params values, we might need to trim and decode */ /* XXX For now we simply mask special chars with '@' to prevent cross code injection */ off = value; while ((off = strpbrk(off, JK_STATUS_ESC_CHARS))) off[0] = '@'; if (strlen(key)) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' adding request param '%s' with value '%s'", w->name, key, value); jk_map_put(m, key, value, NULL); } } } JK_TRACE_EXIT(l); return JK_TRUE; } static int fetch_worker_and_sub_worker(status_endpoint_t *p, const char *operation, const char **worker, const char **sub_worker, jk_logger_t *l) { status_worker_t *w = p->worker; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_WORKER, NULL, worker, l); status_get_string(p, JK_STATUS_ARG_SUB_WORKER, NULL, sub_worker, l); if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' %s worker '%s' sub worker '%s'", w->name, operation, *worker ? *worker : "(null)", *sub_worker ? *sub_worker : "(null)"); JK_TRACE_EXIT(l); return JK_TRUE; } static int check_valid_lb(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, const char *worker, lb_worker_t **lbp, int implemented, jk_logger_t *l) { status_worker_t *w = p->worker; JK_TRACE_ENTER(l); if (jw->type != JK_LB_WORKER_TYPE) { if (implemented) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type of worker '%s' has no sub workers", w->name, worker); p->msg = "worker type has no sub workers"; } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type of worker '%s' not implemented", w->name, worker); p->msg = "worker type not implemented"; } JK_TRACE_EXIT(l); return JK_FALSE; } *lbp = (lb_worker_t *)jw->worker_private; if (!*lbp) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' lb structure of worker '%s' is (null)", w->name, worker); p->msg = "lb structure is (null)"; JK_TRACE_EXIT(l); return JK_FALSE; } p->msg = "OK"; JK_TRACE_EXIT(l); return JK_TRUE; } static int search_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t **jwp, const char *worker, jk_logger_t *l) { status_worker_t *w = p->worker; JK_TRACE_ENTER(l); *jwp = NULL; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' searching worker '%s'", w->name, worker ? worker : "(null)"); if (!worker || !worker[0]) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' NULL or EMPTY worker param", w->name); p->msg = "NULL or EMPTY worker param"; JK_TRACE_EXIT(l); return JK_FALSE; } *jwp = wc_get_worker_for_name(worker, l); if (!*jwp) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' could not find worker '%s'", w->name, worker); p->msg = "Could not find given worker"; JK_TRACE_EXIT(l); return JK_FALSE; } p->msg = "OK"; JK_TRACE_EXIT(l); return JK_TRUE; } static int search_sub_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, const char *worker, worker_record_t **wrp, const char *sub_worker, jk_logger_t *l) { lb_worker_t *lb = NULL; worker_record_t *wr = NULL; status_worker_t *w = p->worker; unsigned int i; JK_TRACE_ENTER(l); if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' searching sub worker '%s' of worker '%s'", w->name, sub_worker ? sub_worker : "(null)", worker ? worker : "(null)"); if (!sub_worker || !sub_worker[0]) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' NULL or EMPTY sub_worker param", w->name); p->msg = "NULL or EMPTY sub_worker param"; JK_TRACE_EXIT(l); return JK_FALSE; } if (check_valid_lb(s, p, jw, worker, &lb, 1, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } for (i = 0; i < (int)lb->num_of_workers; i++) { wr = &(lb->lb_workers[i]); if (strcmp(sub_worker, wr->s->name) == 0) break; } *wrp = wr; if (!wr || i == (int)lb->num_of_workers) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' could not find sub worker '%s' of worker '%s'", w->name, sub_worker, worker ? worker : "(null)"); p->msg = "could not find sub worker"; JK_TRACE_EXIT(l); return JK_FALSE; } p->msg = "OK"; JK_TRACE_EXIT(l); return JK_TRUE; } static int count_maps(jk_ws_service_t *s, const char *worker, jk_logger_t *l) { unsigned int i; int count=0; jk_uri_worker_map_t *uw_map = s->uw_map; JK_TRACE_ENTER(l); for (i = 0; i < uw_map->size; i++) { uri_worker_record_t *uwr = uw_map->maps[i]; if (strcmp(uwr->worker_name, worker)) { continue; } count++; } JK_TRACE_EXIT(l); return count; } static void display_maps(jk_ws_service_t *s, status_endpoint_t *p, const char *worker, jk_logger_t *l) { char buf[64]; unsigned int i; int mime; unsigned int hide; int count=0; const char *arg; status_worker_t *w = p->worker; jk_uri_worker_map_t *uw_map = s->uw_map; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); hide = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_NO_MAPS; count = count_maps(s, worker, l); if (count) { if (hide) { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

\n"); status_write_uri(s, p, "Show URI Mappings", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_MAPS, NULL, l); jk_puts(s, "

\n"); } } else { if (mime == JK_STATUS_MIME_HTML) { jk_printf(s, "

URI Mappings for %s (%d maps) [", worker, count); status_write_uri(s, p, "Hide", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_MAPS, 0, NULL, l); jk_puts(s, "]

\n"); jk_printf(s, JK_STATUS_TABLE_HEAD_3_STRING, "Match Type", "Uri", "Source"); } } } if (hide) { return; JK_TRACE_EXIT(l); } count = 0; for (i = 0; i < uw_map->size; i++) { uri_worker_record_t *uwr = uw_map->maps[i]; if (strcmp(uwr->worker_name, worker)) { continue; } count++; if (mime == JK_STATUS_MIME_HTML) { jk_printf(s, JK_STATUS_TABLE_ROW_3_STRING, uri_worker_map_get_match(uwr, buf, l), uwr->uri, uri_worker_map_get_source(uwr, l)); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 6, 0, "map"); jk_print_xml_att_int(s, 8, "id", count); jk_print_xml_att_string(s, 8, "type", uri_worker_map_get_match(uwr, buf, l)); jk_print_xml_att_string(s, 8, "uri", uwr->uri); jk_print_xml_att_string(s, 8, "source", uri_worker_map_get_source(uwr, l)); jk_print_xml_stop_elt(s, 6, 1); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Map:"); jk_printf(s, " id=%d", count); jk_printf(s, " type=\"%s\"", uri_worker_map_get_match(uwr, buf, l)); jk_printf(s, " uri=\"%s\"", uwr->uri); jk_printf(s, " source=\"%s\"", uri_worker_map_get_source(uwr, l)); jk_puts(s, "\n"); } else if (mime == JK_STATUS_MIME_PROP) { char *mount = jk_pool_alloc(s->pool, sizeof(char *) * (strlen(uwr->uri)+3)); char *off = mount; if (uwr->match_type & MATCH_TYPE_DISABLED) { *off = '-'; off++; } if (uwr->match_type & MATCH_TYPE_NO_MATCH) { *off = '!'; off++; } strcpy(off, uwr->uri); jk_print_prop_att_string(s, w, worker, "mount", mount); jk_print_prop_item_string(s, w, worker, "map", count, "type", uri_worker_map_get_match(uwr, buf, l)); jk_print_prop_item_string(s, w, worker, "map", count, "uri", uwr->uri); jk_print_prop_item_string(s, w, worker, "map", count, "source", uri_worker_map_get_source(uwr, l)); } } if (count) { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "
\n"); } } else { if (mime == JK_STATUS_MIME_HTML) { jk_putv(s, "

Warning: No URI Mappings defined for ", worker, " !

\n", NULL); } } if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' displayed %d maps for worker '%s'", w->name, count, worker); JK_TRACE_EXIT(l); } static void display_worker_lb(jk_ws_service_t *s, status_endpoint_t *p, lb_worker_t *lb, jk_logger_t *l) { char buf[32]; char buf_rd[32]; char buf_wr[32]; int cmd; int mime; int read_only = 0; int single = 0; unsigned int hide_members; const char *arg; time_t now = time(NULL); unsigned int good = 0; unsigned int degraded = 0; unsigned int bad = 0; int map_count; int ms_min; int ms_max; unsigned int j; const char *name = lb->s->name; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l); cmd = status_cmd_int(arg); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); hide_members = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_NO_MEMBERS; if (w->read_only) { read_only = 1; } else { read_only = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_READ_ONLY; } if (cmd == JK_STATUS_CMD_SHOW) { single = 1; } jk_shm_lock(); if (lb->sequence != lb->s->sequence) jk_lb_pull(lb, l); jk_shm_unlock(); for (j = 0; j < lb->num_of_workers; j++) { worker_record_t *wr = &(lb->lb_workers[j]); int rate; rate = status_rate(wr, w, l); if (rate > 0 ) good++; else if (rate < 0 ) bad++; else degraded++; } map_count = count_maps(s, name, l); ms_min = lb->maintain_time - (int)difftime(now, lb->s->last_maintain_time); ms_max = ms_min + lb->maintain_time; ms_min -= JK_LB_MAINTAIN_TOLERANCE; if (ms_min < 0) { ms_min = 0; } if (ms_max < 0) { ms_max = 0; } if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

["); if (single) { jk_puts(s, "S"); } else { status_write_uri(s, p, "S", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, "", l); } if (!read_only) { jk_puts(s, "|"); status_write_uri(s, p, "E", JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, "", l); jk_puts(s, "|"); status_write_uri(s, p, "R", JK_STATUS_CMD_RESET, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, "", l); } jk_puts(s, "]  "); jk_putv(s, "Worker Status for ", name, "

\n", NULL); jk_puts(s, "" JK_STATUS_SHOW_LB_HEAD); jk_printf(s, JK_STATUS_SHOW_LB_ROW, status_worker_type(JK_LB_WORKER_TYPE), jk_get_bool(lb->sticky_session), jk_get_bool(lb->sticky_session_force), lb->retries, jk_lb_get_method(lb, l), jk_lb_get_lock(lb, l), lb->recover_wait_time, lb->max_reply_timeouts); jk_puts(s, "
\n
\n"); jk_puts(s, "" "" "\n"); jk_printf(s, "", good); jk_printf(s, "", degraded); jk_printf(s, "", bad); jk_printf(s, "", lb->s->busy); jk_printf(s, "", lb->s->max_busy); jk_printf(s, "", ms_min, ms_max); jk_puts(s, "\n
GoodDegradedBad/StoppedBusyMax BusyNext Maintenance
%d%d%d%d%d%d/%d
\n\n"); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 2, 0, "balancer"); jk_print_xml_att_string(s, 4, "name", name); jk_print_xml_att_string(s, 4, "type", status_worker_type(JK_LB_WORKER_TYPE)); jk_print_xml_att_string(s, 4, "sticky_session", jk_get_bool(lb->sticky_session)); jk_print_xml_att_string(s, 4, "sticky_session_force", jk_get_bool(lb->sticky_session_force)); jk_print_xml_att_int(s, 4, "retries", lb->retries); jk_print_xml_att_int(s, 4, "recover_time", lb->recover_wait_time); jk_print_xml_att_int(s, 4, "max_reply_timeouts", lb->max_reply_timeouts); jk_print_xml_att_string(s, 4, "method", jk_lb_get_method(lb, l)); jk_print_xml_att_string(s, 4, "lock", jk_lb_get_lock(lb, l)); jk_print_xml_att_int(s, 4, "member_count", lb->num_of_workers); jk_print_xml_att_int(s, 4, "good", good); jk_print_xml_att_int(s, 4, "degraded", degraded); jk_print_xml_att_int(s, 4, "bad", bad); jk_print_xml_att_int(s, 4, "busy", lb->s->busy); jk_print_xml_att_int(s, 4, "max_busy", lb->s->max_busy); jk_print_xml_att_int(s, 4, "map_count", map_count); jk_print_xml_att_int(s, 4, "time_to_maintenance_min", ms_min); jk_print_xml_att_int(s, 4, "time_to_maintenance_max", ms_max); jk_print_xml_stop_elt(s, 2, 0); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Balancer Worker:"); jk_printf(s, " name=%s", name); jk_printf(s, " type=%s", status_worker_type(JK_LB_WORKER_TYPE)); jk_printf(s, " sticky_session=%s", jk_get_bool(lb->sticky_session)); jk_printf(s, " sticky_session_force=%s", jk_get_bool(lb->sticky_session_force)); jk_printf(s, " retries=%d", lb->retries); jk_printf(s, " recover_time=%d", lb->recover_wait_time); jk_printf(s, " max_reply_timeouts=%d", lb->max_reply_timeouts); jk_printf(s, " method=%s", jk_lb_get_method(lb, l)); jk_printf(s, " lock=%s", jk_lb_get_lock(lb, l)); jk_printf(s, " member_count=%d", lb->num_of_workers); jk_printf(s, " good=%d", good); jk_printf(s, " degraded=%d", degraded); jk_printf(s, " bad=%d", bad); jk_printf(s, " busy=%d", lb->s->busy); jk_printf(s, " max_busy=%d", lb->s->max_busy); jk_printf(s, " map_count=%d", map_count); jk_printf(s, " time_to_maintenance_min=%d", ms_min); jk_printf(s, " time_to_maintenance_max=%d", ms_max); jk_puts(s, "\n"); } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_string(s, w, NULL, "list", name); jk_print_prop_att_string(s, w, name, "type", status_worker_type(JK_LB_WORKER_TYPE)); jk_print_prop_att_string(s, w, name, "sticky_session", jk_get_bool(lb->sticky_session)); jk_print_prop_att_string(s, w, name, "sticky_session_force", jk_get_bool(lb->sticky_session_force)); jk_print_prop_att_int(s, w, name, "retries", lb->retries); jk_print_prop_att_int(s, w, name, "recover_time", lb->recover_wait_time); jk_print_prop_att_int(s, w, name, "max_reply_timeouts", lb->max_reply_timeouts); jk_print_prop_att_string(s, w, name, "method", jk_lb_get_method(lb, l)); jk_print_prop_att_string(s, w, name, "lock", jk_lb_get_lock(lb, l)); jk_print_prop_att_int(s, w, name, "member_count", lb->num_of_workers); jk_print_prop_att_int(s, w, name, "good", good); jk_print_prop_att_int(s, w, name, "degraded", degraded); jk_print_prop_att_int(s, w, name, "bad", bad); jk_print_prop_att_int(s, w, name, "busy", lb->s->busy); jk_print_prop_att_int(s, w, name, "max_busy", lb->s->max_busy); jk_print_prop_att_int(s, w, name, "map_count", map_count); jk_print_prop_att_int(s, w, name, "time_to_maintenance_min", ms_min); jk_print_prop_att_int(s, w, name, "time_to_maintenance_max", ms_max); } if (!hide_members) { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

Balancer Members ["); if (single) { status_write_uri(s, p, "Hide", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_MEMBERS, 0, "", l); } else { status_write_uri(s, p, "Hide", JK_STATUS_CMD_LIST, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_MEMBERS, 0, "", l); } jk_puts(s, "]

\n"); jk_puts(s, "" JK_STATUS_SHOW_MEMBER_HEAD); } for (j = 0; j < lb->num_of_workers; j++) { worker_record_t *wr = &(lb->lb_workers[j]); ajp_worker_t *a = (ajp_worker_t *)wr->w->worker_private; int rs_min = 0; int rs_max = 0; if (wr->s->state == JK_LB_STATE_ERROR) { rs_min = lb->recover_wait_time - (int)difftime(now, wr->s->error_time); if (rs_min < 0) { rs_min = 0; } rs_max = rs_min + lb->maintain_time; if (rs_min < ms_min) { rs_min = ms_min; } } if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "\n"); jk_printf(s, JK_STATUS_SHOW_MEMBER_ROW, wr->s->name, status_worker_type(wr->w->type), a->host, a->port, jk_dump_hinfo(&a->worker_inet_addr, buf), jk_lb_get_activation(wr, l), jk_lb_get_state(wr, l), wr->s->distance, wr->s->lb_factor, wr->s->lb_mult, wr->s->lb_value, wr->s->elected, wr->s->errors, wr->s->client_errors, wr->s->reply_timeouts, status_strfsize(wr->s->transferred, buf_wr), status_strfsize(wr->s->readed, buf_rd), wr->s->busy, wr->s->max_busy, wr->s->route, wr->s->redirect ? (*wr->s->redirect ? wr->s->redirect : " ") : " ", wr->s->domain ? (*wr->s->domain ? wr->s->domain : " ") : " ", rs_min, rs_max); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 6, 0, "member"); jk_print_xml_att_string(s, 8, "name", wr->s->name); jk_print_xml_att_string(s, 8, "type", status_worker_type(wr->w->type)); jk_print_xml_att_string(s, 8, "host", a->host); jk_print_xml_att_int(s, 8, "port", a->port); jk_print_xml_att_string(s, 8, "address", jk_dump_hinfo(&a->worker_inet_addr, buf)); jk_print_xml_att_string(s, 8, "activation", jk_lb_get_activation(wr, l)); jk_print_xml_att_int(s, 8, "lbfactor", wr->s->lb_factor); jk_print_xml_att_string(s, 8, "route", wr->s->route); jk_print_xml_att_string(s, 8, "redirect", wr->s->redirect); jk_print_xml_att_string(s, 8, "domain", wr->s->domain); jk_print_xml_att_int(s, 8, "distance", wr->s->distance); jk_print_xml_att_string(s, 8, "state", jk_lb_get_state(wr, l)); jk_print_xml_att_uint64(s, 8, "lbmult", wr->s->lb_mult); jk_print_xml_att_uint64(s, 8, "lbvalue", wr->s->lb_value); jk_print_xml_att_uint64(s, 8, "elected", wr->s->elected); jk_print_xml_att_uint32(s, 8, "errors", wr->s->errors); jk_print_xml_att_uint32(s, 8, "client_errors", wr->s->client_errors); jk_print_xml_att_uint32(s, 8, "reply_timeouts", wr->s->reply_timeouts); jk_print_xml_att_uint64(s, 8, "transferred", wr->s->transferred); jk_print_xml_att_uint64(s, 8, "read", wr->s->readed); jk_print_xml_att_int(s, 8, "busy", wr->s->busy); jk_print_xml_att_int(s, 8, "max_busy", wr->s->max_busy); jk_print_xml_att_int(s, 8, "time_to_recover_min", rs_min); jk_print_xml_att_int(s, 8, "time_to_recover_max", rs_max); /* Terminate the tag */ jk_print_xml_stop_elt(s, 6, 1); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Member:"); jk_printf(s, " name=%s", wr->s->name); jk_printf(s, " type=%s", status_worker_type(wr->w->type)); jk_printf(s, " host=%s", a->host); jk_printf(s, " port=%d", a->port); jk_printf(s, " address=%s", jk_dump_hinfo(&a->worker_inet_addr, buf)); jk_printf(s, " activation=%s", jk_lb_get_activation(wr, l)); jk_printf(s, " lbfactor=%d", wr->s->lb_factor); jk_printf(s, " route=\"%s\"", wr->s->route ? wr->s->route : ""); jk_printf(s, " redirect=\"%s\"", wr->s->redirect ? wr->s->redirect : ""); jk_printf(s, " domain=\"%s\"", wr->s->domain ? wr->s->domain : ""); jk_printf(s, " distance=%d", wr->s->distance); jk_printf(s, " state=%s", jk_lb_get_state(wr, l)); jk_printf(s, " lbmult=%" JK_UINT64_T_FMT, wr->s->lb_mult); jk_printf(s, " lbvalue=%" JK_UINT64_T_FMT, wr->s->lb_value); jk_printf(s, " elected=%" JK_UINT64_T_FMT, wr->s->elected); jk_printf(s, " errors=%" JK_UINT32_T_FMT, wr->s->errors); jk_printf(s, " client_errors=%" JK_UINT32_T_FMT, wr->s->client_errors); jk_printf(s, " reply_timeouts=%" JK_UINT32_T_FMT, wr->s->reply_timeouts); jk_printf(s, " transferred=%" JK_UINT64_T_FMT, wr->s->transferred); jk_printf(s, " read=%" JK_UINT64_T_FMT, wr->s->readed); jk_printf(s, " busy=%d", wr->s->busy); jk_printf(s, " max_busy=%d", wr->s->max_busy); jk_printf(s, " time_to_recover_min=%d", rs_min); jk_printf(s, " time_to_recover_max=%d", rs_max); jk_puts(s, "\n"); } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_string(s, w, name, "balance_workers", wr->s->name); jk_print_prop_att_string(s, w, wr->s->name, "type", status_worker_type(wr->w->type)); jk_print_prop_att_string(s, w, wr->s->name, "host", a->host); jk_print_prop_att_int(s, w, wr->s->name, "port", a->port); jk_print_prop_att_string(s, w, wr->s->name, "address", jk_dump_hinfo(&a->worker_inet_addr, buf)); jk_print_prop_att_string(s, w, wr->s->name, "activation", jk_lb_get_activation(wr, l)); jk_print_prop_att_int(s, w, wr->s->name, "lbfactor", wr->s->lb_factor); jk_print_prop_att_string(s, w, wr->s->name, "route", wr->s->route); jk_print_prop_att_string(s, w, wr->s->name, "redirect", wr->s->redirect); jk_print_prop_att_string(s, w, wr->s->name, "domain", wr->s->domain); jk_print_prop_att_int(s, w, wr->s->name, "distance", wr->s->distance); jk_print_prop_att_string(s, w, wr->s->name, "state", jk_lb_get_state(wr, l)); jk_print_prop_att_uint64(s, w, wr->s->name, "lbmult", wr->s->lb_mult); jk_print_prop_att_uint64(s, w, wr->s->name, "lbvalue", wr->s->lb_value); jk_print_prop_att_uint64(s, w, wr->s->name, "elected", wr->s->elected); jk_print_prop_att_uint32(s, w, wr->s->name, "errors", wr->s->errors); jk_print_prop_att_uint32(s, w, wr->s->name, "client_errors", wr->s->client_errors); jk_print_prop_att_uint32(s, w, wr->s->name, "reply_timeouts", wr->s->reply_timeouts); jk_print_prop_att_uint64(s, w, wr->s->name, "transferred", wr->s->transferred); jk_print_prop_att_uint64(s, w, wr->s->name, "read", wr->s->readed); jk_print_prop_att_int(s, w, wr->s->name, "busy", wr->s->busy); jk_print_prop_att_int(s, w, wr->s->name, "max_busy", wr->s->max_busy); jk_print_prop_att_int(s, w, wr->s->name, "time_to_recover_min", rs_min); jk_print_prop_att_int(s, w, wr->s->name, "time_to_recover_max", rs_max); } } if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "
"); if (!read_only) { jk_puts(s, "["); status_write_uri(s, p, "E", JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, wr->s->name, 0, 0, "", l); jk_puts(s, "|"); status_write_uri(s, p, "R", JK_STATUS_CMD_RESET, JK_STATUS_MIME_UNKNOWN, name, wr->s->name, 0, 0, "", l); if (wr->s->state == JK_LB_STATE_ERROR) { jk_puts(s, "|"); status_write_uri(s, p, "T", JK_STATUS_CMD_RECOVER, JK_STATUS_MIME_UNKNOWN, name, wr->s->name, 0, 0, "", l); } jk_puts(s, "]"); } jk_puts(s, " 

\n"); if (!read_only) { jk_puts(s, "Edit one attribute for all members: ["); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_ACTIVATION, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_ACTIVATION, l); jk_puts(s, "\n|"); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_FACTOR, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_FACTOR, l); jk_puts(s, "\n|"); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_ROUTE, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_ROUTE, l); jk_puts(s, "\n|"); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_REDIRECT, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_REDIRECT, l); jk_puts(s, "\n|"); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_DOMAIN, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_DOMAIN, l); jk_puts(s, "\n|"); status_write_uri(s, p, JK_STATUS_ARG_LBM_TEXT_DISTANCE, JK_STATUS_CMD_EDIT, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, JK_STATUS_ARG_LBM_DISTANCE, l); jk_puts(s, "\n]
\n"); } } } else { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

\n"); if (single) { status_write_uri(s, p, "Show Balancer Members", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_MEMBERS, "", l); } else { status_write_uri(s, p, "Show Balancer Members", JK_STATUS_CMD_LIST, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_MEMBERS, "", l); } jk_puts(s, "

\n"); } } if (name) display_maps(s, p, name, l); if (mime == JK_STATUS_MIME_XML) { jk_print_xml_close_elt(s, w, 2, "balancer"); } JK_TRACE_EXIT(l); } static void display_worker_ajp(jk_ws_service_t *s, status_endpoint_t *p, ajp_worker_t *aw, jk_logger_t *l) { char buf[32]; int cmd; int mime; int single = 0; const char *arg; int map_count; const char *name = aw->name; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l); cmd = status_cmd_int(arg); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); if (cmd == JK_STATUS_CMD_SHOW) { single = 1; } map_count = count_maps(s, name, l); if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

["); if (single) jk_puts(s, "S"); else status_write_uri(s, p, "S", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN, name, "", 0, 0, "", l); jk_puts(s, "]  "); jk_putv(s, "Worker Status for ", name, "

\n", NULL); jk_puts(s, "" JK_STATUS_SHOW_AJP_HEAD); jk_printf(s, JK_STATUS_SHOW_AJP_ROW, status_worker_type(aw->worker.type), aw->host, aw->port, jk_dump_hinfo(&aw->worker_inet_addr, buf)); jk_puts(s, "
\n"); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 0, 0, "ajp"); jk_print_xml_att_string(s, 2, "name", name); jk_print_xml_att_string(s, 2, "type", status_worker_type(aw->worker.type)); jk_print_xml_att_string(s, 2, "host", aw->host); jk_print_xml_att_int(s, 2, "port", aw->port); jk_print_xml_att_string(s, 2, "address", jk_dump_hinfo(&aw->worker_inet_addr, buf)); jk_print_xml_att_int(s, 2, "map_count", map_count); /* Terminate the tag */ jk_print_xml_stop_elt(s, 0, 0); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "AJP Worker:"); jk_printf(s, " name=%s", name); jk_printf(s, " type=%s", status_worker_type(aw->worker.type)); jk_printf(s, " host=%s", aw->host); jk_printf(s, " port=%d", aw->port); jk_printf(s, " address=%s", jk_dump_hinfo(&aw->worker_inet_addr, buf)); jk_printf(s, " map_count=%d", map_count); jk_puts(s, "\n"); } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_string(s, w, NULL, "list", name); jk_print_prop_att_string(s, w, name, "type", status_worker_type(aw->worker.type)); jk_print_prop_att_string(s, w, name, "host", aw->host); jk_print_prop_att_int(s, w, name, "port", aw->port); jk_print_prop_att_string(s, w, name, "address", jk_dump_hinfo(&aw->worker_inet_addr, buf)); jk_print_prop_att_int(s, w, name, "map_count", map_count); } if (name) display_maps(s, p, name, l); if (mime == JK_STATUS_MIME_XML) { jk_print_xml_close_elt(s, w, 0, "ajp"); } JK_TRACE_EXIT(l); } static void display_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, jk_logger_t *l) { status_worker_t *w = p->worker; JK_TRACE_ENTER(l); if (jw->type == JK_LB_WORKER_TYPE) { lb_worker_t *lb = (lb_worker_t *)jw->worker_private; if (lb) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' %s lb worker '%s'", w->name, "displaying", lb->s->name); display_worker_lb(s, p, lb, l); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' lb worker is (null)", w->name); } } else if (jw->type == JK_AJP13_WORKER_TYPE || jw->type == JK_AJP14_WORKER_TYPE) { ajp_worker_t *aw = (ajp_worker_t *)jw->worker_private; if (aw) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' %s ajp worker '%s'", w->name, "displaying", aw->name); display_worker_ajp(s, p, aw, l); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' aw worker is (null)", w->name); } } else { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return; } } static void form_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, jk_logger_t *l) { const char *name = NULL; lb_worker_t *lb = NULL; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); if (jw->type == JK_LB_WORKER_TYPE) { lb = (lb_worker_t *)jw->worker_private; name = lb->s->name; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' producing edit form for lb worker '%s'", w->name, name); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return; } if (!lb) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' lb structure is (null)", w->name); JK_TRACE_EXIT(l); return; } jk_shm_lock(); if (lb->sequence != lb->s->sequence) jk_lb_pull(lb, l); jk_shm_unlock(); jk_putv(s, "

Edit load balancer settings for ", name, "

\n", NULL); status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); jk_putv(s, "\n\n", lb->retries); jk_putv(s, "\n", lb->recover_wait_time); jk_putv(s, "\n", lb->max_reply_timeouts); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n", NULL); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n", NULL); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_puts(s, "
", JK_STATUS_ARG_LB_TEXT_RETRIES, ":
", JK_STATUS_ARG_LB_TEXT_RECOVER_TIME, ":
", JK_STATUS_ARG_LB_TEXT_MAX_REPLY_TIMEOUTS, ":
", JK_STATUS_ARG_LB_TEXT_STICKY, ":sticky_session) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
", JK_STATUS_ARG_LB_TEXT_STICKY_FORCE, ":sticky_session_force) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
", JK_STATUS_ARG_LB_TEXT_METHOD, ":
  Requestslbmethod == JK_LB_METHOD_REQUESTS) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Trafficlbmethod == JK_LB_METHOD_TRAFFIC) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Busynesslbmethod == JK_LB_METHOD_BUSYNESS) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Sessionslbmethod == JK_LB_METHOD_SESSIONS) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
", JK_STATUS_ARG_LB_TEXT_LOCK, ":
  Optimisticlblock == JK_LB_LOCK_OPTIMISTIC) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Pessimisticlblock == JK_LB_LOCK_PESSIMISTIC) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
\n"); jk_puts(s, "
\n"); JK_TRACE_EXIT(l); } static void form_member(jk_ws_service_t *s, status_endpoint_t *p, worker_record_t *wr, const char *lb_name, jk_logger_t *l) { status_worker_t *w = p->worker; JK_TRACE_ENTER(l); if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' producing edit form for sub worker '%s' of lb worker '%s'", w->name, wr->s->name, lb_name); jk_putv(s, "

Edit worker settings for ", wr->s->name, "

\n", NULL); status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); jk_puts(s, "\n"); jk_putv(s, "\n", NULL); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n", wr->s->lb_factor); jk_putv(s, "\n", wr->s->route); jk_putv(s, "\n"); jk_putv(s, "\n"); jk_putv(s, "\n", wr->s->distance); jk_puts(s, "
", JK_STATUS_ARG_LBM_TEXT_ACTIVATION, ":
  Actives->activation == JK_LB_ACTIVATION_ACTIVE) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Disableds->activation == JK_LB_ACTIVATION_DISABLED) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
  Stoppeds->activation == JK_LB_ACTIVATION_STOPPED) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>
", JK_STATUS_ARG_LBM_TEXT_FACTOR, ":
", JK_STATUS_ARG_LBM_TEXT_ROUTE, ":
", JK_STATUS_ARG_LBM_TEXT_REDIRECT, ":s->redirect, NULL); jk_puts(s, "\"/>
", JK_STATUS_ARG_LBM_TEXT_DOMAIN, ":s->domain, NULL); jk_puts(s, "\"/>
", JK_STATUS_ARG_LBM_TEXT_DISTANCE, ":
\n"); jk_puts(s, "
\n\n"); JK_TRACE_EXIT(l); } static void form_all_members(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, const char *attribute, jk_logger_t *l) { const char *name = NULL; lb_worker_t *lb = NULL; status_worker_t *w = p->worker; const char *aname; unsigned int i; JK_TRACE_ENTER(l); if (!attribute) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' missing request parameter '%s'", w->name, JK_STATUS_ARG_ATTRIBUTE); JK_TRACE_EXIT(l); return; } else { if (!strcmp(attribute, JK_STATUS_ARG_LBM_ACTIVATION)) aname=JK_STATUS_ARG_LBM_TEXT_ACTIVATION; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_FACTOR)) aname=JK_STATUS_ARG_LBM_TEXT_FACTOR; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_ROUTE)) aname=JK_STATUS_ARG_LBM_TEXT_ROUTE; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_REDIRECT)) aname=JK_STATUS_ARG_LBM_TEXT_REDIRECT; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DOMAIN)) aname=JK_STATUS_ARG_LBM_TEXT_DOMAIN; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DISTANCE)) aname=JK_STATUS_ARG_LBM_TEXT_DISTANCE; else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' unknown attribute '%s'", w->name, attribute); JK_TRACE_EXIT(l); return; } } if (jw->type == JK_LB_WORKER_TYPE) { lb = (lb_worker_t *)jw->worker_private; name = lb->s->name; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' producing edit form for attribute '%s' [%s] of all members of lb worker '%s'", w->name, attribute, aname, name); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return; } if (lb) { jk_putv(s, "

Edit attribute '", aname, "' for all members of load balancer ", name, "

\n", NULL); status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); jk_putv(s, "" "" "", NULL); for (i = 0; i < lb->num_of_workers; i++) { worker_record_t *wr = &(lb->lb_workers[i]); jk_putv(s, ""); } jk_puts(s, "
Balanced Worker", aname, "
", wr->s->name, "\n", NULL); if (!strcmp(attribute, JK_STATUS_ARG_LBM_ACTIVATION)) { jk_printf(s, "Active: s->activation == JK_LB_ACTIVATION_ACTIVE) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/> | \n"); jk_printf(s, "Disabled: s->activation == JK_LB_ACTIVATION_DISABLED) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/> | \n"); jk_printf(s, "Stopped: s->activation == JK_LB_ACTIVATION_STOPPED) jk_puts(s, " checked=\"checked\""); jk_puts(s, "/>\n"); } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_FACTOR)) { jk_printf(s, "\n", wr->s->lb_factor); } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_ROUTE)) { jk_printf(s, "s->route, "\"/>\n", NULL); } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_REDIRECT)) { jk_printf(s, "s->redirect, "\"/>\n", NULL); } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DOMAIN)) { jk_printf(s, "s->domain, "\"/>\n", NULL); } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DISTANCE)) { jk_printf(s, "\n", wr->s->distance); } jk_puts(s, "
\n"); jk_puts(s, "
\n"); } JK_TRACE_EXIT(l); } static void commit_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, jk_logger_t *l) { const char *name = NULL; lb_worker_t *lb = NULL; status_worker_t *w = p->worker; const char *arg; int i; JK_TRACE_ENTER(l); if (jw->type == JK_LB_WORKER_TYPE) { lb = (lb_worker_t *)jw->worker_private; name = lb->s->name; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' committing changes for lb worker '%s'", w->name, name); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return; } if (!lb) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' lb structure is (null)", w->name); JK_TRACE_EXIT(l); return; } if (lb->sequence != lb->s->sequence) jk_lb_pull(lb, l); i = status_get_int(p, JK_STATUS_ARG_LB_RETRIES, lb->retries, l); if (i != lb->retries && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'retries' for lb worker '%s' to '%i'", w->name, name, i); lb->retries = i; } i = status_get_int(p, JK_STATUS_ARG_LB_RECOVER_TIME, lb->recover_wait_time, l); if (i != lb->recover_wait_time && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'recover_time' for lb worker '%s' to '%i'", w->name, name, i); lb->recover_wait_time = i; } i = status_get_int(p, JK_STATUS_ARG_LB_MAX_REPLY_TIMEOUTS, lb->max_reply_timeouts, l); if (i != lb->max_reply_timeouts && i >= 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'max_reply_timeouts' for lb worker '%s' to '%i'", w->name, name, i); lb->max_reply_timeouts = i; } i = status_get_bool(p, JK_STATUS_ARG_LB_STICKY, 0, l); if (i != lb->sticky_session) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'sticky_session' for lb worker '%s' to '%i'", w->name, name, i); lb->sticky_session = i; } i = status_get_bool(p, JK_STATUS_ARG_LB_STICKY_FORCE, 0, l); if (i != lb->sticky_session_force) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'sticky_session_force' for lb worker '%s' to '%i'", w->name, name, i); lb->sticky_session_force = i; } if (status_get_string(p, JK_STATUS_ARG_LB_METHOD, NULL, &arg, l) == JK_TRUE) { i = jk_lb_get_method_code(arg); if (i != lb->lbmethod && i >= 0 && i <= JK_LB_METHOD_MAX) { lb->lbmethod = i; jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'method' for lb worker '%s' to '%s'", w->name, name, jk_lb_get_method(lb, l)); } } if (status_get_string(p, JK_STATUS_ARG_LB_LOCK, NULL, &arg, l) == JK_TRUE) { i = jk_lb_get_lock_code(arg); if (i != lb->lblock && i >= 0 && i <= JK_LB_LOCK_MAX) { lb->lblock = i; jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'lock' for lb worker '%s' to '%s'", w->name, name, jk_lb_get_lock(lb, l)); } } lb->sequence++; jk_lb_push(lb, l); } static int commit_member(jk_ws_service_t *s, status_endpoint_t *p, worker_record_t *wr, const char *lb_name, jk_logger_t *l) { const char *arg; status_worker_t *w = p->worker; int rc = 0; int rv; int i; JK_TRACE_ENTER(l); if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' committing changes for sub worker '%s' of lb worker '%s'", w->name, wr->s->name, lb_name); if (status_get_string(p, JK_STATUS_ARG_LBM_ACTIVATION, NULL, &arg, l) == JK_TRUE) { i = jk_lb_get_activation_code(arg); if (i != wr->s->activation && i >= 0 && i <= JK_LB_ACTIVATION_MAX) { wr->s->activation = i; jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'activation' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, lb_name, jk_lb_get_activation(wr, l)); rc |= 1; } } i = status_get_int(p, JK_STATUS_ARG_LBM_FACTOR, wr->s->lb_factor, l); if (i != wr->s->lb_factor && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'lbfactor' for sub worker '%s' of lb worker '%s' to '%i'", w->name, wr->s->name, lb_name, i); wr->s->lb_factor = i; /* Recalculate the load multiplicators wrt. lb_factor */ rc |= 2; } if ((rv = status_get_string(p, JK_STATUS_ARG_LBM_ROUTE, NULL, &arg, l)) == JK_TRUE) { if (strncmp(wr->s->route, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'route' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, lb_name, arg); strncpy(wr->s->route, arg, JK_SHM_STR_SIZ); if (!wr->s->domain[0]) { char * id_domain = strchr(wr->s->route, '.'); if (id_domain) { *id_domain = '\0'; strcpy(wr->s->domain, wr->s->route); *id_domain = '.'; } } } } if ((rv = status_get_string(p, JK_STATUS_ARG_LBM_REDIRECT, NULL, &arg, l)) == JK_TRUE) { if (strncmp(wr->s->redirect, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'redirect' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, lb_name, arg); strncpy(wr->s->redirect, arg, JK_SHM_STR_SIZ); } } if ((rv = status_get_string(p, JK_STATUS_ARG_LBM_DOMAIN, NULL, &arg, l)) == JK_TRUE) { if (strncmp(wr->s->domain, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'domain' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, lb_name, arg); strncpy(wr->s->domain, arg, JK_SHM_STR_SIZ); } } i = status_get_int(p, JK_STATUS_ARG_LBM_DISTANCE, wr->s->distance, l); if (i != wr->s->distance && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'distance' for sub worker '%s' of lb worker '%s' to '%i'", w->name, wr->s->name, lb_name, i); wr->s->distance = i; } return rc; } static void commit_all_members(jk_ws_service_t *s, status_endpoint_t *p, jk_worker_t *jw, const char *attribute, jk_logger_t *l) { const char *arg; char vname[32]; const char *name = NULL; lb_worker_t *lb = NULL; status_worker_t *w = p->worker; const char *aname; int i; int rc = 0; unsigned int j; JK_TRACE_ENTER(l); if (!attribute) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' missing request parameter '%s'", w->name, JK_STATUS_ARG_ATTRIBUTE); JK_TRACE_EXIT(l); return; } else { if (!strcmp(attribute, JK_STATUS_ARG_LBM_ACTIVATION)) aname=JK_STATUS_ARG_LBM_TEXT_ACTIVATION; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_FACTOR)) aname=JK_STATUS_ARG_LBM_TEXT_FACTOR; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_ROUTE)) aname=JK_STATUS_ARG_LBM_TEXT_ROUTE; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_REDIRECT)) aname=JK_STATUS_ARG_LBM_TEXT_REDIRECT; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DOMAIN)) aname=JK_STATUS_ARG_LBM_TEXT_DOMAIN; else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DISTANCE)) aname=JK_STATUS_ARG_LBM_TEXT_DISTANCE; else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' unknown attribute '%s'", w->name, attribute); JK_TRACE_EXIT(l); return; } } if (jw->type == JK_LB_WORKER_TYPE) { lb = (lb_worker_t *)jw->worker_private; name = lb->s->name; if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' committing changes for attribute '%s' [%s] of all members of lb worker '%s'", w->name, attribute, aname, name); } else { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return; } if (lb) { for (j = 0; j < lb->num_of_workers; j++) { worker_record_t *wr = &(lb->lb_workers[j]); snprintf(vname, 32-1, "" JK_STATUS_ARG_MULT_VALUE_BASE "%d", j); if (!strcmp(attribute, JK_STATUS_ARG_LBM_FACTOR)) { i = status_get_int(p, vname, wr->s->lb_factor, l); if (i != wr->s->lb_factor && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'lbfactor' for sub worker '%s' of lb worker '%s' to '%i'", w->name, wr->s->name, name, i); wr->s->lb_factor = i; rc = 2; } } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DISTANCE)) { i = status_get_int(p, vname, wr->s->distance, l); if (i != wr->s->distance && i > 0) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'distance' for sub worker '%s' of lb worker '%s' to '%i'", w->name, wr->s->name, name, i); wr->s->lb_factor = i; } } else { int rv = status_get_string(p, vname, NULL, &arg, l); if (!strcmp(attribute, JK_STATUS_ARG_LBM_ACTIVATION)) { if (rv == JK_TRUE) { i = jk_lb_get_activation_code(arg); if (i != wr->s->activation && i >= 0 && i <= JK_LB_ACTIVATION_MAX) { wr->s->activation = i; jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'activation' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, name, jk_lb_get_activation(wr, l)); rc = 1; } } } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_ROUTE)) { if (rv == JK_TRUE) { if (strncmp(wr->s->route, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'route' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, name, arg); strncpy(wr->s->route, arg, JK_SHM_STR_SIZ); if (!wr->s->domain[0]) { char * id_domain = strchr(wr->s->route, '.'); if (id_domain) { *id_domain = '\0'; strcpy(wr->s->domain, wr->s->route); *id_domain = '.'; } } } } } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_REDIRECT)) { if (rv == JK_TRUE) { if (strncmp(wr->s->redirect, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'redirect' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, name, arg); strncpy(wr->s->redirect, arg, JK_SHM_STR_SIZ); } } } else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DOMAIN)) { if (rv == JK_TRUE) { if (strncmp(wr->s->domain, arg, JK_SHM_STR_SIZ)) { jk_log(l, JK_LOG_INFO, "Status worker '%s' setting 'domain' for sub worker '%s' of lb worker '%s' to '%s'", w->name, wr->s->name, name, arg); strncpy(wr->s->domain, arg, JK_SHM_STR_SIZ); } } } } } if (rc == 1) reset_lb_values(lb, l); else if (rc == 2) /* Recalculate the load multiplicators wrt. lb_factor */ update_mult(lb, l); } JK_TRACE_EXIT(l); } static void display_legend(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { int mime; const char *arg; unsigned int hide_legend; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); if (mime != JK_STATUS_MIME_HTML) { JK_TRACE_EXIT(l); return; } hide_legend = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_NO_LEGEND; if (hide_legend) { jk_puts(s, "

\n"); status_write_uri(s, p, "Show Legend", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_LEGEND, NULL, l); jk_puts(s, "

\n"); } else { jk_puts(s, "

Legend ["); status_write_uri(s, p, "Hide", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_LEGEND, 0, NULL, l); jk_puts(s, "]

\n"); jk_puts(s, "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "
NameWorker name
TypeWorker type
RouteWorker route
AddrBackend Address info
ActWorker activation configuration
\n" "ACT=Active, DIS=Disabled, STP=Stopped
StateWorker error status
\n" "OK=OK, ERR=Error with substates
\n" "IDLE=No requests handled, BUSY=All connections busy,
\n" "REC=Recovering, PRB=Probing, FRC=Forced Recovery
DWorker distance
FLoad Balancer factor
MLoad Balancer multiplicity
VLoad Balancer value
AccNumber of requests
ErrNumber of failed requests
CENumber of client errors
RENumber of reply timeouts (decayed)
WrNumber of bytes transferred/min
RdNumber of bytes read/min
BusyCurrent number of busy connections
MaxMaximum number of busy connections
RRRoute redirect
CdCluster domain
RsRecovery scheduled in app. min/max seconds
\n"); } JK_TRACE_EXIT(l); } static int check_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; worker_record_t *wr = NULL; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "checking", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (sub_worker && sub_worker[0]) { if(search_sub_worker(s, p, jw, worker, &wr, sub_worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } } JK_TRACE_EXIT(l); return JK_TRUE; } static void count_workers(jk_ws_service_t *s, status_endpoint_t *p, int *lb_cnt, int *ajp_cnt, jk_logger_t *l) { unsigned int i; jk_worker_t *jw = NULL; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); *lb_cnt = 0; *ajp_cnt = 0; for (i = 0; i < w->we->num_of_workers; i++) { jw = wc_get_worker_for_name(w->we->worker_list[i], l); if (!jw) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' could not find worker '%s'", w->name, w->we->worker_list[i]); continue; } if (jw->type == JK_LB_WORKER_TYPE) { (*lb_cnt)++; } else if (jw->type == JK_AJP13_WORKER_TYPE || jw->type == JK_AJP14_WORKER_TYPE) { (*ajp_cnt)++; } } JK_TRACE_EXIT(l); } static void list_workers_type(jk_ws_service_t *s, status_endpoint_t *p, int list_lb, int count, jk_logger_t *l) { const char *arg; unsigned int i; int mime; unsigned int hide; jk_worker_t *jw = NULL; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); if (list_lb) { hide = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_NO_LB; if (hide) { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

\n"); status_write_uri(s, p, "Show Load Balancing Workers", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_LB, NULL, l); jk_puts(s, "

\n"); } } else { if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 0, 0, "balancers"); jk_print_xml_att_int(s, 2, "count", count); jk_print_xml_stop_elt(s, 0, 0); } else if (mime == JK_STATUS_MIME_TXT) { jk_printf(s, "Balancer Workers: count=%d\n", count); } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_int(s, w, NULL, "lb_count", count); } else { jk_printf(s, "

Listing Load Balancing Worker%s (%d Worker%s) [", count>1 ? "s" : "", count, count>1 ? "s" : ""); status_write_uri(s, p, "Hide", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_LB, 0, NULL, l); jk_puts(s, "]

\n"); } } } else { hide = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_NO_AJP; if (hide) { if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "

\n"); status_write_uri(s, p, "Show AJP Workers", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_NO_AJP, NULL, l); jk_puts(s, "

\n"); } } else { if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 0, 0, "ajp_workers"); jk_print_xml_att_int(s, 2, "count", count); jk_print_xml_stop_elt(s, 0, 0); } else if (mime == JK_STATUS_MIME_TXT) { jk_printf(s, "AJP Workers: count=%d\n", count); } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_int(s, w, NULL, "ajp_count", count); } else { jk_printf(s, "

Listing AJP Worker%s (%d Worker%s) [", count>1 ? "s" : "", count, count>1 ? "s" : ""); status_write_uri(s, p, "Hide", JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_NO_AJP, 0, NULL, l); jk_puts(s, "]

\n"); } } } if (hide) { JK_TRACE_EXIT(l); return; } for (i = 0; i < w->we->num_of_workers; i++) { jw = wc_get_worker_for_name(w->we->worker_list[i], l); if (!jw) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' could not find worker '%s'", w->name, w->we->worker_list[i]); continue; } if ((list_lb && jw->type == JK_LB_WORKER_TYPE) || (!list_lb && jw->type != JK_LB_WORKER_TYPE)) { display_worker(s, p, jw, l); } } if (list_lb) { if (mime == JK_STATUS_MIME_XML) { jk_print_xml_close_elt(s, w, 0, "balancers"); } else if (mime == JK_STATUS_MIME_TXT) { } else if (mime == JK_STATUS_MIME_PROP) { } else if (mime == JK_STATUS_MIME_HTML) { } } else { if (mime == JK_STATUS_MIME_XML) { jk_print_xml_close_elt(s, w, 0, "ajp_workers"); } else if (mime == JK_STATUS_MIME_TXT) { } else if (mime == JK_STATUS_MIME_PROP) { } else if (mime == JK_STATUS_MIME_HTML) { } } JK_TRACE_EXIT(l); } static int list_workers(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { int lb_cnt = 0; int ajp_cnt = 0; JK_TRACE_ENTER(l); count_workers(s, p, &lb_cnt, &ajp_cnt, l); if (lb_cnt) { list_workers_type(s, p, 1, lb_cnt, l); } if (ajp_cnt) { list_workers_type(s, p, 0, ajp_cnt, l); } display_legend(s, p, l); JK_TRACE_EXIT(l); return JK_TRUE; } static int show_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "showing", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } display_worker(s, p, jw, l); display_legend(s, p, l); JK_TRACE_EXIT(l); return JK_TRUE; } static int edit_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "editing", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (!sub_worker || !sub_worker[0]) { const char *arg; if (status_get_string(p, JK_STATUS_ARG_ATTRIBUTE, NULL, &arg, l) == JK_TRUE) form_all_members(s, p, jw, arg, l); else form_worker(s, p, jw, l); } else { worker_record_t *wr = NULL; if (jw->type != JK_LB_WORKER_TYPE) { jk_log(l, JK_LOG_WARNING, "Status worker '%s' worker type not implemented", w->name); JK_TRACE_EXIT(l); return JK_FALSE; } if(search_sub_worker(s, p, jw, worker, &wr, sub_worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } form_member(s, p, wr, worker, l); } JK_TRACE_EXIT(l); return JK_TRUE; } static int update_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "updating", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (!sub_worker || !sub_worker[0]) { const char *arg; if (status_get_string(p, JK_STATUS_ARG_ATTRIBUTE, NULL, &arg, l) == JK_TRUE) commit_all_members(s, p, jw, arg, l); else commit_worker(s, p, jw, l); } else { lb_worker_t *lb = NULL; worker_record_t *wr = NULL; int rc = 0; if (check_valid_lb(s, p, jw, worker, &lb, 0, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if(search_sub_worker(s, p, jw, worker, &wr, sub_worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } rc = commit_member(s, p, wr, lb->s->name, l); if (rc & 1) reset_lb_values(lb, l); if (rc & 2) /* Recalculate the load multiplicators wrt. lb_factor */ update_mult(lb, l); } JK_TRACE_EXIT(l); return JK_TRUE; } static int reset_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { unsigned int i; const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; lb_worker_t *lb = NULL; worker_record_t *wr = NULL; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "resetting", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } /* XXX Until now, we only have something to reset for lb workers or their members */ if (check_valid_lb(s, p, jw, worker, &lb, 0, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (!sub_worker || !sub_worker[0]) { lb->s->max_busy = 0; for (i = 0; i < lb->num_of_workers; i++) { wr = &(lb->lb_workers[i]); wr->s->client_errors = 0; wr->s->reply_timeouts = 0; wr->s->elected = 0; wr->s->elected_snapshot = 0; wr->s->error_time = 0; wr->s->errors = 0; wr->s->lb_value = 0; wr->s->max_busy = 0; wr->s->recoveries = 0; wr->s->recovery_errors = 0; wr->s->readed = 0; wr->s->transferred = 0; wr->s->state = JK_LB_STATE_IDLE; } JK_TRACE_EXIT(l); return JK_TRUE; } else { if(search_sub_worker(s, p, jw, worker, &wr, sub_worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } wr->s->client_errors = 0; wr->s->reply_timeouts = 0; wr->s->elected = 0; wr->s->elected_snapshot = 0; wr->s->error_time = 0; wr->s->errors = 0; wr->s->lb_value = 0; wr->s->max_busy = 0; wr->s->recoveries = 0; wr->s->recovery_errors = 0; wr->s->readed = 0; wr->s->transferred = 0; wr->s->state = JK_LB_STATE_IDLE; JK_TRACE_EXIT(l); return JK_TRUE; } JK_TRACE_EXIT(l); return JK_FALSE; } static int recover_worker(jk_ws_service_t *s, status_endpoint_t *p, jk_logger_t *l) { const char *worker; const char *sub_worker; jk_worker_t *jw = NULL; worker_record_t *wr = NULL; status_worker_t *w = p->worker; JK_TRACE_ENTER(l); fetch_worker_and_sub_worker(p, "recovering", &worker, &sub_worker, l); if (search_worker(s, p, &jw, worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if(search_sub_worker(s, p, jw, worker, &wr, sub_worker, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (wr->s->state == JK_LB_STATE_ERROR) { lb_worker_t *lb = NULL; /* We need an lb to correct the lb_value */ if (check_valid_lb(s, p, jw, worker, &lb, 0, l) == JK_FALSE) { JK_TRACE_EXIT(l); return JK_FALSE; } if (lb->lbmethod != JK_LB_METHOD_BUSYNESS) { unsigned int i; jk_uint64_t curmax = 0; for (i = 0; i < lb->num_of_workers; i++) { if (lb->lb_workers[i].s->lb_value > curmax) { curmax = lb->lb_workers[i].s->lb_value; } } wr->s->lb_value = curmax; } wr->s->reply_timeouts = 0; wr->s->state = JK_LB_STATE_RECOVER; jk_log(l, JK_LOG_INFO, "Status worker '%s' marked worker '%s' sub worker '%s' for recovery", w->name, worker ? worker : "(null)", sub_worker ? sub_worker : "(null)"); JK_TRACE_EXIT(l); return JK_TRUE; } jk_log(l, JK_LOG_WARNING, "Status worker '%s' could not mark worker '%s' sub worker '%s' for recovery - state %s is not an error state", w->name, worker ? worker : "(null)", sub_worker ? sub_worker : "(null)", jk_lb_get_state(wr, l)); JK_TRACE_EXIT(l); return JK_FALSE; } static int JK_METHOD service(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, int *is_error) { int cmd; int mime; int refresh; int read_only = 0; const char *arg; char *err = NULL; status_endpoint_t *p; status_worker_t *w; int denied = 0; JK_TRACE_ENTER(l); if (!e || !e->endpoint_private || !s || !is_error) { JK_LOG_NULL_PARAMS(l); if (is_error) *is_error = JK_HTTP_SERVER_ERROR; JK_TRACE_EXIT(l); return JK_FALSE; } p = e->endpoint_private; w = p->worker; /* Set returned error to OK */ *is_error = JK_HTTP_OK; if (w->num_of_users) { if (s->remote_user) { unsigned int i; denied = 1; for (i = 0; i < w->num_of_users; i++) { if (w->user_case_insensitive) { if (!strcasecmp(s->remote_user, w->user_names[i])) { denied = 0; break; } } else { if (!strcmp(s->remote_user, w->user_names[i])) { denied = 0; break; } } } } else { denied = 2; } } /* Step 1: Process GET params and update configuration */ if (status_parse_uri(s, p, l) != JK_TRUE) { err = "Error during parsing of URI"; } status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l); cmd = status_cmd_int(arg); status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l); mime = status_mime_int(arg); refresh = status_get_int(p, JK_STATUS_ARG_REFRESH, 0, l); if (w->read_only) { read_only = 1; } else { read_only = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) & JK_STATUS_ARG_OPTION_READ_ONLY; } if (mime == JK_STATUS_MIME_HTML) { s->start_response(s, 200, "OK", headers_names, headers_vhtml, 3); jk_puts(s, JK_STATUS_HEAD); } else if (mime == JK_STATUS_MIME_XML) { s->start_response(s, 200, "OK", headers_names, headers_vxml, 3); jk_puts(s, JK_STATUS_XMLH); if (w->doctype) { jk_putv(s, w->doctype, "\n", NULL); } jk_print_xml_start_elt(s, w, 0, 0, "status"); if (w->xmlns && strlen(w->xmlns)) jk_putv(s, " ", w->xmlns, NULL); jk_print_xml_stop_elt(s, 0, 0); } else { s->start_response(s, 200, "OK", headers_names, headers_vtxt, 3); } if (denied == 0) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' service allowed for user '%s' [%s] from %s [%s]", w->name, s->remote_user ? s->remote_user : "(null)", s->auth_type ? s->auth_type : "(null)", s->remote_addr ? s->remote_addr : "(null)", s->remote_host ? s->remote_host : "(null)"); } else if (denied == 1) { err = "Access denied."; jk_log(l, JK_LOG_WARNING, "Status worker '%s' service denied for user '%s' [%s] from %s [%s]", w->name, s->remote_user ? s->remote_user : "(null)", s->auth_type ? s->auth_type : "(null)", s->remote_addr ? s->remote_addr : "(null)", s->remote_host ? s->remote_host : "(null)"); } else if (denied == 2) { err = "Access denied."; jk_log(l, JK_LOG_WARNING, "Status worker '%s' service denied (no user) [%s] from %s [%s]", w->name, s->remote_user ? s->remote_user : "(null)", s->auth_type ? s->auth_type : "(null)", s->remote_addr ? s->remote_addr : "(null)", s->remote_host ? s->remote_host : "(null)"); } else { err = "Access denied."; jk_log(l, JK_LOG_WARNING, "Status worker '%s' service denied (unknown reason) for user '%s' [%s] from %s [%s]", w->name, s->remote_user ? s->remote_user : "(null)", s->auth_type ? s->auth_type : "(null)", s->remote_addr ? s->remote_addr : "(null)", s->remote_host ? s->remote_host : "(null)"); } if (!err) { if (read_only && (cmd == JK_STATUS_CMD_EDIT || cmd == JK_STATUS_CMD_UPDATE || cmd == JK_STATUS_CMD_RESET || cmd == JK_STATUS_CMD_RECOVER)) { err = "This command is not allowed in read only mode."; } } if (!err) { if (cmd == JK_STATUS_CMD_UNKNOWN) { err = "Invalid command."; } else if (mime == JK_STATUS_MIME_UNKNOWN) { err = "Invalid mime type."; } else if (cmd != JK_STATUS_CMD_LIST && cmd != JK_STATUS_CMD_VERSION && (check_worker(s, p, l) != JK_TRUE)) { err = p->msg; } } if (!err) { if (cmd == JK_STATUS_CMD_UPDATE) { /* lock shared memory */ jk_shm_lock(); if (update_worker(s, p, l) == JK_FALSE) { err = "Update failed"; } /* unlock the shared memory */ jk_shm_unlock(); if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "\n"); if (!err) { jk_putv(s, "

Result: OK - You will be redirected in " JK_STATUS_WAIT_AFTER_UPDATE " seconds.

", NULL); } } } else if (cmd == JK_STATUS_CMD_RESET) { /* lock shared memory */ jk_shm_lock(); if (reset_worker(s, p, l) == JK_FALSE) { err = "Reset failed"; } /* unlock the shared memory */ jk_shm_unlock(); if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "\n"); if (!err) { jk_putv(s, "

Result: OK - You will be redirected in " JK_STATUS_WAIT_AFTER_UPDATE " seconds.

", NULL); } } } else if (cmd == JK_STATUS_CMD_RECOVER) { /* lock shared memory */ jk_shm_lock(); if (recover_worker(s, p, l) == JK_FALSE) { err = "Marking worker for recovery failed"; } /* unlock the shared memory */ jk_shm_unlock(); if (mime == JK_STATUS_MIME_HTML) { jk_puts(s, "\n"); if (!err) { jk_putv(s, "

Result: OK - You will be redirected in " JK_STATUS_WAIT_AFTER_UPDATE " seconds.

", NULL); } } } else { if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 0, 0, "server"); jk_print_xml_att_string(s, 2, "name", s->server_name); jk_print_xml_att_int(s, 2, "port", s->server_port); jk_print_xml_stop_elt(s, 0, 1); if ((cmd == JK_STATUS_CMD_LIST) || (cmd == JK_STATUS_CMD_SHOW) || (cmd == JK_STATUS_CMD_VERSION)) { jk_print_xml_start_elt(s, w, 0, 0, "software"); jk_print_xml_att_string(s, 2, "web_server", s->server_software); jk_print_xml_att_string(s, 2, "jk_version", JK_EXPOSED_VERSION); jk_print_xml_stop_elt(s, 0, 1); } if (cmd == JK_STATUS_CMD_LIST) { /* Step 2: Display configuration */ if (list_workers(s, p, l) != JK_TRUE) { err = "Error in listing the workers."; } } else if (cmd == JK_STATUS_CMD_SHOW) { /* Step 2: Display detailed configuration */ if(show_worker(s, p, l) != JK_TRUE) { err = "Error in showing this worker."; } } } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Server:"); jk_printf(s, " name=%s", s->server_name); jk_printf(s, " port=%d", s->server_port); jk_puts(s, "\n"); if ((cmd == JK_STATUS_CMD_LIST) || (cmd == JK_STATUS_CMD_SHOW) || (cmd == JK_STATUS_CMD_VERSION)) { jk_puts(s, "Software:"); jk_printf(s, " web_server=\"%s\"", s->server_software); jk_printf(s, " jk_version=%s", JK_EXPOSED_VERSION); jk_puts(s, "\n"); } if (cmd == JK_STATUS_CMD_LIST) { /* Step 2: Display configuration */ if (list_workers(s, p, l) != JK_TRUE) { err = "Error in listing the workers."; } } else if (cmd == JK_STATUS_CMD_SHOW) { /* Step 2: Display detailed configuration */ if(show_worker(s, p, l) != JK_TRUE) { err = "Error in showing this worker."; } } } else if (mime == JK_STATUS_MIME_PROP) { jk_print_prop_att_string(s, w, NULL, "server_name", s->server_name); jk_print_prop_att_int(s, w, NULL, "server_port", s->server_port); if ((cmd == JK_STATUS_CMD_LIST) || (cmd == JK_STATUS_CMD_SHOW) || (cmd == JK_STATUS_CMD_VERSION)) { jk_print_prop_att_string(s, w, NULL, "web_server", s->server_software); jk_print_prop_att_string(s, w, NULL, "jk_version", JK_EXPOSED_VERSION); } if (cmd == JK_STATUS_CMD_LIST) { /* Step 2: Display configuration */ if (list_workers(s, p, l) != JK_TRUE) { err = "Error in listing the workers."; } } else if (cmd == JK_STATUS_CMD_SHOW) { /* Step 2: Display detailed configuration */ if(show_worker(s, p, l) != JK_TRUE) { err = "Error in showing this worker."; } } } else if (mime == JK_STATUS_MIME_HTML) { if ((cmd == JK_STATUS_CMD_LIST || cmd == JK_STATUS_CMD_SHOW) && refresh > 0) { jk_printf(s, "\n", refresh, s->req_uri, s->query_string); } if (w->css) { jk_putv(s, "\ncss, "\" />\n", NULL); } jk_puts(s, JK_STATUS_HEND); jk_puts(s, "

JK Status Manager for "); jk_puts(s, s->server_name); jk_printf(s, ":%d", s->server_port); if (read_only) { jk_puts(s, " (read only)"); } jk_puts(s, "

\n\n"); if ((cmd == JK_STATUS_CMD_LIST) || (cmd == JK_STATUS_CMD_SHOW) || (cmd == JK_STATUS_CMD_VERSION)) { jk_putv(s, "\n", NULL); jk_putv(s, "
Server Version:", s->server_software, "
JK Version:", JK_EXPOSED_VERSION, "
\n", NULL); jk_puts(s, "
\n"); } if (cmd == JK_STATUS_CMD_LIST || cmd == JK_STATUS_CMD_SHOW) { if (refresh > 0) { const char *str = s->query_string; char *buf = jk_pool_alloc(s->pool, sizeof(char *) * (strlen(str)+1)); int result = 0; size_t scan = 0; size_t len = strlen(JK_STATUS_ARG_REFRESH); while (str[scan] != '\0') { if (strncmp(&str[scan], JK_STATUS_ARG_REFRESH, len) == 0 && str[scan+len] == '=') { scan += len + 1; while (str[scan] != '\0' && str[scan] != '&') scan++; if (str[scan] == '&') scan++; } else { if (result > 0 && str[scan] != '\0' && str[scan] != '&') { buf[result] = '&'; result++; } while (str[scan] != '\0' && str[scan] != '&') { buf[result] = str[scan]; result++; scan++; } if (str[scan] == '&') scan++; } } buf[result] = '\0'; jk_putv(s, "[req_uri, NULL); if (buf && buf[0]) jk_putv(s, "?", buf, NULL); jk_puts(s, "\">Stop auto refresh]  "); } else { status_start_form(s, p, "GET", JK_STATUS_CMD_UNKNOWN, l); jk_puts(s, "\n"); jk_putv(s, "(every ", " ", "seconds)", NULL); jk_puts(s, "\n"); } } if (cmd == JK_STATUS_CMD_SHOW || cmd == JK_STATUS_CMD_EDIT || cmd == JK_STATUS_CMD_VERSION) { int from; status_get_string(p, JK_STATUS_ARG_FROM, NULL, &arg, l); from = status_cmd_int(arg); jk_puts(s, "["); if (cmd == JK_STATUS_CMD_SHOW || cmd == JK_STATUS_CMD_VERSION || from == JK_STATUS_CMD_LIST) { status_write_uri(s, p, "Back to worker list", JK_STATUS_CMD_LIST, JK_STATUS_MIME_UNKNOWN, "", "", 0, 0, "", l); } else { status_write_uri(s, p, "Back to worker view", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, 0, "", l); } jk_puts(s, "]  "); } if (cmd == JK_STATUS_CMD_LIST || cmd == JK_STATUS_CMD_SHOW || cmd == JK_STATUS_CMD_VERSION) { jk_puts(s, "[Change Format: "); status_write_uri(s, p, "XML", 0, JK_STATUS_MIME_XML, NULL, NULL, 0, 0, NULL, l); jk_puts(s, " | "); status_write_uri(s, p, "Property", 0, JK_STATUS_MIME_PROP, NULL, NULL, 0, 0, NULL, l); jk_puts(s, " | "); status_write_uri(s, p, "Text", 0, JK_STATUS_MIME_TXT, NULL, NULL, 0, 0, NULL, l); jk_puts(s, "]  "); } if (cmd == JK_STATUS_CMD_LIST || cmd == JK_STATUS_CMD_SHOW) { if (!w->read_only) { jk_puts(s, "["); if (read_only) { status_write_uri(s, p, "Read/Write", 0, JK_STATUS_MIME_UNKNOWN, NULL, NULL, 0, JK_STATUS_ARG_OPTION_READ_ONLY, NULL, l); } else { status_write_uri(s, p, "Read Only", 0, JK_STATUS_MIME_UNKNOWN, NULL, NULL, JK_STATUS_ARG_OPTION_READ_ONLY, 0, NULL, l); } jk_puts(s, "]  \n"); } } if (cmd == JK_STATUS_CMD_LIST || cmd == JK_STATUS_CMD_SHOW) { jk_puts(s, "["); if (cmd == JK_STATUS_CMD_LIST) jk_puts(s, "S=Show only this worker"); if (!read_only && cmd == JK_STATUS_CMD_LIST) jk_puts(s, ", "); if (!read_only) jk_puts(s, "E=Edit worker, R=Reset worker state, T=Try worker recovery"); jk_puts(s, "]\n"); } if (cmd == JK_STATUS_CMD_LIST) { /* Step 2: Display configuration */ if (list_workers(s, p, l) != JK_TRUE) { err = "Error in listing the workers."; } } else if (cmd == JK_STATUS_CMD_SHOW) { /* Step 2: Display detailed configuration */ if(show_worker(s, p, l) != JK_TRUE) { err = "Error in showing this worker."; } } else if (cmd == JK_STATUS_CMD_EDIT) { /* Step 2: Display edit form */ if(edit_worker(s, p, l) != JK_TRUE) { err = "Error in generating this worker's configuration form."; } } } } } if (err) { jk_log(l, JK_LOG_WARNING, "Status worker '%s': %s", w->name, err); if (mime == JK_STATUS_MIME_HTML) { jk_putv(s, "

Result: ERROR - ", err, "
", NULL); jk_putv(s, "req_uri, "\">JK Status Manager Start Page

", NULL); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 2, 0, "result"); jk_print_xml_att_string(s, 4, "type", "ERROR"); jk_print_xml_att_string(s, 4, "message", err); jk_print_xml_stop_elt(s, 2, 1); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Result:"); jk_printf(s, " type=%s", "ERROR"); jk_printf(s, " message=\"%s\"", err); jk_puts(s, "\n"); } else { jk_print_prop_att_string(s, w, "result", "type", "ERROR"); jk_print_prop_att_string(s, w, "result", "message", err); } } else { if (mime == JK_STATUS_MIME_HTML) { jk_putv(s, "

req_uri, "\">JK Status Manager Start Page

", NULL); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_start_elt(s, w, 2, 0, "result"); jk_print_xml_att_string(s, 4, "type", "OK"); jk_print_xml_att_string(s, 4, "message", "Action finished"); jk_print_xml_stop_elt(s, 2, 1); } else if (mime == JK_STATUS_MIME_TXT) { jk_puts(s, "Result:"); jk_printf(s, " type=%s", "OK"); jk_printf(s, " message=\"%s\"", "Action finished"); jk_puts(s, "\n"); } else { jk_print_prop_att_string(s, w, "result", "type", "OK"); jk_print_prop_att_string(s, w, "result", "message", "Action finished"); } } if (mime == JK_STATUS_MIME_HTML) { if (w->css) { jk_putv(s, "
", JK_STATUS_COPYRIGHT, "
\n", NULL); } else { jk_putv(s, "

", JK_STATUS_COPYRIGHT, "

\n", NULL); } jk_puts(s, JK_STATUS_BEND); } else if (mime == JK_STATUS_MIME_XML) { jk_print_xml_close_elt(s, w, 0, "status"); } JK_TRACE_EXIT(l); return JK_TRUE; } static int JK_METHOD done(jk_endpoint_t **e, jk_logger_t *l) { JK_TRACE_ENTER(l); if (e && *e && (*e)->endpoint_private) { status_endpoint_t *p = (*e)->endpoint_private; free(p); *e = NULL; JK_TRACE_EXIT(l); return JK_TRUE; } JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } static int JK_METHOD validate(jk_worker_t *pThis, jk_map_t *props, jk_worker_env_t *we, jk_logger_t *l) { JK_TRACE_ENTER(l); if (pThis && pThis->worker_private) { JK_TRACE_EXIT(l); return JK_TRUE; } JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } static int JK_METHOD init(jk_worker_t *pThis, jk_map_t *props, jk_worker_env_t *we, jk_logger_t *l) { JK_TRACE_ENTER(l); if (pThis && pThis->worker_private) { status_worker_t *p = pThis->worker_private; char **good_rating; unsigned int num_of_good; char **bad_rating; unsigned int num_of_bad; unsigned int i; p->we = we; p->css = jk_get_worker_style_sheet(props, p->name, NULL); p->prefix = jk_get_worker_prop_prefix(props, p->name, JK_STATUS_PREFIX_DEF); p->ns = jk_get_worker_name_space(props, p->name, JK_STATUS_NS_DEF); p->xmlns = jk_get_worker_xmlns(props, p->name, JK_STATUS_XMLNS_DEF); p->doctype = jk_get_worker_xml_doctype(props, p->name, NULL); p->read_only = jk_get_is_read_only(props, p->name); p->user_case_insensitive = jk_get_worker_user_case_insensitive(props, p->name); if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' is %s and has css '%s', prefix '%s', name space '%s', xml name space '%s', document type '%s'", p->name, p->read_only ? "read-only" : "read/write", p->css ? p->css : "(null)", p->prefix ? p->prefix : "(null)", p->ns ? p->ns : "(null)", p->xmlns ? p->xmlns : "(null)", p->doctype ? p->doctype : "(null)"); if (jk_get_worker_user_list(props, p->name, &(p->user_names), &(p->num_of_users)) && p->num_of_users) { for (i = 0; i < p->num_of_users; i++) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' restricting access to user '%s' case %s", p->name, p->user_names[i], p->user_case_insensitive ? "insensitive" : "sensitive"); } } if (jk_get_worker_good_rating(props, p->name, &good_rating, &num_of_good) && num_of_good) { p->good_mask = 0; for (i = 0; i < num_of_good; i++) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' rating as good: '%s'", p->name, good_rating[i]); p->good_mask |= status_get_rating(good_rating[i], l); } } else { p->good_mask = JK_STATUS_MASK_GOOD_DEF; } if (jk_get_worker_bad_rating(props, p->name, &bad_rating, &num_of_bad) && num_of_bad) { p->bad_mask = 0; for (i = 0; i < num_of_bad; i++) { if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' rating as bad: '%s'", p->name, bad_rating[i]); p->bad_mask |= status_get_rating(bad_rating[i], l); } } else { p->bad_mask = JK_STATUS_MASK_BAD_DEF; } if (JK_IS_DEBUG_LEVEL(l)) jk_log(l, JK_LOG_DEBUG, "Status worker '%s' has good rating for '%08" JK_UINT32_T_HEX_FMT "' and bad rating for '%08" JK_UINT32_T_HEX_FMT "'", p->name, p->good_mask, p->bad_mask); if (p->good_mask & p->bad_mask) jk_log(l, JK_LOG_WARNING, "Status worker '%s' has non empty intersection '%08" JK_UINT32_T_HEX_FMT "' between good rating for '%08" JK_UINT32_T_HEX_FMT "' and bad rating for '%08" JK_UINT32_T_HEX_FMT "'", p->name, p->good_mask & p->bad_mask, p->good_mask, p->bad_mask); } JK_TRACE_EXIT(l); return JK_TRUE; } static int JK_METHOD get_endpoint(jk_worker_t *pThis, jk_endpoint_t **pend, jk_logger_t *l) { JK_TRACE_ENTER(l); if (pThis && pThis->worker_private && pend) { status_endpoint_t *p = (status_endpoint_t *) malloc(sizeof(status_endpoint_t)); p->worker = pThis->worker_private; p->endpoint.endpoint_private = p; p->endpoint.service = service; p->endpoint.done = done; p->req_params = NULL; p->msg = NULL; *pend = &p->endpoint; JK_TRACE_EXIT(l); return JK_TRUE; } else { JK_LOG_NULL_PARAMS(l); } JK_TRACE_EXIT(l); return JK_FALSE; } static int JK_METHOD destroy(jk_worker_t **pThis, jk_logger_t *l) { JK_TRACE_ENTER(l); if (pThis && *pThis && (*pThis)->worker_private) { status_worker_t *private_data = (*pThis)->worker_private; jk_close_pool(&private_data->p); free(private_data); JK_TRACE_EXIT(l); return JK_TRUE; } JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } int JK_METHOD status_worker_factory(jk_worker_t **w, const char *name, jk_logger_t *l) { JK_TRACE_ENTER(l); if (NULL != name && NULL != w) { status_worker_t *private_data = (status_worker_t *) calloc(1, sizeof(status_worker_t)); jk_open_pool(&private_data->p, private_data->buf, sizeof(jk_pool_atom_t) * TINY_POOL_SIZE); private_data->name = name; private_data->worker.worker_private = private_data; private_data->worker.validate = validate; private_data->worker.init = init; private_data->worker.get_endpoint = get_endpoint; private_data->worker.destroy = destroy; private_data->worker.retries = 1; *w = &private_data->worker; JK_TRACE_EXIT(l); return JK_STATUS_WORKER_TYPE; } else { JK_LOG_NULL_PARAMS(l); } JK_TRACE_EXIT(l); return 0; }