2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 /***************************************************************************
19 * Description: Workers controller *
20 * Author: Gal Shachor <shachor@il.ibm.com> *
21 * Author: Henri Gomez <hgomez@apache.org> *
22 * Version: $Revision: 708019 $ *
23 ***************************************************************************/
25 #define _PLACE_WORKER_LIST_HERE
26 #include "jk_worker_list.h"
27 #include "jk_worker.h"
31 static void close_workers(jk_logger_t *l);
33 static worker_factory get_factory_for(const char *type);
35 static int build_worker_map(jk_map_t *init_data,
37 unsigned num_of_workers,
38 jk_worker_env_t *we, jk_logger_t *l);
40 /* Global worker list */
41 static jk_map_t *worker_map;
43 static JK_CRIT_SEC worker_lock;
45 static int worker_maintain_time = 0;
47 int wc_open(jk_map_t *init_data, jk_worker_env_t *we, jk_logger_t *l)
52 if (!jk_map_alloc(&worker_map)) {
56 JK_INIT_CS(&worker_lock, rc);
58 jk_log(l, JK_LOG_ERROR,
59 "creating thread lock (errno=%d)",
65 jk_map_dump(init_data, l);
66 we->init_data = init_data;
67 if (!jk_get_worker_list(init_data, &(we->worker_list),
68 &we->num_of_workers)) {
70 we->num_of_workers = 0;
71 we->worker_list = NULL;
75 worker_maintain_time = jk_get_worker_maintain_time(init_data);
76 if(worker_maintain_time < 0)
77 worker_maintain_time = 0;
79 if (!build_worker_map(init_data, we->worker_list,
80 we->num_of_workers, we, l)) {
82 we->num_of_workers = 0;
83 we->worker_list = NULL;
93 void wc_close(jk_logger_t *l)
97 JK_DELETE_CS(&worker_lock, rc);
102 jk_worker_t *wc_get_worker_for_name(const char *name, jk_logger_t *l)
108 JK_LOG_NULL_PARAMS(l);
113 rc = jk_map_get(worker_map, name, NULL);
115 if (JK_IS_DEBUG_LEVEL(l))
116 jk_log(l, JK_LOG_DEBUG, "%s a worker %s",
117 rc ? "found" : "did not find", name);
122 int wc_create_worker(const char *name, int use_map,
124 jk_worker_t **rc, jk_worker_env_t *we, jk_logger_t *l)
129 const char *type = jk_get_worker_type(init_data, name);
130 worker_factory fac = get_factory_for(type);
131 jk_worker_t *w = NULL;
132 unsigned int i, num_of_maps;
139 jk_log(l, JK_LOG_ERROR, "Unknown worker type %s for worker %s",
145 if (JK_IS_DEBUG_LEVEL(l))
146 jk_log(l, JK_LOG_DEBUG,
147 "about to create instance %s of %s", name,
150 if (((wtype = fac(&w, name, l)) == 0) || !w) {
151 jk_log(l, JK_LOG_ERROR,
152 "factory for %s failed for %s", type,
158 if (JK_IS_DEBUG_LEVEL(l))
159 jk_log(l, JK_LOG_DEBUG,
160 "about to validate and init %s", name);
161 if (!w->validate(w, init_data, we, l)) {
163 jk_log(l, JK_LOG_ERROR,
164 "validate failed for %s", name);
169 if (!w->init(w, init_data, we, l)) {
171 jk_log(l, JK_LOG_ERROR, "init failed for %s",
177 jk_get_worker_mount_list(init_data, name,
179 &num_of_maps) && num_of_maps) {
180 for (i = 0; i < num_of_maps; i++) {
181 if (JK_IS_DEBUG_LEVEL(l))
182 jk_log(l, JK_LOG_DEBUG,
183 "mounting %s to worker %s",
185 if (uri_worker_map_add(we->uri_to_worker, map_names[i],
186 name, SOURCE_TYPE_WORKERDEF, l) == JK_FALSE) {
188 jk_log(l, JK_LOG_ERROR,
189 "mounting %s failed for %s",
202 JK_LOG_NULL_PARAMS(l);
206 static void close_workers(jk_logger_t *l)
208 int sz = jk_map_size(worker_map);
214 for (i = 0; i < sz; i++) {
215 jk_worker_t *w = jk_map_value_at(worker_map, i);
217 if (JK_IS_DEBUG_LEVEL(l))
218 jk_log(l, JK_LOG_DEBUG,
219 "close_workers will destroy worker %s",
220 jk_map_name_at(worker_map, i));
225 jk_map_free(&worker_map);
229 static int build_worker_map(jk_map_t *init_data,
231 unsigned num_of_workers,
232 jk_worker_env_t *we, jk_logger_t *l)
238 for (i = 0; i < num_of_workers; i++) {
239 jk_worker_t *w = NULL;
241 if (JK_IS_DEBUG_LEVEL(l))
242 jk_log(l, JK_LOG_DEBUG,
243 "creating worker %s", worker_list[i]);
245 if (wc_create_worker(worker_list[i], 1, init_data, &w, we, l)) {
246 jk_worker_t *oldw = NULL;
247 if (!jk_map_put(worker_map, worker_list[i], w, (void *)&oldw)) {
254 if (JK_IS_DEBUG_LEVEL(l))
255 jk_log(l, JK_LOG_DEBUG,
256 "removing old %s worker",
258 oldw->destroy(&oldw, l);
262 jk_log(l, JK_LOG_ERROR,
263 "failed to create worker %s",
274 static worker_factory get_factory_for(const char *type)
276 worker_factory_record_t *factory = &worker_factories[0];
277 while (factory->name) {
278 if (0 == strcmp(factory->name, type)) {
288 const char *wc_get_name_for_type(int type, jk_logger_t *l)
290 worker_factory_record_t *factory = &worker_factories[0];
291 while (factory->name) {
292 if (type == factory->type) {
293 jk_log(l, JK_LOG_DEBUG,
294 "Found worker type '%s'",
296 return factory->name;
305 void wc_maintain(jk_logger_t *l)
307 static time_t last_maintain = 0;
308 static int running_maintain = 0;
309 int sz = jk_map_size(worker_map);
313 /* Only proceed if all of the below hold true:
314 * - there are workers
315 * - maintenance wasn't disabled by configuration
316 * - time since last maintenance is big enough
318 if (sz > 0 && worker_maintain_time > 0 &&
319 difftime(time(NULL), last_maintain) >= worker_maintain_time) {
321 JK_ENTER_CS(&worker_lock, i);
322 if (running_maintain ||
323 difftime(time(NULL), last_maintain) < worker_maintain_time) {
324 /* Already in maintain */
325 JK_LEAVE_CS(&worker_lock, i);
329 /* Set the maintain run flag so other threads skip
330 * the maintain until we are finished.
332 running_maintain = 1;
333 JK_LEAVE_CS(&worker_lock, i);
335 for (i = 0; i < sz; i++) {
336 jk_worker_t *w = jk_map_value_at(worker_map, i);
337 if (w && w->maintain) {
338 if (JK_IS_DEBUG_LEVEL(l))
339 jk_log(l, JK_LOG_DEBUG,
340 "Maintaining worker %s",
341 jk_map_name_at(worker_map, i));
342 w->maintain(w, time(NULL), l);
345 JK_ENTER_CS(&worker_lock, i);
346 last_maintain = time(NULL);
347 running_maintain = 0;
348 JK_LEAVE_CS(&worker_lock, i);