blob: 7f28d77b9b65b1c4a695de29071c900d185212f3 [file] [log] [blame]
/*
* 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: Workers controller *
* Author: Gal Shachor <shachor@il.ibm.com> *
* Author: Henri Gomez <hgomez@apache.org> *
* Version: $Revision$ *
***************************************************************************/
#include "jk_env.h"
#include "jk_workerEnv.h"
#include "jk_config.h"
#include "jk_worker.h"
#include "jk_shm.h"
#include "jk_channel.h"
#include "jk_registry.h"
#define DEFAULT_WORKER ("lb")
static void jk2_workerEnv_close(jk_env_t *env, jk_workerEnv_t *wEnv);
static void jk2_workerEnv_initHandlers(jk_env_t *env, jk_workerEnv_t *wEnv);
static int jk2_workerEnv_init1(jk_env_t *env, jk_workerEnv_t *wEnv);
/* ==================== Setup ==================== */
static int JK_METHOD jk2_workerEnv_setAttribute(struct jk_env *env,
struct jk_bean *mbean,
char *name, void *valueP)
{
jk_workerEnv_t *wEnv = mbean->object;
char *value = valueP;
/** XXX Should it be per/uri ?
*/
if (strcmp(name, "logger") == 0) {
wEnv->logger_name = value;
}
else if (strcmp(name, "sslEnable") == 0) {
wEnv->ssl_enable = JK_TRUE;
}
else if (strcmp(name, "timing") == 0) {
wEnv->timing = atoi(value);
}
else if (strcmp(name, "httpsIndicator") == 0) {
wEnv->https_indicator = value;
}
else if (strcmp(name, "certsIndicator") == 0) {
wEnv->certs_indicator = value;
}
else if (strcmp(name, "cipherIndicator") == 0) {
wEnv->cipher_indicator = value;
}
else if (strcmp(name, "sessionIndicator") == 0) {
wEnv->session_indicator = value;
}
else if (strcmp(name, "keySizeIndicator") == 0) {
wEnv->key_size_indicator = value;
}
else if (strcmp(name, "forwardKeySize") == 0) {
wEnv->options |= JK_OPT_FWDKEYSIZE;
/* Small change in how we treat options: we have a default,
and assume that any option declared by user has the intention
of overriding the default ( "-Option == no option, leave the
default
*/
}
else if (strcmp(name, "forwardURICompat") == 0) {
wEnv->options &= ~JK_OPT_FWDURIMASK;
wEnv->options |= JK_OPT_FWDURICOMPAT;
}
else if (strcmp(name, "forwardURICompatUnparsed") == 0) {
wEnv->options &= ~JK_OPT_FWDURIMASK;
wEnv->options |= JK_OPT_FWDURICOMPATUNPARSED;
}
else if (strcmp(name, "forwardURIEscaped") == 0) {
wEnv->options &= ~JK_OPT_FWDURIMASK;
wEnv->options |= JK_OPT_FWDURIESCAPED;
}
else if (strcmp(name, "noRecoveryIfRequestSent") == 0) {
wEnv->options &= ~JK_OPT_RECOSTRATEGYMASK;
wEnv->options |= JK_OPT_RECO_ABORTIFTCGETREQUEST;
}
else if (strcmp(name, "noRecoveryIfHeaderSent") == 0) {
wEnv->options &= ~JK_OPT_RECOSTRATEGYMASK;
wEnv->options |= JK_OPT_RECO_ABORTIFTCSENDHEADER;
}
else {
return JK_ERR;
}
return JK_OK;
}
static void jk2_workerEnv_close(jk_env_t *env, jk_workerEnv_t *wEnv)
{
int sz;
int i;
sz = wEnv->worker_map->size(env, wEnv->worker_map);
for (i = 0; i < sz; i++) {
jk_worker_t *w = wEnv->worker_map->valueAt(env, wEnv->worker_map, i);
if (w) {
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"destroy worker %s\n",
wEnv->worker_map->nameAt(env, wEnv->worker_map, i));
if (w->mbean->destroy != NULL)
w->mbean->destroy(env, w->mbean);
}
}
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"workerEnv.close() done %d\n", sz);
wEnv->worker_map->clear(env, wEnv->worker_map);
}
static void jk2_workerEnv_checkSpace(jk_env_t *env, jk_pool_t *pool,
void ***tableP, int *sizeP, int id)
{
void **newTable;
int i;
int newSize = id + 4;
if (*sizeP > id)
return;
/* resize the table */
newTable = (void **)pool->calloc(env, pool, newSize * sizeof(void *));
for (i = 0; i < *sizeP; i++) {
newTable[i] = (*tableP)[i];
}
*tableP = newTable;
*sizeP = newSize;
}
static int jk2_workerEnv_initWorker(jk_env_t *env,
jk_workerEnv_t *wEnv, jk_worker_t *w)
{
int rc;
if ((w == NULL) || (w->mbean == NULL))
return JK_ERR;
if (w->mbean->disabled)
return JK_OK;
w->workerEnv = wEnv;
if (w->mbean->state >= JK_STATE_INIT)
return JK_OK;
if (w->mbean->init == NULL)
return JK_OK;
rc = w->mbean->init(env, w->mbean);
if (rc == JK_OK) {
w->mbean->state = JK_STATE_INIT;
}
else {
w->mbean->state = JK_STATE_DISABLED;
w->mbean->disabled = JK_TRUE;
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.initWorkers() init failed for %s\n",
w->mbean->name);
}
return JK_OK;
}
static int jk2_workerEnv_initWorkers(jk_env_t *env, jk_workerEnv_t *wEnv)
{
int i;
for (i = 0; i < wEnv->worker_map->size(env, wEnv->worker_map); i++) {
jk_worker_t *w = wEnv->worker_map->valueAt(env, wEnv->worker_map, i);
jk2_workerEnv_initWorker(env, wEnv, w);
}
return JK_OK;
}
static int jk2_workerEnv_initChannel(jk_env_t *env,
jk_workerEnv_t *wEnv, jk_channel_t *ch)
{
int rc = JK_OK;
ch->workerEnv = wEnv;
if (ch->mbean->disabled)
return JK_OK;
if (ch->mbean->init != NULL) {
rc = ch->mbean->init(env, ch->mbean);
if (rc != JK_OK) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.initChannel() init failed for %s\n",
ch->mbean->name);
/* Disable the associated worker */
ch->worker->channel = NULL;
ch->worker->channelName = NULL;
}
jk2_workerEnv_initWorker(env, wEnv, ch->worker);
}
return rc;
}
static int jk2_workerEnv_initChannels(jk_env_t *env, jk_workerEnv_t *wEnv)
{
int i;
for (i = 0; i < wEnv->channel_map->size(env, wEnv->channel_map); i++) {
jk_channel_t *ch =
wEnv->channel_map->valueAt(env, wEnv->channel_map, i);
jk2_workerEnv_initChannel(env, wEnv, ch);
}
return JK_OK;
}
static void jk2_workerEnv_initHandlers(jk_env_t *env, jk_workerEnv_t *wEnv)
{
/* Find the max message id */
/* XXX accessing private data... env most provide some method to get this */
jk_map_t *registry = env->_registry;
int size = registry->size(env, registry);
int i;
for (i = 0; i < size; i++) {
jk_handler_t *handler;
char *name = registry->nameAt(env, registry, i);
if (strncmp(name, "handler.", 8) == 0) {
jk_bean_t *jkb = env->createBean2(env, wEnv->pool, name, "");
if (jkb == NULL || jkb->object == NULL)
continue;
handler = (jk_handler_t *) jkb->object;
handler->init(env, handler, wEnv);
}
}
}
static int jk2_workerEnv_registerHandler(jk_env_t *env, jk_workerEnv_t *wEnv,
const char *type,
const char *name, int preferedId,
jk_handler_callback callback,
char *signature)
{
jk_handler_t *h =
(jk_handler_t *) wEnv->pool->calloc(env, wEnv->pool,
sizeof(jk_handler_t));
h->name = (char *)name;
h->messageId = preferedId;
h->callback = callback;
h->workerEnv = wEnv;
jk2_workerEnv_checkSpace(env, wEnv->pool,
(void ***)&wEnv->handlerTable,
&wEnv->lastMessageId, h->messageId);
wEnv->handlerTable[h->messageId] = h;
/*wEnv->l->jkLog( wEnv->l, JK_LOG_INFO, "Registered %s %d\n", */
/* handler->name, handler->messageId); */
return JK_OK;
}
/** Called from the parent, in a multi-process server.
*/
static int jk2_workerEnv_parentInit(jk_env_t *env, jk_workerEnv_t *wEnv)
{
char *configFile;
env->l->init(env, env->l);
configFile = wEnv->config->file;
if (configFile == NULL) {
wEnv->config->setPropertyString(env, wEnv->config,
"config.file",
JK_WORKER_FILE_DEF);
configFile = wEnv->config->file;
}
if (wEnv->shm != NULL && wEnv->shm->mbean->disabled)
wEnv->shm = NULL;
if (wEnv->shm != NULL) {
/* Disable the shm if the initialization fails
*/
if (wEnv->shm->init(env, wEnv->shm) == JK_ERR)
wEnv->shm = NULL;
}
if (wEnv->shm != NULL && wEnv->shm->head != NULL) {
wEnv->shm->reset(env, wEnv->shm);
if (wEnv->mbean->debug > 0)
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"workerEnv.init() Reset shm\n");
}
return JK_OK;
}
/** Normal child init
*/
static int jk2_workerEnv_init(jk_env_t *env, jk_workerEnv_t *wEnv)
{
char *configFile;
jk_bean_t *jkb;
/* We need to pid here - Linux will return the pid of the thread if
called after init(), and we'll not be able to locate the slot id
This is part of the workarounds needed for Apache2's removal of
child_num from connection.
*/
wEnv->childProcessId = getpid();
configFile = wEnv->config->file;
if (configFile == NULL) {
wEnv->config->setPropertyString(env, wEnv->config,
"config.file",
JK_WORKER_FILE_DEF);
configFile = wEnv->config->file;
}
jkb = env->createBean2(env, wEnv->mbean->pool, "threadMutex", NULL);
if (jkb != NULL) {
wEnv->cs = jkb->object;
jkb->init(env, jkb);
}
if (wEnv->logger_name != NULL) {
jkb = env->getBean(env, wEnv->logger_name);
if (jkb == NULL) {
jkb = env->createBean(env, env->globalPool, wEnv->logger_name);
}
env->alias(env, wEnv->logger_name, "logger");
env->l = jkb->object;
}
env->l->init(env, env->l);
/* Set default worker. It'll be used for all uris that have no worker
*/
if (wEnv->defaultWorker == NULL) {
jk_worker_t *w =
wEnv->worker_map->get(env, wEnv->worker_map, "lb:lb");
if (w == NULL) {
jk_bean_t *jkb = env->createBean2(env, wEnv->pool, "lb", "lb");
w = jkb->object;
if (wEnv->mbean->debug > 0)
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"workerEnv.init() create default worker %s\n",
jkb->name);
}
wEnv->defaultWorker = w;
}
if (wEnv->vm != NULL && !wEnv->vm->mbean->disabled) {
wEnv->vm->init(env, wEnv->vm);
}
jk2_workerEnv_initChannels(env, wEnv);
jk2_workerEnv_initWorkers(env, wEnv);
jk2_workerEnv_initHandlers(env, wEnv);
if (wEnv->shm != NULL && wEnv->shm->mbean->disabled)
wEnv->shm = NULL;
if (wEnv->shm != NULL) {
/* Disable the shm if the initialization fails
*/
if (wEnv->shm->init(env, wEnv->shm) == JK_ERR)
wEnv->shm = NULL;
}
wEnv->epStat = NULL;
wEnv->uriMap->init(env, wEnv->uriMap);
env->l->jkLog(env, env->l, JK_LOG_INFO, "workerEnv.init() ok %s\n",
configFile);
return JK_OK;
}
static int jk2_workerEnv_dispatch(jk_env_t *env, jk_workerEnv_t *wEnv,
void *target, jk_endpoint_t *e, int code,
jk_msg_t *msg)
{
jk_handler_t *handler;
int rc;
jk_handler_t **handlerTable = wEnv->handlerTable;
int maxHandler = wEnv->lastMessageId;
rc = -1;
handler = NULL;
if (code < maxHandler) {
handler = handlerTable[code];
}
if (handler == NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.dispatch() Invalid code: %d\n", code);
e->reply->dump(env, e->reply, "Message: ");
return JK_ERR;
}
if (wEnv->mbean->debug > 0)
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"workerEnv.dispatch() Calling %d %s\n",
handler->messageId, handler->name);
/* Call the message handler */
rc = handler->callback(env, target, e, msg);
return rc;
}
/* XXX This should go to channel ( or a base class for socket channels ) */
/*
* Process incoming messages.
*
* We will know only at read time if the remote host closed
* the connection (half-closed state - FIN-WAIT2). In that case
* we must close our side of the socket and abort emission.
* We will need another connection to send the request
* There is need of refactoring here since we mix
* reply reception (tomcat -> apache) and request send (apache -> tomcat)
* and everything using the same buffer (repmsg)
* ajp13/ajp14 is async but handling read/send this way prevent nice recovery
* In fact if tomcat link is broken during upload (browser ->apache ->tomcat)
* we'll loose data and we'll have to abort the whole request.
*/
static int jk2_workerEnv_processCallbacks(jk_env_t *env, jk_workerEnv_t *wEnv,
jk_endpoint_t *ep,
jk_ws_service_t *req)
{
int code;
jk_handler_t *handler;
int rc;
ep->currentRequest = req;
/* Process reply - this is the main loop */
/* Start read all reply message */
while (1) {
jk_msg_t *msg = ep->reply;
rc = -1;
handler = NULL;
if (ep->worker->mbean->debug > 0)
env->l->jkLog(env, env->l, JK_LOG_DEBUG,
"workerEnv.callbacks() %s\n",
ep->worker->channel->mbean->name);
msg->reset(env, msg);
/* Check for reply in timeout */
if (ep->worker->reply_timeout != 0) {
if (ep->worker->channel->
hasinput(env, ep->worker->channel, ep,
ep->worker->reply_timeout) != JK_TRUE) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() no reply after %d ms waiting\n",
ep->worker->reply_timeout);
/* Error is unrecoverable if tomcat failed (Tomcat allready got request) */
if (wEnv->options & JK_OPT_RECO_ABORTIFTCGETREQUEST)
req->is_recoverable_error = JK_FALSE;
return JK_ERR;
}
}
rc = ep->worker->channel->recv(env, ep->worker->channel, ep, msg);
if (rc != JK_OK) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() Error reading reply\n");
/* Error is unrecoverable if tomcat failed (Tomcat allready got request) */
if (wEnv->options & JK_OPT_RECO_ABORTIFTCGETREQUEST) {
req->is_recoverable_error = JK_FALSE;
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() by configuration, avoid recovery when tomcat has received request\n");
}
return rc;
}
/** After I received the first message ( head most likely ), it
is impossible to recover */
ep->recoverable = JK_FALSE;
if (ep->worker->mbean->debug > 10)
ep->request->dump(env, msg, "Received");
/* XXX Use this _only_ for backward compatibility.
invoke() and jk_bean should be used, probably with a first parameter
indicating the target component and a second param indicating the
code ( local to each component ).
*/
code = (int)msg->getByte(env, msg);
rc = jk2_workerEnv_dispatch(env, wEnv, req, ep, code, msg);
/* Process the status code returned by handler */
switch (rc) {
case JK_HANDLER_LAST:
/* no more data to be sent, fine we have finish here */
return JK_OK;
case JK_HANDLER_OK:
/* One-time request, continue to listen */
break;
case JK_HANDLER_RESPONSE:
/*
* in upload-mode there is no second chance since
* we may have allready send part of uploaded data
* to Tomcat.
* In this case if Tomcat connection is broken we must
* abort request and indicate error.
* A possible work-around could be to store the uploaded
* data to file and replay for it
*/
req->is_recoverable_error = JK_FALSE;
if (ep->worker->mbean->debug > 10)
msg->dump(env, msg, "Apache->tomcat");
rc = ep->worker->channel->send(env, ep->worker->channel, ep, msg);
if (rc < 0) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() error sending response data\n");
ep->recoverable = JK_FALSE;
return rc;
}
break;
case JK_HANDLER_ERROR:
/* Normal error ( for example writing to the client failed ).
* The ajp connection is still in a stable state but if we ask in configuration
* to abort when header has been send to client, mark as unrecoverable.
*/
if (wEnv->options & JK_OPT_RECO_ABORTIFTCSENDHEADER) {
req->is_recoverable_error = JK_FALSE;
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() by configuration, avoid recovery when tomcat has started to send headers to client\n");
}
else
ep->recoverable = JK_TRUE; /* Should we do this ? not sure */
return rc;
case JK_HANDLER_FATAL:
/*
* Protocol error. We'll disconnect the ajp connection and reconnect.
*/
ep->recoverable = JK_FALSE;
return rc;
default:
/* Unknown status */
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.processCallbacks() unknown status %d\n",
rc);
ep->recoverable = JK_FALSE;
return rc;
}
}
return JK_ERR;
}
static int jk2_workerEnv_addChannel(jk_env_t *env, jk_workerEnv_t *wEnv,
jk_channel_t *ch)
{
jk_bean_t *jkb;
ch->mbean->id = wEnv->channel_map->size(env, wEnv->channel_map);
wEnv->channel_map->add(env, wEnv->channel_map, ch->mbean->name, ch);
/* Automatically create the ajp13 worker to be used with this channel.
*/
jkb =
env->createBean2(env, ch->mbean->pool, "ajp13", ch->mbean->localName);
if (jkb == NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.addChannel(): Can't find ajp13 worker\n");
return JK_ERR;
}
ch->worker = jkb->object;
ch->worker->channelName = ch->mbean->name;
ch->worker->channel = ch;
return JK_OK;
}
static int jk2_workerEnv_addEndpoint(jk_env_t *env, jk_workerEnv_t *wEnv,
jk_endpoint_t *ep)
{
int pos = wEnv->endpointMap->size(env, wEnv->endpointMap);
wEnv->endpointMap->add(env, wEnv->endpointMap, ep->mbean->localName, ep);
ep->mbean->id = pos;
if (ep->mbean->init(env, ep->mbean) == JK_ERR)
return JK_ERR;
return JK_OK;
}
static int jk2_workerEnv_addWorker(jk_env_t *env, jk_workerEnv_t *wEnv,
jk_worker_t *w)
{
int err = JK_OK;
jk_worker_t *oldW = NULL;
w->workerEnv = wEnv;
w->mbean->id = wEnv->worker_map->size(env, wEnv->worker_map);
w->rPoolCache = jk2_objCache_create(env, w->mbean->pool);
err = w->rPoolCache->init(env, w->rPoolCache, 1024); /* XXX make it unbound */
wEnv->worker_map->put(env, wEnv->worker_map, w->mbean->name, w,
(void *)&oldW);
if (oldW != NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.addWorker() duplicated %s worker \n",
w->mbean->name);
if (w->mbean->destroy != NULL)
oldW->mbean->destroy(env, oldW->mbean);
}
return JK_OK;
}
static jk_worker_t *jk2_workerEnv_createWorker(jk_env_t *env,
jk_workerEnv_t *wEnv,
char *type, char *name)
{
jk_worker_t *w = NULL;
jk_bean_t *jkb;
/* First find if it already exists */
w = env->getByName(env, name);
if (w != NULL) {
env->l->jkLog(env, env->l, JK_LOG_INFO,
"workerEnv.createWorker(): Using existing worker %s\n",
name);
return w;
}
jkb = env->createBean(env, wEnv->pool, name);
if (jkb == NULL || jkb->object == NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"workerEnv.createWorker(): factory can't create worker %s:%s\n",
type, name);
return NULL;
}
w = (jk_worker_t *)jkb->object;
return w;
}
int JK_METHOD jk2_workerEnv_factory(jk_env_t *env, jk_pool_t *pool,
jk_bean_t *result,
const char *type, const char *name)
{
jk_workerEnv_t *wEnv;
jk_bean_t *jkb;
wEnv = (jk_workerEnv_t *)pool->calloc(env, pool, sizeof(jk_workerEnv_t));
/* env->l->jkLog(env, env->l, JK_LOG_DEBUG, "Creating workerEnv %#lx\n", wEnv); */
result->object = wEnv;
wEnv->mbean = result;
result->setAttribute = jk2_workerEnv_setAttribute;
wEnv->pool = pool;
wEnv->initData = NULL;
jk2_map_default_create(env, &wEnv->initData, pool);
/* Add 'compile time' settings. Those are defined in jk_global,
with the other platform-specific settings. No need to ask
the user what we can find ourself
*/
wEnv->initData->put(env, wEnv->initData, "fs", FILE_SEPARATOR_STR, NULL);
wEnv->initData->put(env, wEnv->initData, "ps", PATH_SEPARATOR_STR, NULL);
wEnv->initData->put(env, wEnv->initData, "so", SO_EXTENSION, NULL);
wEnv->initData->put(env, wEnv->initData, "arch", ARCH, NULL);
wEnv->logger_name = NULL;
wEnv->was_initialized = JK_FALSE;
wEnv->options = JK_OPT_FWDURIDEFAULT | JK_OPT_RECOSTRATEGYDEFAULT;
/*
* By default we will try to gather SSL info.
* Disable this functionality through JkExtractSSL
*/
wEnv->ssl_enable = JK_TRUE;
/*
* The defaults ssl indicators match those in mod_ssl (seems
* to be in more use).
*/
wEnv->https_indicator = "HTTPS";
wEnv->certs_indicator = "SSL_CLIENT_CERT";
/*
* The following (comented out) environment variables match apache_ssl!
* If you are using apache_sslapache_ssl uncomment them (or use the
* configuration directives to set them.
*
wEnv->cipher_indicator = "HTTPS_CIPHER";
wEnv->session_indicator = NULL;
*/
/*
* The following environment variables match mod_ssl! If you
* are using another module (say apache_ssl) comment them out.
*/
wEnv->cipher_indicator = "SSL_CIPHER";
wEnv->session_indicator = "SSL_SESSION_ID";
wEnv->key_size_indicator = "SSL_CIPHER_USEKEYSIZE";
/* if(!map_alloc(&(wEnv->automount))) { */
/* jk_error_exit(APLOG_MARK, APLOG_EMERG, s, p, "Memory error"); */
/* } */
wEnv->uriMap = NULL;
wEnv->envvars_in_use = JK_FALSE;
jk2_map_default_create(env, &wEnv->envvars, pool);
jk2_map_default_create(env, &wEnv->worker_map, wEnv->pool);
jk2_map_default_create(env, &wEnv->channel_map, wEnv->pool);
jk2_map_default_create(env, &wEnv->endpointMap, wEnv->pool);
wEnv->perThreadWorker = 0;
/* methods */
wEnv->init = &jk2_workerEnv_init;
wEnv->parentInit = &jk2_workerEnv_parentInit;
wEnv->close = &jk2_workerEnv_close;
wEnv->addWorker = &jk2_workerEnv_addWorker;
wEnv->addChannel = &jk2_workerEnv_addChannel;
wEnv->addEndpoint = &jk2_workerEnv_addEndpoint;
wEnv->initChannel = &jk2_workerEnv_initChannel;
wEnv->registerHandler = &jk2_workerEnv_registerHandler;
wEnv->processCallbacks = &jk2_workerEnv_processCallbacks;
wEnv->dispatch = &jk2_workerEnv_dispatch;
wEnv->globalEnv = env;
jkb = env->createBean2(env, wEnv->pool, "uriMap", "");
if (jkb == NULL || jkb->object == NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR,
"Error getting uriMap implementation\n");
return JK_ERR;
}
wEnv->uriMap = jkb->object;
wEnv->uriMap->workerEnv = wEnv;
jkb = env->createBean2(env, wEnv->pool, "config", "");
if (jkb == NULL) {
env->l->jkLog(env, env->l, JK_LOG_ERROR, "Error creating config\n");
return JK_ERR;
}
env->alias(env, "config:", "config");
wEnv->config = jkb->object;
wEnv->config->file = NULL;
wEnv->config->workerEnv = wEnv;
wEnv->config->map = wEnv->initData;
wEnv->childId = -1;
wEnv->epStat = NULL;
jkb = env->createBean2(env, wEnv->pool, "shm", "");
if (jkb == NULL) {
wEnv->shm = NULL;
}
else {
env->alias(env, "shm:", "shm");
wEnv->shm = (jk_shm_t *)jkb->object;
}
return JK_OK;
}