| /* |
| * 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 <mturk@jboss.com> * |
| * Author: Rainer Jung <rjung@apache.org> * |
| * Version: $Revision$ * |
| ***************************************************************************/ |
| |
| #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_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_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_NA 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 "<!DOCTYPE HTML PUBLIC \"-//W3C//" \ |
| "DTD HTML 3.2 Final//EN\">\n" \ |
| "<html><head><title>JK Status Manager</title>" |
| |
| #define JK_STATUS_COPYRIGHT "Copyright © 1999-2006, The Apache Software Foundation<br />" \ |
| "Licensed under the <a href=\"http://www.apache.org/licenses/LICENSE-2.0\">" \ |
| "Apache License, Version 2.0</a>." |
| |
| #define JK_STATUS_HEND "</head>\n<body>\n" |
| #define JK_STATUS_BEND "</body>\n</html>\n" |
| |
| #define JK_STATUS_XMLH "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\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 "<form method=\"%s\" action=\"%s\">\n" |
| #define JK_STATUS_FORM_HIDDEN_INT "<input type=\"hidden\" name=\"%s\" value=\"%d\"/>\n" |
| #define JK_STATUS_FORM_HIDDEN_STRING "<input type=\"hidden\" name=\"%s\" value=\"%s\"/>\n" |
| #define JK_STATUS_TABLE_HEAD_3_STRING "<tr><th>%s</th><th>%s</th><th>%s</th></tr>\n" |
| #define JK_STATUS_TABLE_ROW_3_STRING "<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n" |
| #define JK_STATUS_SHOW_AJP_HEAD "<tr>" \ |
| "<th>Type</th>" \ |
| "<th>Host</th>" \ |
| "<th>Addr</th>" \ |
| "</tr>\n" |
| #define JK_STATUS_SHOW_AJP_ROW "<tr>" \ |
| "<td>%s</td>" \ |
| "<td>%s:%d</td>" \ |
| "<td>%s</td>" \ |
| "</tr>\n" |
| #define JK_STATUS_SHOW_LB_HEAD "<tr>" \ |
| "<th>Type</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_STICKY "</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_STICKY_FORCE "</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_RETRIES "</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_METHOD "</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_LOCK "</th>" \ |
| "<th>" JK_STATUS_ARG_LB_TEXT_RECOVER_TIME "</th>" \ |
| "</tr>\n" |
| #define JK_STATUS_SHOW_LB_ROW "<tr>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%d</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%d</td>" \ |
| "</tr>\n" |
| #define JK_STATUS_SHOW_MEMBER_HEAD "<tr>" \ |
| "<th> </th><th>Name</th><th>Type</th>" \ |
| "<th>Host</th><th>Addr</th>" \ |
| "<th>Act</th><th>Stat</th>" \ |
| "<th>D</th><th>F</th><th>M</th>" \ |
| "<th>V</th><th>Acc</th>" \ |
| "<th>Err</th><th>CE</th>" \ |
| "<th>Wr</th><th>Rd</th><th>Busy</th><th>Max</th>" \ |
| "<th>" JK_STATUS_ARG_LBM_TEXT_ROUTE "</th>" \ |
| "<th>RR</th><th>Cd</th><th>Rs</th>" \ |
| "</tr>\n" |
| #define JK_STATUS_SHOW_MEMBER_ROW "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s:%d</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%d</td>" \ |
| "<td>%d</td>" \ |
| "<td>%" JK_UINT64_T_FMT "</td>" \ |
| "<td>%" JK_UINT64_T_FMT "</td>" \ |
| "<td>%" JK_UINT64_T_FMT "</td>" \ |
| "<td>%" JK_UINT32_T_FMT "</td>" \ |
| "<td>%" JK_UINT32_T_FMT "</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%d</td>" \ |
| "<td>%d</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%s</td>" \ |
| "<td>%d/%d</td>" \ |
| "</tr>\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</%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_NA: |
| mask &= JK_STATUS_MASK_NA; |
| 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 'N': |
| case 'n': |
| return JK_STATUS_MASK_NA; |
| 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; |
| } |
| |
| 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; |
| } |
| |
| 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, "<a href=\""); |
| jk_puts(s, 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, "</a>", 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, "<p>\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, "</p>\n"); |
| } |
| } |
| else { |
| if (mime == JK_STATUS_MIME_HTML) { |
| jk_printf(s, "<hr/><h3>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, "]</h3><table>\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, "</table>\n"); |
| } |
| } |
| else { |
| if (mime == JK_STATUS_MIME_HTML) { |
| jk_putv(s, "<hr/><h3>Warning: No URI Mappings defined for ", |
| worker, " !</h3>\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, "<hr/><h3>["); |
| 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, "</h3>\n", NULL); |
| jk_puts(s, "<table>" 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); |
| jk_puts(s, "</table>\n<br/>\n"); |
| |
| jk_puts(s, "<table><tr>" |
| "<th>Good</th><th>Degraded</th><th>Bad/Stopped</th><th>Busy</th><th>Max Busy</th><th>Next Maintenance</th>" |
| "</tr>\n<tr>"); |
| jk_printf(s, "<td>%d</td>", good); |
| jk_printf(s, "<td>%d</td>", degraded); |
| jk_printf(s, "<td>%d</td>", bad); |
| jk_printf(s, "<td>%d</td>", lb->s->busy); |
| jk_printf(s, "<td>%d</td>", lb->s->max_busy); |
| jk_printf(s, "<td>%d/%d</td>", ms_min, ms_max); |
| jk_puts(s, "</tr>\n</table>\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_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, " 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_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, "<h4>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, "]</h4>\n"); |
| jk_puts(s, "<table>" 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, "<tr>\n<td>"); |
| 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, " </td>"); |
| 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, |
| 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_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, " 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_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, "</table><br/>\n"); |
| if (!read_only) { |
| jk_puts(s, "<b>E</b>dit 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]<br/>\n"); |
| } |
| |
| } |
| |
| } |
| else { |
| |
| if (mime == JK_STATUS_MIME_HTML) { |
| |
| jk_puts(s, "<p>\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, "</p>\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, "<hr/><h3>["); |
| 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, "</h3>\n", NULL); |
| jk_puts(s, "<table>" 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, "</table>\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, "<hr/><h3>Edit load balancer settings for ", |
| name, "</h3>\n", NULL); |
| |
| status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); |
| |
| jk_putv(s, "<table>\n<tr><td>", JK_STATUS_ARG_LB_TEXT_RETRIES, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LB_RETRIES, "\" type=\"text\" ", NULL); |
| jk_printf(s, "value=\"%d\"/></td></tr>\n", lb->retries); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LB_TEXT_RECOVER_TIME, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LB_RECOVER_TIME, "\" type=\"text\" ", NULL); |
| jk_printf(s, "value=\"%d\"/></td></tr>\n", lb->recover_wait_time); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LB_TEXT_STICKY, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LB_STICKY, "\" type=\"checkbox\"", NULL); |
| if (lb->sticky_session) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LB_TEXT_STICKY_FORCE, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LB_STICKY_FORCE, "\" type=\"checkbox\"", NULL); |
| if (lb->sticky_session_force) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LB_TEXT_METHOD, |
| ":</td><td></td></tr>\n", NULL); |
| jk_putv(s, "<tr><td> Requests</td><td><input name=\"", |
| JK_STATUS_ARG_LB_METHOD, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_METHOD_REQUESTS); |
| if (lb->lbmethod == JK_LB_METHOD_REQUESTS) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Traffic</td><td><input name=\"", |
| JK_STATUS_ARG_LB_METHOD, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_METHOD_TRAFFIC); |
| if (lb->lbmethod == JK_LB_METHOD_TRAFFIC) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Busyness</td><td><input name=\"", |
| JK_STATUS_ARG_LB_METHOD, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_METHOD_BUSYNESS); |
| if (lb->lbmethod == JK_LB_METHOD_BUSYNESS) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Sessions</td><td><input name=\"", |
| JK_STATUS_ARG_LB_METHOD, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_METHOD_SESSIONS); |
| if (lb->lbmethod == JK_LB_METHOD_SESSIONS) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LB_TEXT_LOCK, |
| ":</td><td></td></tr>\n", NULL); |
| jk_putv(s, "<tr><td> Optimistic</td><td><input name=\"", |
| JK_STATUS_ARG_LB_LOCK, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_LOCK_OPTIMISTIC); |
| if (lb->lblock == JK_LB_LOCK_OPTIMISTIC) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Pessimistic</td><td><input name=\"", |
| JK_STATUS_ARG_LB_LOCK, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_LOCK_PESSIMISTIC); |
| if (lb->lblock == JK_LB_LOCK_PESSIMISTIC) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_puts(s, "</table>\n"); |
| jk_puts(s, "<br/><input type=\"submit\" value=\"Update Balancer\"/></form>\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, "<hr/><h3>Edit worker settings for ", |
| wr->s->name, "</h3>\n", NULL); |
| status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); |
| |
| jk_puts(s, "<table>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_ACTIVATION, |
| ":</td><td></td></tr>\n", NULL); |
| jk_putv(s, "<tr><td> Active</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_ACTIVATION, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_ACTIVE); |
| if (wr->s->activation == JK_LB_ACTIVATION_ACTIVE) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Disabled</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_ACTIVATION, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_DISABLED); |
| if (wr->s->activation == JK_LB_ACTIVATION_DISABLED) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td> Stopped</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_ACTIVATION, "\" type=\"radio\"", NULL); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_STOPPED); |
| if (wr->s->activation == JK_LB_ACTIVATION_STOPPED) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_FACTOR, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_FACTOR, "\" type=\"text\" ", NULL); |
| jk_printf(s, "value=\"%d\"/></td></tr>\n", wr->s->lb_factor); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_ROUTE, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_ROUTE, "\" type=\"text\" ", NULL); |
| jk_printf(s, "value=\"%s\"/></td></tr>\n", wr->s->route); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_REDIRECT, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_REDIRECT, "\" type=\"text\" ", NULL); |
| jk_putv(s, "value=\"", wr->s->redirect, NULL); |
| jk_puts(s, "\"/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_DOMAIN, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_DOMAIN, "\" type=\"text\" ", NULL); |
| jk_putv(s, "value=\"", wr->s->domain, NULL); |
| jk_puts(s, "\"/></td></tr>\n"); |
| jk_putv(s, "<tr><td>", JK_STATUS_ARG_LBM_TEXT_DISTANCE, |
| ":</td><td><input name=\"", |
| JK_STATUS_ARG_LBM_DISTANCE, "\" type=\"text\" ", NULL); |
| jk_printf(s, "value=\"%d\"/></td></tr>\n", wr->s->distance); |
| jk_puts(s, "</table>\n"); |
| jk_puts(s, "<br/><input type=\"submit\" value=\"Update Worker\"/>\n</form>\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, "<hr/><h3>Edit attribute '", aname, |
| "' for all members of load balancer ", |
| name, "</h3>\n", NULL); |
| |
| status_start_form(s, p, "GET", JK_STATUS_CMD_UPDATE, l); |
| |
| jk_putv(s, "<table><tr>" |
| "<th>Balanced Worker</th><th>", aname, "</th>" |
| "</tr>", NULL); |
| |
| for (i = 0; i < lb->num_of_workers; i++) { |
| worker_record_t *wr = &(lb->lb_workers[i]); |
| |
| jk_putv(s, "<tr><td>", wr->s->name, "</td><td>\n", NULL); |
| |
| if (!strcmp(attribute, JK_STATUS_ARG_LBM_ACTIVATION)) { |
| |
| jk_printf(s, "Active: <input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"radio\"", i); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_ACTIVE); |
| if (wr->s->activation == JK_LB_ACTIVATION_ACTIVE) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/> | \n"); |
| jk_printf(s, "Disabled: <input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"radio\"", i); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_DISABLED); |
| if (wr->s->activation == JK_LB_ACTIVATION_DISABLED) |
| jk_puts(s, " checked=\"checked\""); |
| jk_puts(s, "/> | \n"); |
| jk_printf(s, "Stopped: <input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"radio\"", i); |
| jk_printf(s, " value=\"%d\"", JK_LB_ACTIVATION_STOPPED); |
| if (wr->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, "<input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"text\"", i); |
| jk_printf(s, "value=\"%d\"/>\n", wr->s->lb_factor); |
| } |
| else if (!strcmp(attribute, JK_STATUS_ARG_LBM_ROUTE)) { |
| jk_printf(s, "<input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"text\"", i); |
| jk_putv(s, "value=\"", wr->s->route, "\"/>\n", NULL); |
| } |
| else if (!strcmp(attribute, JK_STATUS_ARG_LBM_REDIRECT)) { |
| jk_printf(s, "<input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"text\"", i); |
| jk_putv(s, "value=\"", wr->s->redirect, "\"/>\n", NULL); |
| } |
| else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DOMAIN)) { |
| jk_printf(s, "<input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"text\"", i); |
| jk_putv(s, "value=\"", wr->s->domain, "\"/>\n", NULL); |
| } |
| else if (!strcmp(attribute, JK_STATUS_ARG_LBM_DISTANCE)) { |
| jk_printf(s, "<input name=\"" JK_STATUS_ARG_MULT_VALUE_BASE "%d\" type=\"text\"", i); |
| jk_printf(s, "value=\"%d\"/>\n", wr->s->distance); |
| } |
| |
| jk_puts(s, "</td></tr>"); |
| } |
| |
| jk_puts(s, "</table>\n"); |
| jk_puts(s, "<br/><input type=\"submit\" value=\"Update Balancer\"/></form>\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_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, "<p>\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, "</p>\n"); |
| } |
| else { |
| jk_puts(s, "<h2>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, "]</h2>\n"); |
| |
| jk_puts(s, "<table>\n" |
| "<tbody valign=\"baseline\">\n" |
| "<tr><th>Name</th><td>Worker name</td></tr>\n" |
| "<tr><th>Type</th><td>Worker type</td></tr>\n" |
| "<tr><th>Route</th><td>Worker route</td></tr>\n" |
| "<tr><th>Addr</th><td>Backend Address info</td></tr>\n" |
| "<tr><th>Act</th><td>Worker activation configuration<br/>\n" |
| "ACT=Active, DIS=Disabled, STP=Stopped</td></tr>\n" |
| "<tr><th>Stat</th><td>Worker error status<br/>\n" |
| "OK=OK, N/A=Unknown, ERR=Error, BSY=Busy<br/>\n" |
| "REC=Recovering, PRB=Probing, FRC=Forced Recovery</td></tr>\n" |
| "<tr><th>D</th><td>Worker distance</td></tr>\n" |
| "<tr><th>F</th><td>Load Balancer factor</td></tr>\n" |
| "<tr><th>M</th><td>Load Balancer multiplicity</td></tr>\n" |
| "<tr><th>V</th><td>Load Balancer value</td></tr>\n" |
| "<tr><th>Acc</th><td>Number of requests</td></tr>\n" |
| "<tr><th>Err</th><td>Number of failed requests</td></tr>\n" |
| "<tr><th>CE</th><td>Number of client errors</td></tr>\n" |
| "<tr><th>Wr</th><td>Number of bytes transferred/min</td></tr>\n" |
| "<tr><th>Rd</th><td>Number of bytes read/min</td></tr>\n" |
| "<tr><th>Busy</th><td>Current number of busy connections</td></tr>\n" |
| "<tr><th>Max</th><td>Maximum number of busy connections</td></tr>\n" |
| "<tr><th>RR</th><td>Route redirect</td></tr>\n" |
| "<tr><th>Cd</th><td>Cluster domain</td></tr>\n" |
| "<tr><th>Rs</th><td>Recovery scheduled in app. min/max seconds</td></tr>\n" |
| "</tbody>\n" |
| "</table>\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, "<p>\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, "</p>\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, "<hr/><h2>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, "]</h2>\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, "<p>\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, "</p>\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, "<hr/><h2>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, "]</h2>\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->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_NA; |
| } |
| 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->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_NA; |
| 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) { |
| 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 (is_error) |
| *is_error = JK_FALSE; |
| if (!e || !e->endpoint_private || !s || !is_error) { |
| JK_LOG_NULL_PARAMS(l); |
| JK_TRACE_EXIT(l); |
| return JK_FALSE; |
| } |
| |
| p = e->endpoint_private; |
| w = p->worker; |
| |
| 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<meta http-equiv=\"Refresh\" content=\"" |
| JK_STATUS_WAIT_AFTER_UPDATE ";url="); |
| status_write_uri(s, p, NULL, JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, |
| NULL, NULL, 0, 0, NULL, l); |
| jk_puts(s, "\">"); |
| if (!err) { |
| jk_putv(s, "<p><b>Result: OK - You will be redirected in " |
| JK_STATUS_WAIT_AFTER_UPDATE " seconds.</b><p/>", 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<meta http-equiv=\"Refresh\" content=\"" |
| JK_STATUS_WAIT_AFTER_UPDATE ";url="); |
| status_write_uri(s, p, NULL, JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, |
| NULL, NULL, 0, 0, NULL, l); |
| jk_puts(s, "\">"); |
| if (!err) { |
| jk_putv(s, "<p><b>Result: OK - You will be redirected in " |
| JK_STATUS_WAIT_AFTER_UPDATE " seconds.</b><p/>", 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<meta http-equiv=\"Refresh\" content=\"" |
| JK_STATUS_WAIT_AFTER_UPDATE ";url="); |
| status_write_uri(s, p, NULL, JK_STATUS_CMD_UNKNOWN, JK_STATUS_MIME_UNKNOWN, |
| NULL, NULL, 0, 0, NULL, l); |
| jk_puts(s, "\">"); |
| if (!err) { |
| jk_putv(s, "<p><b>Result: OK - You will be redirected in " |
| JK_STATUS_WAIT_AFTER_UPDATE " seconds.</b><p/>", 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<meta http-equiv=\"Refresh\" content=\"%d;url=%s?%s\">", |
| refresh, s->req_uri, s->query_string); |
| } |
| if (w->css) { |
| jk_putv(s, "\n<link rel=\"stylesheet\" type=\"text/css\" href=\"", |
| w->css, "\" />\n", NULL); |
| } |
| jk_puts(s, JK_STATUS_HEND); |
| jk_puts(s, "<h1>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, "</h1>\n\n"); |
| if ((cmd == JK_STATUS_CMD_LIST) || |
| (cmd == JK_STATUS_CMD_SHOW) || |
| (cmd == JK_STATUS_CMD_VERSION)) { |
| jk_putv(s, "<table><tr><td>Server Version:</td><td>", |
| s->server_software, "</td></tr>\n", NULL); |
| jk_putv(s, "<tr><td>JK Version:</td><td>", |
| JK_EXPOSED_VERSION, "</td></tr></table>\n", NULL); |
| jk_puts(s, "<hr/>\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, "[<a href=\"", s->req_uri, NULL); |
| if (buf && buf[0]) |
| jk_putv(s, "?", buf, NULL); |
| jk_puts(s, "\">Stop auto refresh</a>] "); |
| } |
| else { |
| status_start_form(s, p, "GET", JK_STATUS_CMD_UNKNOWN, l); |
| jk_puts(s, "<input type=\"submit\" value=\"Start auto refresh\"/>\n"); |
| jk_putv(s, "(every ", |
| "<input name=\"", JK_STATUS_ARG_REFRESH, |
| "\" type=\"text\" size=\"3\" value=\"", |
| JK_STATUS_REFRESH_DEF "\"/> ", |
| "seconds)", NULL); |
| jk_puts(s, "</form>\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, "<b>S</b>=Show only this worker"); |
| if (!read_only && cmd == JK_STATUS_CMD_LIST) |
| jk_puts(s, ", "); |
| if (!read_only) |
| jk_puts(s, "<b>E</b>=Edit worker, <b>R</b>=Reset worker state, <b>T</b>=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, "<p><b>Result: ERROR - ", err, "</b><br/>", NULL); |
| jk_putv(s, "<a href=\"", s->req_uri, "\">JK Status Manager Start Page</a></p>", 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, "<p><a href=\"", s->req_uri, "\">JK Status Manager Start Page</a></p>", 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, "<hr/><div class=\"footer\">", JK_STATUS_COPYRIGHT, |
| "</div>\n", NULL); |
| } |
| else { |
| jk_putv(s, "<hr/><p align=\"center\"><small>", JK_STATUS_COPYRIGHT, |
| "</small></p>\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; |
| } |