~ubuntu-branches/ubuntu/oneiric/libapache-mod-jk/oneiric

« back to all changes in this revision

Viewing changes to jk/native/common/jk_worker.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2006-08-05 16:30:53 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060805163053-myf66gm6j1a21ps6
Tags: 1:1.2.18-1ubuntu1
Merge from Debian unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright 1999-2004 The Apache Software Foundation
3
 
 *
4
 
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 
 *  you may not use this file except in compliance with the License.
6
 
 *  You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 *  Unless required by applicable law or agreed to in writing, software
11
 
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 *  See the License for the specific language governing permissions and
14
 
 *  limitations under the License.
15
 
 */
16
 
 
17
 
/***************************************************************************
18
 
 * Description: Workers controller                                         *
19
 
 * Author:      Gal Shachor <shachor@il.ibm.com>                           *
20
 
 * Author:      Henri Gomez <hgomez@apache.org>                            *
21
 
 * Version:     $Revision: 1.36 $                                          *
22
 
 ***************************************************************************/
23
 
 
24
 
#define _PLACE_WORKER_LIST_HERE
25
 
#include "jk_worker_list.h"
26
 
#include "jk_worker.h"
27
 
#include "jk_util.h"
28
 
#include "jk_mt.h"
29
 
 
30
 
static void close_workers(jk_logger_t *l);
31
 
 
32
 
static worker_factory get_factory_for(const char *type);
33
 
 
34
 
static int build_worker_map(jk_map_t *init_data,
35
 
                            char **worker_list,
36
 
                            unsigned num_of_workers,
37
 
                            jk_worker_env_t *we, jk_logger_t *l);
38
 
 
39
 
/* Global worker list */
40
 
static jk_map_t *worker_map;
41
 
#if _MT_CODE
42
 
static JK_CRIT_SEC worker_lock;
43
 
#endif
44
 
static int worker_maintain_time = 0;
45
 
 
46
 
int wc_open(jk_map_t *init_data, jk_worker_env_t *we, jk_logger_t *l)
47
 
{
48
 
    int rc;
49
 
    JK_TRACE_ENTER(l);
50
 
 
51
 
    if (!jk_map_alloc(&worker_map)) {
52
 
        JK_TRACE_EXIT(l);
53
 
        return JK_FALSE;
54
 
    }
55
 
    JK_INIT_CS(&worker_lock, rc);
56
 
    if (rc == JK_FALSE) {
57
 
        jk_log(l, JK_LOG_ERROR,
58
 
                "creating thread lock errno=%d",
59
 
                errno);
60
 
        JK_TRACE_EXIT(l);
61
 
        return JK_FALSE;
62
 
    }
63
 
 
64
 
    if (!jk_get_worker_list(init_data, &(we->worker_list),
65
 
                            &we->num_of_workers)) {
66
 
        JK_TRACE_EXIT(l);
67
 
        we->num_of_workers = 0;
68
 
        we->worker_list = NULL;
69
 
        return JK_FALSE;
70
 
    }
71
 
 
72
 
    worker_maintain_time = jk_get_worker_maintain_time(init_data);
73
 
 
74
 
    if (!build_worker_map(init_data, we->worker_list,
75
 
                          we->num_of_workers, we, l)) {
76
 
        close_workers(l);
77
 
        we->num_of_workers = 0;
78
 
        we->worker_list = NULL;
79
 
        JK_TRACE_EXIT(l);
80
 
        return JK_FALSE;
81
 
    }
82
 
 
83
 
    JK_TRACE_EXIT(l);
84
 
    return JK_TRUE;
85
 
}
86
 
 
87
 
 
88
 
void wc_close(jk_logger_t *l)
89
 
{
90
 
    int rc;
91
 
    JK_TRACE_ENTER(l);
92
 
    JK_DELETE_CS(&worker_lock, rc);
93
 
    close_workers(l);
94
 
    JK_TRACE_EXIT(l);
95
 
}
96
 
 
97
 
jk_worker_t *wc_get_worker_for_name(const char *name, jk_logger_t *l)
98
 
{
99
 
    jk_worker_t *rc;
100
 
 
101
 
    JK_TRACE_ENTER(l);
102
 
    if (!name) {
103
 
        JK_LOG_NULL_PARAMS(l);
104
 
        JK_TRACE_EXIT(l);
105
 
        return NULL;
106
 
    }
107
 
 
108
 
    rc = jk_map_get(worker_map, name, NULL);
109
 
 
110
 
    if (JK_IS_DEBUG_LEVEL(l))
111
 
        jk_log(l, JK_LOG_DEBUG, "%s a worker %s",
112
 
               rc ? "found" : "did not find", name);
113
 
    JK_TRACE_EXIT(l);
114
 
    return rc;
115
 
}
116
 
 
117
 
int wc_create_worker(const char *name, int use_map,
118
 
                     jk_map_t *init_data,
119
 
                     jk_worker_t **rc, jk_worker_env_t *we, jk_logger_t *l)
120
 
{
121
 
    JK_TRACE_ENTER(l);
122
 
 
123
 
    if (rc) {
124
 
        const char *type = jk_get_worker_type(init_data, name);
125
 
        worker_factory fac = get_factory_for(type);
126
 
        jk_worker_t *w = NULL;
127
 
        unsigned int i, num_of_maps;
128
 
        char **map_names;
129
 
        int wtype;
130
 
 
131
 
        *rc = NULL;
132
 
 
133
 
        if (!fac) {
134
 
            jk_log(l, JK_LOG_ERROR, "Unknown worker type %s for worker %s",
135
 
                   type, name);
136
 
            JK_TRACE_EXIT(l);
137
 
            return JK_FALSE;
138
 
        }
139
 
 
140
 
        if (JK_IS_DEBUG_LEVEL(l))
141
 
            jk_log(l, JK_LOG_DEBUG,
142
 
                   "about to create instance %s of %s", name,
143
 
                   type);
144
 
 
145
 
        if (((wtype = fac(&w, name, l)) == 0) || !w) {
146
 
            jk_log(l, JK_LOG_ERROR,
147
 
                   "factory for %s failed for %s", type,
148
 
                   name);
149
 
            JK_TRACE_EXIT(l);
150
 
            return JK_FALSE;
151
 
        }
152
 
 
153
 
        if (JK_IS_DEBUG_LEVEL(l))
154
 
            jk_log(l, JK_LOG_DEBUG,
155
 
                   "about to validate and init %s", name);
156
 
        if (!w->validate(w, init_data, we, l)) {
157
 
            w->destroy(&w, l);
158
 
            jk_log(l, JK_LOG_ERROR,
159
 
                   "validate failed for %s", name);
160
 
            JK_TRACE_EXIT(l);
161
 
            return JK_FALSE;
162
 
        }
163
 
 
164
 
        if (!w->init(w, init_data, we, l)) {
165
 
            w->destroy(&w, l);
166
 
            jk_log(l, JK_LOG_ERROR, "init failed for %s",
167
 
                   name);
168
 
            JK_TRACE_EXIT(l);
169
 
            return JK_FALSE;
170
 
        }
171
 
        if (use_map &&
172
 
            jk_get_worker_mount_list(init_data, name,
173
 
                                     &map_names,
174
 
                                     &num_of_maps) && num_of_maps) {
175
 
            for (i = 0; i < num_of_maps; i++) {
176
 
                if (JK_IS_DEBUG_LEVEL(l))
177
 
                    jk_log(l, JK_LOG_DEBUG,
178
 
                            "mounting %s to worker %s",
179
 
                            map_names[i], name);
180
 
                if (uri_worker_map_add(we->uri_to_worker, map_names[i],
181
 
                                       name, l) == JK_FALSE) {
182
 
                    w->destroy(&w, l);
183
 
                    jk_log(l, JK_LOG_ERROR,
184
 
                           "validate failed for %s", name);
185
 
                    JK_TRACE_EXIT(l);
186
 
                    return JK_FALSE;
187
 
                }
188
 
            }
189
 
        }
190
 
        w->type = wtype;
191
 
        *rc = w;
192
 
        JK_TRACE_EXIT(l);
193
 
        return JK_TRUE;
194
 
    }
195
 
 
196
 
    JK_LOG_NULL_PARAMS(l);
197
 
    return JK_FALSE;
198
 
}
199
 
 
200
 
static void close_workers(jk_logger_t *l)
201
 
{
202
 
    int sz = jk_map_size(worker_map);
203
 
 
204
 
    JK_TRACE_ENTER(l);
205
 
 
206
 
    if (sz > 0) {
207
 
        int i;
208
 
        for (i = 0; i < sz; i++) {
209
 
            jk_worker_t *w = jk_map_value_at(worker_map, i);
210
 
            if (w) {
211
 
                if (JK_IS_DEBUG_LEVEL(l))
212
 
                    jk_log(l, JK_LOG_DEBUG,
213
 
                           "close_workers will destroy worker %s",
214
 
                           jk_map_name_at(worker_map, i));
215
 
                w->destroy(&w, l);
216
 
            }
217
 
        }
218
 
    }
219
 
    jk_map_free(&worker_map);
220
 
    JK_TRACE_EXIT(l);
221
 
}
222
 
 
223
 
static int build_worker_map(jk_map_t *init_data,
224
 
                            char **worker_list,
225
 
                            unsigned num_of_workers,
226
 
                            jk_worker_env_t *we, jk_logger_t *l)
227
 
{
228
 
    unsigned i;
229
 
 
230
 
    JK_TRACE_ENTER(l);
231
 
 
232
 
    for (i = 0; i < num_of_workers; i++) {
233
 
        jk_worker_t *w = NULL;
234
 
 
235
 
        if (JK_IS_DEBUG_LEVEL(l))
236
 
            jk_log(l, JK_LOG_DEBUG,
237
 
                   "creating worker %s", worker_list[i]);
238
 
 
239
 
        if (wc_create_worker(worker_list[i], 1, init_data, &w, we, l)) {
240
 
            jk_worker_t *oldw = NULL;
241
 
            if (!jk_map_put(worker_map, worker_list[i], w, (void *)&oldw)) {
242
 
                w->destroy(&w, l);
243
 
                JK_TRACE_EXIT(l);
244
 
                return JK_FALSE;
245
 
            }
246
 
 
247
 
            if (JK_IS_DEBUG_LEVEL(l))
248
 
                jk_log(l, JK_LOG_DEBUG,
249
 
                       "removing old %s worker",
250
 
                       worker_list[i]);
251
 
            if (oldw) {
252
 
                oldw->destroy(&oldw, l);
253
 
            }
254
 
        }
255
 
        else {
256
 
            jk_log(l, JK_LOG_ERROR,
257
 
                   "failed to create worker %s",
258
 
                   worker_list[i]);
259
 
            JK_TRACE_EXIT(l);
260
 
            return JK_FALSE;
261
 
        }
262
 
    }
263
 
 
264
 
    JK_TRACE_EXIT(l);
265
 
    return JK_TRUE;
266
 
}
267
 
 
268
 
static worker_factory get_factory_for(const char *type)
269
 
{
270
 
    worker_factory_record_t *factory = &worker_factories[0];
271
 
    while (factory->name) {
272
 
        if (0 == strcmp(factory->name, type)) {
273
 
            return factory->fac;
274
 
        }
275
 
 
276
 
        factory++;
277
 
    }
278
 
 
279
 
    return NULL;
280
 
}
281
 
 
282
 
void wc_maintain(jk_logger_t *l)
283
 
{
284
 
    static time_t last_maintain = 0;
285
 
    int sz = jk_map_size(worker_map);
286
 
 
287
 
    JK_TRACE_ENTER(l);
288
 
 
289
 
    if (sz > 0 && worker_maintain_time > 0) {
290
 
        int i;
291
 
        time_t now;
292
 
        JK_ENTER_CS(&worker_lock, i);
293
 
        now = time(NULL);
294
 
        if (difftime(now, last_maintain) >= worker_maintain_time) {
295
 
            last_maintain = now;
296
 
            JK_LEAVE_CS(&worker_lock, i);
297
 
            for (i = 0; i < sz; i++) {
298
 
                jk_worker_t *w = jk_map_value_at(worker_map, i);
299
 
                if (w && w->maintain) {
300
 
                    if (JK_IS_DEBUG_LEVEL(l))
301
 
                        jk_log(l, JK_LOG_DEBUG,
302
 
                               "Maintaining worker %s",
303
 
                               jk_map_name_at(worker_map, i));
304
 
                    w->maintain(w, l);
305
 
                }
306
 
            }
307
 
        }
308
 
        else {
309
 
            JK_LEAVE_CS(&worker_lock, i);
310
 
        }
311
 
    }
312
 
    JK_TRACE_EXIT(l);
313
 
}