📄 jk_util.c
字号:
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/***************************************************************************
* Description: Utility functions (mainly configuration) *
* Author: Gal Shachor <shachor@il.ibm.com> *
* Author: Henri Gomez <hgomez@apache.org> *
* Version: $Revision: 386592 $ *
***************************************************************************/
#include "jk_util.h"
#include "jk_ajp12_worker.h"
#include "jk_ajp13_worker.h"
#include "jk_ajp14_worker.h"
#include "jk_lb_worker.h"
#include "jk_mt.h"
#define SYSPROPS_OF_WORKER ("sysprops")
#define STDERR_OF_WORKER ("stderr")
#define STDOUT_OF_WORKER ("stdout")
#define SECRET_OF_WORKER ("secret")
#define CONF_OF_WORKER ("conf")
#define MX_OF_WORKER ("mx")
#define MS_OF_WORKER ("ms")
#define CP_OF_WORKER ("class_path")
#define BRIDGE_OF_WORKER ("bridge")
#define JVM_OF_WORKER ("jvm_lib")
#define LIBPATH_OF_WORKER ("ld_path")
#define CMD_LINE_OF_WORKER ("cmd_line")
#define NATIVE_LIB_OF_WORKER ("native_lib")
#define HOST_OF_WORKER ("host")
#define PORT_OF_WORKER ("port")
#define TYPE_OF_WORKER ("type")
#define CACHE_OF_WORKER_DEPRECATED ("cachesize")
#define CACHE_OF_WORKER ("connection_pool_size")
#define CACHE_TIMEOUT_OF_WORKER ("cache_timeout")
#define RECOVERY_OPTS_OF_WORKER ("recovery_options")
#define CONNECT_TIMEOUT_OF_WORKER ("connect_timeout")
#define PREPOST_TIMEOUT_OF_WORKER ("prepost_timeout")
#define REPLY_TIMEOUT_OF_WORKER ("reply_timeout")
#define SOCKET_TIMEOUT_OF_WORKER ("socket_timeout")
#define SOCKET_BUFFER_OF_WORKER ("socket_buffer")
#define SOCKET_KEEPALIVE_OF_WORKER ("socket_keepalive")
#define RECYCLE_TIMEOUT_OF_WORKER ("recycle_timeout")
#define LOAD_FACTOR_OF_WORKER ("lbfactor")
/* deprecated directive. Use balance_workers instead */
#define BALANCED_WORKERS ("balanced_workers")
#define BALANCE_WORKERS ("balance_workers")
#define STICKY_SESSION ("sticky_session")
#define STICKY_SESSION_FORCE ("sticky_session_force")
#define DOMAIN_OF_WORKER ("domain")
#define REDIRECT_OF_WORKER ("redirect")
#define MOUNT_OF_WORKER ("mount")
#define METHOD_OF_WORKER ("method")
#define LOCK_OF_WORKER ("lock")
#define IS_WORKER_DISABLED ("disabled")
#define IS_WORKER_STOPPED ("stopped")
#define WORKER_RECOVER_TIME ("recover_time")
#define DEFAULT_WORKER_TYPE JK_AJP13_WORKER_NAME
#define SECRET_KEY_OF_WORKER ("secretkey")
#define RETRIES_OF_WORKER ("retries")
#define DEFAULT_WORKER JK_AJP13_WORKER_NAME
#define WORKER_LIST_PROPERTY_NAME ("worker.list")
#define WORKER_MAINTAIN_PROPERTY_NAME ("worker.maintain")
#define DEFAULT_MAINTAIN_TIME (60)
#define DEFAULT_LB_FACTOR (1)
#define LOG_FORMAT ("log_format")
#define TOMCAT32_BRIDGE_NAME ("tomcat32")
#define TOMCAT33_BRIDGE_NAME ("tomcat33")
#define TOMCAT40_BRIDGE_NAME ("tomcat40")
#define TOMCAT41_BRIDGE_NAME ("tomcat41")
#define TOMCAT50_BRIDGE_NAME ("tomcat5")
#define HUGE_BUFFER_SIZE (8*1024)
#define LOG_LINE_SIZE (1024)
#define MAKE_WORKER_PARAM(P) \
strcpy(buf, "worker."); \
strcat(buf, wname); \
strcat(buf, "."); \
strcat(buf, P)
/*
* define the log format, we're using by default the one from error.log
*
* [Mon Mar 26 19:44:48 2001] [jk_uri_worker_map.c (155)]: Into jk_uri_worker_map_t::uri_worker_map_alloc
* log format used by apache in error.log
*/
#ifndef JK_TIME_FORMAT
#define JK_TIME_FORMAT "[%a %b %d %H:%M:%S %Y] "
#endif
/* Visual C++ Toolkit 2003 support */
#if defined (_MSC_VER) && (_MSC_VER == 1310)
extern long _ftol(double); /* defined by VC6 C libs */
extern long _ftol2(double dblSource) { return _ftol(dblSource); }
#endif
static const char *jk_level_werbs[] = {
"[" JK_LOG_TRACE_VERB "] ",
"[" JK_LOG_DEBUG_VERB "] ",
"[" JK_LOG_INFO_VERB "] ",
"[" JK_LOG_WARNING_VERB "] ",
"[" JK_LOG_ERROR_VERB "] ",
"[" JK_LOG_EMERG_VERB "] ",
NULL
};
const char *jk_log_fmt = JK_TIME_FORMAT;
static void set_time_str(char *str, int len)
{
time_t t = time(NULL);
struct tm *tms;
tms = localtime(&t);
strftime(str, len, jk_log_fmt, tms);
}
/* Write at most n characters to the buffer in str, return the
* number of chars written or -1 if the buffer would have been
* overflowed.
*
* This is portable to any POSIX-compliant system that has /dev/null
*/
#if !defined(HAVE_VSNPRINTF) && !defined(HAVE_APR)
static FILE *f = NULL;
static int vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{
int res;
if (f == NULL)
f = fopen("/dev/null", "w");
if (f == NULL)
return -1;
setvbuf(f, str, _IOFBF, n);
res = vfprintf(f, fmt, ap);
if (res > 0 && res < n) {
res = vsprintf(str, fmt, ap);
}
return res;
}
#endif
#if !defined(HAVE_SNPRINTF) && !defined(HAVE_APR)
static int snprintf(char *str, size_t n, const char *fmt, ...)
{
va_list ap;
int res;
va_start(ap, fmt);
res = vsnprintf(str, n, fmt, ap);
va_end(ap);
return res;
}
#endif
static int JK_METHOD log_to_file(jk_logger_t *l, int level, const char *what)
{
if (l &&
(l->level <= level || level == JK_LOG_REQUEST_LEVEL) &&
l->logger_private && what) {
size_t sz = strlen(what);
if (sz) {
file_logger_t *p = l->logger_private;
fwrite(what, 1, sz, p->logfile);
fputc('\n', p->logfile);
/* [V] Flush the dam' thing! */
if (l->level < JK_LOG_INFO_LEVEL)
fflush(p->logfile);
}
return JK_TRUE;
}
return JK_FALSE;
}
int jk_parse_log_level(const char *level)
{
if (0 == strcasecmp(level, JK_LOG_TRACE_VERB)) {
return JK_LOG_TRACE_LEVEL;
}
if (0 == strcasecmp(level, JK_LOG_DEBUG_VERB)) {
return JK_LOG_DEBUG_LEVEL;
}
if (0 == strcasecmp(level, JK_LOG_INFO_VERB)) {
return JK_LOG_INFO_LEVEL;
}
if (0 == strcasecmp(level, JK_LOG_WARNING_VERB)) {
return JK_LOG_WARNING_LEVEL;
}
if (0 == strcasecmp(level, JK_LOG_ERROR_VERB)) {
return JK_LOG_ERROR_LEVEL;
}
if (0 == strcasecmp(level, JK_LOG_EMERG_VERB)) {
return JK_LOG_EMERG_LEVEL;
}
return JK_LOG_INFO_LEVEL;
}
int jk_open_file_logger(jk_logger_t **l, const char *file, int level)
{
if (l && file) {
jk_logger_t *rc = (jk_logger_t *)malloc(sizeof(jk_logger_t));
file_logger_t *p = (file_logger_t *) malloc(sizeof(file_logger_t));
if (rc && p) {
rc->log = log_to_file;
rc->level = level;
rc->logger_private = p;
#ifdef AS400
p->logfile = fopen(file, "a+, o_ccsid=0");
#else
p->logfile = fopen(file, "a+");
#endif
if (p->logfile) {
*l = rc;
return JK_TRUE;
}
}
if (rc) {
free(rc);
}
if (p) {
free(p);
}
*l = NULL;
}
return JK_FALSE;
}
int jk_close_file_logger(jk_logger_t **l)
{
if (l && *l) {
file_logger_t *p = (*l)->logger_private;
if (p) {
fflush(p->logfile);
fclose(p->logfile);
free(p);
}
free(*l);
*l = NULL;
return JK_TRUE;
}
return JK_FALSE;
}
int jk_log(jk_logger_t *l,
const char *file, int line, const char *funcname, int level,
const char *fmt, ...)
{
int rc = 0;
if (!l || !file || !fmt) {
return -1;
}
if ((l->level <= level) || (level == JK_LOG_REQUEST_LEVEL)) {
#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
char *f = (char *)(file + strlen(file) - 1);
va_list args;
size_t used = 0;
while (f != file && '\\' != *f && '/' != *f) {
f--;
}
if (f != file) {
f++;
}
#ifdef NETWARE
buf = (char *)malloc(HUGE_BUFFER_SIZE);
if (NULL == buf)
return -1;
#endif
set_time_str(buf, HUGE_BUFFER_SIZE);
used = strlen(buf);
/* Log [pid:threadid] for debug and trace levels */
if (l->level < JK_LOG_INFO_LEVEL) {
#ifdef USE_SPRINTF /* until we get a snprintf function */
used += sprintf(&buf[used], "[%04d:%04d] ", getpid(),
jk_gettid());
#else
used += snprintf(&buf[used], HUGE_BUFFER_SIZE - used,
"[%04d:%04d] ", getpid(), jk_gettid());
#endif
if (used < 0) {
return 0;
}
}
if (line) {
strcat(buf, jk_level_werbs[level]);
used += 8;
if (funcname) {
strcat(buf, funcname);
strcat(buf, "::");
used += strlen(funcname) + 2;
}
}
#ifdef USE_SPRINTF /* until we get a snprintf function */
if (line)
used += sprintf(&buf[used], "%s (%d): ", f, line);
#else
if (line)
used += snprintf(&buf[used], HUGE_BUFFER_SIZE - used,
"%s (%d): ", f, line);
#endif
if (used < 0) {
return 0; /* [V] not sure what to return... */
}
va_start(args, fmt);
#ifdef USE_VSPRINTF /* until we get a vsnprintf function */
rc = vsprintf(buf + used, fmt, args);
#else
rc = vsnprintf(buf + used, HUGE_BUFFER_SIZE - used, fmt, args);
#endif
va_end(args);
l->log(l, level, buf);
#ifdef NETWARE
free(buf);
#endif
}
return rc;
}
const char *jk_get_worker_type(jk_map_t *m, const char *wname)
{
char buf[1024];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(TYPE_OF_WORKER);
return jk_map_get_string(m, buf, DEFAULT_WORKER_TYPE);
}
const char *jk_get_worker_domain(jk_map_t *m, const char *wname, const char *def)
{
char buf[1024];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(DOMAIN_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_redirect(jk_map_t *m, const char *wname, const char *def)
{
char buf[1024];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(REDIRECT_OF_WORKER);
return jk_map_get_string(m, buf, def);
}
const char *jk_get_worker_secret(jk_map_t *m, const char *wname)
{
char buf[1024];
if (!m || !wname) {
return NULL;
}
MAKE_WORKER_PARAM(SECRET_OF_WORKER);
return jk_map_get_string(m, buf, NULL);
}
/* [V] I suggest that the following general purpose functions be used. */
/* More should be added (double etc.), but now these were enough for me. */
/* Functions that can be simulated with these should be "deprecated". */
int jk_get_worker_str_prop(jk_map_t *m,
const char *wname, const char *pname, const char **prop)
{
char buf[1024];
if (m && prop && wname && pname) {
MAKE_WORKER_PARAM(pname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -