summaryrefslogtreecommitdiffstats
path: root/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c
diff options
context:
space:
mode:
Diffstat (limited to 'rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c')
-rw-r--r--rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c
new file mode 100644
index 00000000..b75ae933
--- /dev/null
+++ b/rubbos/app/tomcat-connectors-1.2.32-src/native/common/jk_worker.c
@@ -0,0 +1,351 @@
+/*
+ * 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: Workers controller *
+ * Author: Gal Shachor <shachor@il.ibm.com> *
+ * Author: Henri Gomez <hgomez@apache.org> *
+ * Version: $Revision: 708019 $ *
+ ***************************************************************************/
+
+#define _PLACE_WORKER_LIST_HERE
+#include "jk_worker_list.h"
+#include "jk_worker.h"
+#include "jk_util.h"
+#include "jk_mt.h"
+
+static void close_workers(jk_logger_t *l);
+
+static worker_factory get_factory_for(const char *type);
+
+static int build_worker_map(jk_map_t *init_data,
+ char **worker_list,
+ unsigned num_of_workers,
+ jk_worker_env_t *we, jk_logger_t *l);
+
+/* Global worker list */
+static jk_map_t *worker_map;
+#if _MT_CODE
+static JK_CRIT_SEC worker_lock;
+#endif
+static int worker_maintain_time = 0;
+
+int wc_open(jk_map_t *init_data, jk_worker_env_t *we, jk_logger_t *l)
+{
+ int rc;
+ JK_TRACE_ENTER(l);
+
+ if (!jk_map_alloc(&worker_map)) {
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+ JK_INIT_CS(&worker_lock, rc);
+ if (rc == JK_FALSE) {
+ jk_log(l, JK_LOG_ERROR,
+ "creating thread lock (errno=%d)",
+ errno);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ jk_map_dump(init_data, l);
+ we->init_data = init_data;
+ if (!jk_get_worker_list(init_data, &(we->worker_list),
+ &we->num_of_workers)) {
+ JK_TRACE_EXIT(l);
+ we->num_of_workers = 0;
+ we->worker_list = NULL;
+ return JK_FALSE;
+ }
+
+ worker_maintain_time = jk_get_worker_maintain_time(init_data);
+ if(worker_maintain_time < 0)
+ worker_maintain_time = 0;
+
+ if (!build_worker_map(init_data, we->worker_list,
+ we->num_of_workers, we, l)) {
+ close_workers(l);
+ we->num_of_workers = 0;
+ we->worker_list = NULL;
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ JK_TRACE_EXIT(l);
+ return JK_TRUE;
+}
+
+
+void wc_close(jk_logger_t *l)
+{
+ int rc;
+ JK_TRACE_ENTER(l);
+ JK_DELETE_CS(&worker_lock, rc);
+ close_workers(l);
+ JK_TRACE_EXIT(l);
+}
+
+jk_worker_t *wc_get_worker_for_name(const char *name, jk_logger_t *l)
+{
+ jk_worker_t *rc;
+
+ JK_TRACE_ENTER(l);
+ if (!name) {
+ JK_LOG_NULL_PARAMS(l);
+ JK_TRACE_EXIT(l);
+ return NULL;
+ }
+
+ rc = jk_map_get(worker_map, name, NULL);
+
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG, "%s a worker %s",
+ rc ? "found" : "did not find", name);
+ JK_TRACE_EXIT(l);
+ return rc;
+}
+
+int wc_create_worker(const char *name, int use_map,
+ jk_map_t *init_data,
+ jk_worker_t **rc, jk_worker_env_t *we, jk_logger_t *l)
+{
+ JK_TRACE_ENTER(l);
+
+ if (rc) {
+ const char *type = jk_get_worker_type(init_data, name);
+ worker_factory fac = get_factory_for(type);
+ jk_worker_t *w = NULL;
+ unsigned int i, num_of_maps;
+ char **map_names;
+ int wtype;
+
+ *rc = NULL;
+
+ if (!fac) {
+ jk_log(l, JK_LOG_ERROR, "Unknown worker type %s for worker %s",
+ type, name);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "about to create instance %s of %s", name,
+ type);
+
+ if (((wtype = fac(&w, name, l)) == 0) || !w) {
+ jk_log(l, JK_LOG_ERROR,
+ "factory for %s failed for %s", type,
+ name);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "about to validate and init %s", name);
+ if (!w->validate(w, init_data, we, l)) {
+ w->destroy(&w, l);
+ jk_log(l, JK_LOG_ERROR,
+ "validate failed for %s", name);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ if (!w->init(w, init_data, we, l)) {
+ w->destroy(&w, l);
+ jk_log(l, JK_LOG_ERROR, "init failed for %s",
+ name);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+ if (use_map &&
+ jk_get_worker_mount_list(init_data, name,
+ &map_names,
+ &num_of_maps) && num_of_maps) {
+ for (i = 0; i < num_of_maps; i++) {
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "mounting %s to worker %s",
+ map_names[i], name);
+ if (uri_worker_map_add(we->uri_to_worker, map_names[i],
+ name, SOURCE_TYPE_WORKERDEF, l) == JK_FALSE) {
+ w->destroy(&w, l);
+ jk_log(l, JK_LOG_ERROR,
+ "mounting %s failed for %s",
+ map_names[i], name);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+ }
+ }
+ w->type = wtype;
+ *rc = w;
+ JK_TRACE_EXIT(l);
+ return JK_TRUE;
+ }
+
+ JK_LOG_NULL_PARAMS(l);
+ return JK_FALSE;
+}
+
+static void close_workers(jk_logger_t *l)
+{
+ int sz = jk_map_size(worker_map);
+
+ JK_TRACE_ENTER(l);
+
+ if (sz > 0) {
+ int i;
+ for (i = 0; i < sz; i++) {
+ jk_worker_t *w = jk_map_value_at(worker_map, i);
+ if (w) {
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "close_workers will destroy worker %s",
+ jk_map_name_at(worker_map, i));
+ w->destroy(&w, l);
+ }
+ }
+ }
+ jk_map_free(&worker_map);
+ JK_TRACE_EXIT(l);
+}
+
+static int build_worker_map(jk_map_t *init_data,
+ char **worker_list,
+ unsigned num_of_workers,
+ jk_worker_env_t *we, jk_logger_t *l)
+{
+ unsigned i;
+
+ JK_TRACE_ENTER(l);
+
+ for (i = 0; i < num_of_workers; i++) {
+ jk_worker_t *w = NULL;
+
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "creating worker %s", worker_list[i]);
+
+ if (wc_create_worker(worker_list[i], 1, init_data, &w, we, l)) {
+ jk_worker_t *oldw = NULL;
+ if (!jk_map_put(worker_map, worker_list[i], w, (void *)&oldw)) {
+ w->destroy(&w, l);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+
+ if (oldw) {
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "removing old %s worker",
+ worker_list[i]);
+ oldw->destroy(&oldw, l);
+ }
+ }
+ else {
+ jk_log(l, JK_LOG_ERROR,
+ "failed to create worker %s",
+ worker_list[i]);
+ JK_TRACE_EXIT(l);
+ return JK_FALSE;
+ }
+ }
+
+ JK_TRACE_EXIT(l);
+ return JK_TRUE;
+}
+
+static worker_factory get_factory_for(const char *type)
+{
+ worker_factory_record_t *factory = &worker_factories[0];
+ while (factory->name) {
+ if (0 == strcmp(factory->name, type)) {
+ return factory->fac;
+ }
+
+ factory++;
+ }
+
+ return NULL;
+}
+
+const char *wc_get_name_for_type(int type, jk_logger_t *l)
+{
+ worker_factory_record_t *factory = &worker_factories[0];
+ while (factory->name) {
+ if (type == factory->type) {
+ jk_log(l, JK_LOG_DEBUG,
+ "Found worker type '%s'",
+ factory->name);
+ return factory->name;
+ }
+
+ factory++;
+ }
+
+ return NULL;
+}
+
+void wc_maintain(jk_logger_t *l)
+{
+ static time_t last_maintain = 0;
+ static int running_maintain = 0;
+ int sz = jk_map_size(worker_map);
+
+ JK_TRACE_ENTER(l);
+
+ /* Only proceed if all of the below hold true:
+ * - there are workers
+ * - maintenance wasn't disabled by configuration
+ * - time since last maintenance is big enough
+ */
+ if (sz > 0 && worker_maintain_time > 0 &&
+ difftime(time(NULL), last_maintain) >= worker_maintain_time) {
+ int i;
+ JK_ENTER_CS(&worker_lock, i);
+ if (running_maintain ||
+ difftime(time(NULL), last_maintain) < worker_maintain_time) {
+ /* Already in maintain */
+ JK_LEAVE_CS(&worker_lock, i);
+ JK_TRACE_EXIT(l);
+ return;
+ }
+ /* Set the maintain run flag so other threads skip
+ * the maintain until we are finished.
+ */
+ running_maintain = 1;
+ JK_LEAVE_CS(&worker_lock, i);
+
+ for (i = 0; i < sz; i++) {
+ jk_worker_t *w = jk_map_value_at(worker_map, i);
+ if (w && w->maintain) {
+ if (JK_IS_DEBUG_LEVEL(l))
+ jk_log(l, JK_LOG_DEBUG,
+ "Maintaining worker %s",
+ jk_map_name_at(worker_map, i));
+ w->maintain(w, time(NULL), l);
+ }
+ }
+ JK_ENTER_CS(&worker_lock, i);
+ last_maintain = time(NULL);
+ running_maintain = 0;
+ JK_LEAVE_CS(&worker_lock, i);
+ }
+ JK_TRACE_EXIT(l);
+}