/[hydra]/hydra/src/hic.c
ViewVC logotype

Contents of /hydra/src/hic.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.8 - (show annotations)
Mon Sep 30 17:16:54 2002 UTC (21 years, 6 months ago) by nmav
Branch: MAIN
CVS Tags: hydra_0_0_4
Changes since 1.7: +53 -29 lines
File MIME type: text/plain
Added support for multiple HIC threads.

1 /*
2 * Copyright (C) 2002 Nikos Mavroyanopoulos
3 *
4 * This file is part of BOA webserver.
5 *
6 * Hydra is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * Hydra is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #include "boa.h"
22 #include <signal.h> /* signal */
23
24 /* Hydra Internally handled CGIs (HIC HIC)
25 *
26 * How does it work?
27 *
28 * A special thread (maybe more than one), is used for CGIs. This tread
29 * uses one pipe to communicate with the others via hic_send_command().
30 *
31 * If a request for a HIC file arrives, the server goes as a normal CGI
32 * creates a pipe, but does not fork. It enqueues a hic_request
33 * for this (HIC) thread, and sends a SIGUSR2 signal. The HIC thread is then
34 * waken up, and handles all pending requests.
35 *
36 * The HIC thread, when receives the message, parses the CGIs,
37 * one CGI at the time, and sends the output to fd.
38 *
39 * The benefit is that in no case the server is blocked. We may have
40 * a performance problem, if the server only uses parsed CGIs.
41 *
42 */
43
44 #ifdef ENABLE_HIC
45
46 #include "hic.h"
47
48 static int process_hic_request(hic_params*, hic_request * cmd);
49 void hic_dequeue(hic_request ** head, hic_request * req);
50 void hic_enqueue(hic_request ** head, hic_request * req);
51 int hic_sigchld_flag = 0; /* if we received a SIGCHLD signal, then this flag
52 * is non zero */
53
54 void *hic_main_loop(void *_hic_params)
55 {
56 hic_request* current, *next;
57 hic_params *params = _hic_params;
58
59 #ifdef ENABLE_SMP
60 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);
61 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
62 #endif
63
64 while (1) {
65 for (current = params->request_head;current;current=next) {
66
67 #ifdef ENABLE_SMP
68 pthread_mutex_lock(&params->lock);
69 #endif
70 next = current->next;
71 #ifdef ENABLE_SMP
72 pthread_mutex_unlock(&params->lock);
73 #endif
74
75 if (process_hic_request( params, current) == -1) {
76 log_error_time();
77 fprintf(stderr, "hic: Error while processing command.\n");
78 exit(1);
79 }
80 }
81
82 /* If somebody sends a command, then he should
83 * send a sigusr2 as well.
84 */
85 unblock_sigusr2();
86 if (!params->request_head) pause();
87 block_sigusr2();
88
89 if (params->sigchld_flag)
90 sigchld_run();
91
92
93 }
94
95 }
96
97 static int process_hic_request(hic_params* params, hic_request * req)
98 {
99 hic_module_st *hst;
100 hic_stuff* cmd = &req->command;
101
102 #ifdef ENABLE_SMP
103 pthread_mutex_lock(&params->lock);
104 #endif
105 hic_dequeue( &params->request_head, req);
106 #ifdef ENABLE_SMP
107 pthread_mutex_unlock(&params->lock);
108 #endif
109
110 hst = find_hic_appr_module(get_mime_type(cmd->path_translated), 0);
111 if (hst == NULL) {
112 log_error_time();
113 fprintf(stderr, "Could not find HIC handler for '%s'\n",
114 cmd->path_translated);
115 close(cmd->out_fd);
116 free( req);
117 return 0;
118 }
119
120 hst->request(cmd);
121 close(cmd->out_fd);
122 free( req);
123
124 /*
125 log_error_time();
126 fprintf(stderr, "HIC status: %d wrote: %d\n", cmd->status, cmd->bytes_sent);
127 */
128
129 return 0;
130 }
131
132 #ifdef ENABLE_SMP
133 /* We use this index, to send messages to different
134 * HIC thread every time.
135 */
136 static pthread_mutex_t index_lock = PTHREAD_MUTEX_INITIALIZER;
137 static int index;
138 #endif
139
140 /* Sends a command to a HIC thread.
141 */
142 int hic_send_command(request * req, int out_fd)
143 {
144 hic_request *x;
145 hic_params *params;
146
147 /* choose a random hic thread */
148 if (global_hic_params_size > 1) {
149 #ifdef ENABLE_SMP
150 pthread_mutex_lock( &index_lock);
151 #endif
152 params = &global_hic_params[ index];
153 index++;
154 index %= global_hic_params_size;
155 #ifdef ENABLE_SMP
156 pthread_mutex_unlock( &index_lock);
157 #endif
158 } else {
159 params = &global_hic_params[0];
160 }
161
162 x = malloc( sizeof( hic_request));
163 if (x==NULL)
164 return -1;
165
166 x->next = x->prev = NULL;
167 x->command.cgi_env = req->cgi_env;
168 x->command.cgi_env_max = req->cgi_env_index;
169 x->command.one_one = 0;
170 x->command.post_data_fd = req->post_data_fd;
171 x->command.out_fd = out_fd;
172 x->command.request_uri = req->request_uri;
173 x->command.path_translated = req->path_translated;
174
175 if (!req->secure)
176 x->command.server_version = boa_version;
177 else
178 x->command.server_version = boa_tls_version;
179
180 #ifdef ENABLE_SMP
181 pthread_mutex_lock(&params->lock);
182 #endif
183
184 hic_enqueue( &params->request_head, x);
185 #ifdef ENABLE_SMP
186 /* Notify the HIC thread about the pending request
187 */
188 pthread_kill( params->tid, SIGUSR2);
189 #endif
190
191 #ifdef ENABLE_SMP
192 pthread_mutex_unlock(&params->lock);
193 #endif
194
195 return 1;
196
197 }
198
199 /* Implement a basic queue for HIC stuff. This is created after
200 * queue.c.
201 */
202
203 #include "queue.h"
204
205 ENQUEUE_FUNCTION( hic_enqueue, hic_request)
206 DEQUEUE_FUNCTION( hic_dequeue, hic_request)
207
208 #endif /* ENABLE_HIC */

webmaster@linux.gr
ViewVC Help
Powered by ViewVC 1.1.26