webroar 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +48 -1
- data/README +11 -14
- data/Rakefile +1 -1
- data/conf/mime_type.yml +172 -166
- data/conf/server_internal_config.yml +30 -8
- data/doc/user-guide.html +294 -153
- data/doc/user-guide.txt +9 -13
- data/lib/command_runner.rb +1 -0
- data/lib/dependencies.rb +18 -15
- data/lib/installer.rb +115 -50
- data/src/admin_panel/app/controllers/admin_controller.rb +1 -15
- data/src/admin_panel/app/controllers/application_controller.rb +2 -2
- data/src/admin_panel/app/controllers/application_specification_controller.rb +2 -1
- data/src/admin_panel/app/controllers/headers_controller.rb +73 -0
- data/src/admin_panel/app/controllers/mail_specification_controller.rb +10 -0
- data/src/admin_panel/app/controllers/server_specification_controller.rb +14 -0
- data/src/admin_panel/app/helpers/admin_helper.rb +0 -85
- data/src/admin_panel/app/models/app.rb +1 -1
- data/src/admin_panel/app/models/application_specification.rb +33 -25
- data/src/admin_panel/app/models/headers.rb +116 -0
- data/src/admin_panel/app/models/mail_specification.rb +20 -5
- data/src/admin_panel/app/models/server_specification.rb +2 -7
- data/src/admin_panel/app/views/admin/configuration.html.erb +10 -5
- data/src/admin_panel/app/views/exceptions/_exception_list_partial.html.erb +4 -4
- data/src/admin_panel/app/views/graph/_graph_page.html.erb +3 -0
- data/src/admin_panel/app/views/headers/_add_expires_text_box.html.erb +35 -0
- data/src/admin_panel/app/views/headers/_expires_by_type_form.html.erb +65 -0
- data/src/admin_panel/app/views/headers/_headers_table.html.erb +113 -0
- data/src/admin_panel/app/views/mail_specification/_current_spec.html.erb +168 -0
- data/src/admin_panel/app/views/{admin → server_specification}/_add_div.html.erb +1 -1
- data/src/admin_panel/config/initializers/application_constants.rb +6 -0
- data/src/admin_panel/lib/control.rb +6 -3
- data/src/admin_panel/lib/scgi.rb +74 -21
- data/src/admin_panel/lib/yaml_writer.rb +51 -17
- data/src/admin_panel/public/javascripts/application.js +20 -1
- data/src/head/wr_access_log.c +2 -2
- data/src/head/wr_application.c +294 -236
- data/src/head/wr_application.h +8 -8
- data/src/head/wr_configurator.c +451 -517
- data/src/head/wr_configurator.h +10 -115
- data/src/head/wr_connection.c +26 -25
- data/src/head/wr_connection.h +2 -3
- data/src/head/wr_controller.c +110 -93
- data/src/head/wr_controller.h +6 -6
- data/src/head/wr_main.c +31 -24
- data/src/head/wr_request.c +70 -93
- data/src/head/wr_request.h +0 -4
- data/src/head/wr_resolver.c +21 -15
- data/src/head/wr_resolver.h +2 -2
- data/src/head/wr_server.c +36 -26
- data/src/head/wr_server.h +5 -5
- data/src/head/wr_worker.c +551 -512
- data/src/head/wr_worker.h +33 -20
- data/src/helper/wr_config.c +316 -0
- data/src/helper/wr_config.h +235 -0
- data/src/helper/wr_helper.h +1 -5
- data/src/helper/wr_logger.c +4 -4
- data/src/helper/wr_scgi.c +3 -4
- data/src/helper/wr_scgi.h +2 -0
- data/src/helper/wr_string.h +2 -2
- data/src/helper/wr_util.c +3 -1
- data/src/helper/wr_util.h +0 -0
- data/src/helper/wr_yaml_parser.c +30 -0
- data/src/helper/wr_yaml_parser.h +1 -0
- data/src/ruby_lib/exception_tracker/instrumentation/action_controller.rb +2 -1
- data/src/ruby_lib/mailer/smtpmail.rb +7 -4
- data/src/ruby_lib/profiler/instrumentation/action_controller.rb +2 -1
- data/src/ruby_lib/profiler/instrumentation/active_record.rb +3 -0
- data/src/ruby_lib/rack/adapter/rails.rb +14 -7
- data/src/ruby_lib/ruby_interface/client.rb +1 -1
- data/src/ruby_lib/ruby_interface/version.rb +2 -2
- data/src/ruby_lib/webroar_app_loader.rb +4 -2
- data/src/worker/wkr_controller.c +200 -140
- data/src/worker/wkr_http.c +14 -28
- data/src/worker/wkr_http.h +4 -4
- data/src/worker/wkr_http_request.c +12 -11
- data/src/worker/wkr_http_request.h +7 -8
- data/src/worker/wkr_http_response.c +10 -14
- data/src/worker/wkr_http_response.h +0 -1
- data/src/worker/wkr_main.c +74 -140
- data/src/worker/wkr_static.c +295 -108
- data/src/worker/wkr_static.h +20 -7
- data/src/worker/worker.c +245 -70
- data/src/worker/worker.h +46 -34
- data/tasks/compile.rake +128 -175
- data/tasks/test.rake +345 -469
- data/test/spec/webroar_command_spec.rb +23 -0
- metadata +173 -43
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/README +0 -34
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/Rakefile +0 -13
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/init.rb +0 -5
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/action_mailer_tls.rb +0 -16
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/smtp_tls.rb +0 -123
- data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/test/tls_test.rb +0 -42
- data/src/head/wr_config.h +0 -165
- data/src/ruby_lib/mailer/action_mailer_tls.rb +0 -16
- data/src/ruby_lib/mailer/smtp_tls.rb +0 -123
data/src/head/wr_worker.c
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
|
2
|
+
#include "wr_worker.h"
|
3
|
+
|
1
4
|
/* WebROaR - Ruby Application Server - http://webroar.in/
|
2
5
|
* Copyright (C) 2009 Goonj LLC
|
3
6
|
*
|
@@ -17,31 +20,177 @@
|
|
17
20
|
* along with WebROaR. If not, see <http://www.gnu.org/licenses/>.
|
18
21
|
*/
|
19
22
|
#include <wr_request.h>
|
20
|
-
#include <wr_access_log.h>
|
21
23
|
#include <unistd.h>
|
22
24
|
#include <errno.h>
|
23
25
|
#include <fcntl.h>
|
24
26
|
#include <sys/un.h>
|
25
27
|
|
28
|
+
extern config_t *Config;
|
29
|
+
|
26
30
|
/** Private functions */
|
27
|
-
|
31
|
+
void wr_req_hearer_write_cb(struct ev_loop*, struct ev_io*, int);
|
32
|
+
void wr_wrk_allocate(wr_wkr_t* worker);
|
33
|
+
void wr_wkr_ping_send(wr_wkr_t *worker);
|
34
|
+
|
35
|
+
void wr_wkr_state_machine(wr_wkr_t *worker, wr_wkr_action_t action){
|
36
|
+
|
37
|
+
switch(action){
|
38
|
+
case WKR_ACTION_ERROR:
|
39
|
+
case WKR_ACTION_REMOVE:
|
40
|
+
worker->state = WKR_STATE_ERROR;
|
41
|
+
wr_wkr_free(worker);
|
42
|
+
return;
|
43
|
+
}
|
28
44
|
|
29
|
-
|
30
|
-
|
45
|
+
switch(worker->state){
|
46
|
+
// Connecting
|
47
|
+
case WKR_STATE_CONNECTING:
|
48
|
+
switch(action){
|
49
|
+
case WKR_ACTION_ADD:
|
50
|
+
worker->state = WKR_STATE_INACTIVE;
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
break;
|
54
|
+
|
55
|
+
// Active
|
56
|
+
case WKR_STATE_ACTIVE:
|
57
|
+
switch(action){
|
58
|
+
case WKR_ACTION_REQ_PROCESSED:
|
59
|
+
worker->state = WKR_STATE_INACTIVE;
|
60
|
+
wr_wrk_allocate(worker);
|
61
|
+
return;
|
62
|
+
case WKR_ACTION_PING_TIMEOUT:
|
63
|
+
if(worker->trials_done < Config->Server.Worker.ping_trials) {
|
64
|
+
worker->state = WKR_STATE_PINGING;
|
65
|
+
wr_wkr_ping_send(worker);
|
66
|
+
} else {
|
67
|
+
worker->state = WKR_STATE_HANGUP;
|
68
|
+
wr_app_t *app = worker->app;
|
69
|
+
wr_wkr_free(worker);
|
70
|
+
wr_app_wkr_balance(app);
|
71
|
+
}
|
72
|
+
return;
|
73
|
+
}
|
74
|
+
break;
|
75
|
+
|
76
|
+
// Inactive
|
77
|
+
case WKR_STATE_INACTIVE:
|
78
|
+
switch(action){
|
79
|
+
case WKR_ACTION_REQ_PROCESSING:
|
80
|
+
worker->state = WKR_STATE_ACTIVE;
|
81
|
+
return;
|
82
|
+
}
|
83
|
+
break;
|
84
|
+
|
85
|
+
// Pinging
|
86
|
+
case WKR_STATE_PINGING:
|
87
|
+
switch(action){
|
88
|
+
case WKR_ACTION_REQ_PROCESSED:
|
89
|
+
worker->state = WKR_STATE_INACTIVE;
|
90
|
+
wr_wrk_allocate(worker);
|
91
|
+
return;
|
92
|
+
case WKR_ACTION_REQ_PROCESSING:
|
93
|
+
worker->state = WKR_STATE_ACTIVE;
|
94
|
+
return;
|
95
|
+
case WKR_ACTION_PING_REPLAY:
|
96
|
+
worker->state = WKR_STATE_ACTIVE;
|
97
|
+
ev_timer_stop(worker->loop, &worker->t_wait);
|
98
|
+
worker->t_wait.repeat = Config->Server.Worker.idle_time;
|
99
|
+
ev_timer_again(worker->loop, &worker->t_wait);
|
100
|
+
return;
|
101
|
+
case WKR_ACTION_PING_TIMEOUT:
|
102
|
+
if(worker->trials_done < Config->Server.Worker.ping_trials) {
|
103
|
+
worker->state = WKR_STATE_PINGING;
|
104
|
+
wr_wkr_ping_send(worker);
|
105
|
+
} else {
|
106
|
+
worker->state = WKR_STATE_HANGUP;
|
107
|
+
wr_app_t *app = worker->app;
|
108
|
+
wr_wkr_free(worker);
|
109
|
+
wr_app_wkr_balance(app);
|
110
|
+
}
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
|
115
|
+
// Expired
|
116
|
+
case WKR_STATE_EXPIRED:
|
117
|
+
switch(action){
|
118
|
+
case WKR_ACTION_REQ_PROCESSED:
|
119
|
+
case WKR_ACTION_PING_TIMEOUT:
|
120
|
+
worker->state = WKR_STATE_DISCONNECTING;
|
121
|
+
wr_wkr_free(worker);
|
122
|
+
return;
|
123
|
+
}
|
124
|
+
break;
|
125
|
+
|
126
|
+
// Acknowledge Error message
|
127
|
+
case WKR_STATE_ERROR_ACK:
|
128
|
+
break;
|
129
|
+
|
130
|
+
case WKR_STATE_ERROR: // Error
|
131
|
+
case WKR_STATE_TIMEDOUT: // Timedout
|
132
|
+
case WKR_STATE_HANGUP: // Hangup
|
133
|
+
case WKR_STATE_DISCONNECTING: // Disconnecting
|
134
|
+
wr_wkr_free(worker);
|
135
|
+
break;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
void wr_wkr_ping_send(wr_wkr_t *worker){
|
140
|
+
worker->trials_done++;
|
141
|
+
LOG_INFO("Worker %d with pid %u ping for trial no %d",
|
142
|
+
worker->id, worker->pid, worker->trials_done);
|
143
|
+
worker->t_wait.repeat = Config->Server.Worker.ping_timeout;
|
144
|
+
|
145
|
+
scgi_t *scgi = scgi_new();
|
146
|
+
scgi_header_add(scgi, "COMPONENT", strlen("COMPONENT"), "WORKER", strlen("WORKER"));
|
147
|
+
scgi_header_add(scgi, "METHOD", strlen("METHOD"), "PING", strlen("PING"));
|
148
|
+
if(scgi_build(scgi)!=0) {
|
149
|
+
LOG_ERROR(WARN,"SCGI request build failed.");
|
150
|
+
}
|
151
|
+
worker->ctl->scgi = scgi;
|
152
|
+
ev_io_start(worker->loop, &worker->ctl->w_write);
|
153
|
+
//ev_timer_again(loop, &worker->t_ping_wait);
|
154
|
+
ev_timer_again(worker->loop, &worker->t_wait);
|
155
|
+
}
|
156
|
+
|
157
|
+
void wr_wait_watcher_start(wr_wkr_t *worker) {
|
158
|
+
wr_wkr_state_machine(worker, WKR_ACTION_REQ_PROCESSING);
|
159
|
+
worker->trials_done = 0;
|
31
160
|
// Clear WR_WKR_PING_SENT, WR_WKR_PING_REPLIED and WR_WKR_HANG state.
|
32
|
-
|
33
|
-
|
34
|
-
|
161
|
+
if(Config->Server.Worker.idle_time > 0){
|
162
|
+
worker->t_wait.repeat = Config->Server.Worker.idle_time;
|
163
|
+
ev_timer_again(worker->loop, &worker->t_wait);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
void wr_wkr_req_processing(wr_wkr_t* worker, wr_req_t* req){
|
168
|
+
LOG_DEBUG(4,"Allocate worker %d to req id %d", worker->id , req->id);
|
169
|
+
req->wkr = worker;
|
170
|
+
req->using_wkr = TRUE;
|
171
|
+
|
172
|
+
worker->req = req;
|
173
|
+
worker->watcher.data = req;
|
174
|
+
|
175
|
+
wr_wkr_state_machine(worker, WKR_ACTION_REQ_PROCESSING);
|
176
|
+
|
177
|
+
ev_io_init(&worker->watcher, wr_req_hearer_write_cb, worker->fd, EV_WRITE);
|
178
|
+
ev_io_start(worker->loop,&worker->watcher);
|
35
179
|
}
|
36
180
|
|
37
181
|
/** Check for pending request to process */
|
38
|
-
|
182
|
+
void wr_wrk_allocate(wr_wkr_t* worker) {
|
39
183
|
LOG_FUNCTION
|
40
184
|
wr_req_t* req;
|
41
185
|
wr_app_t* app = worker->app;
|
42
186
|
wr_svr_t* server = app->svr;
|
43
187
|
int retval;
|
188
|
+
|
44
189
|
//do we need high load ratio check here?
|
190
|
+
if(worker->app){
|
191
|
+
wr_app_chk_load_to_remove_wkr(worker->app);
|
192
|
+
}
|
193
|
+
|
45
194
|
if(app && app->q_messages->q_count > 0) {
|
46
195
|
//There is pending request
|
47
196
|
WR_QUEUE_FETCH(app->q_messages, req) ;
|
@@ -49,47 +198,30 @@ static inline void wr_wrk_allocate(wr_wkr_t* worker) {
|
|
49
198
|
if(req == NULL) {
|
50
199
|
WR_QUEUE_INSERT(app->q_free_workers, worker, retval) ;
|
51
200
|
} else {
|
52
|
-
|
53
|
-
req->wkr = worker;
|
54
|
-
worker->req = req;
|
55
|
-
worker->watcher.data = req;
|
56
|
-
ev_io_init(&worker->watcher, wr_req_hearer_write_cb, worker->fd, EV_WRITE);
|
57
|
-
ev_io_start(server->ebb_svr.loop,&worker->watcher);
|
201
|
+
wr_wkr_req_processing(worker, req);
|
58
202
|
}
|
59
203
|
} else if(app) {
|
60
204
|
//No any pending request. Add Worker to free worker list
|
61
205
|
LOG_DEBUG(4,"Message queue is empty");
|
62
206
|
WR_QUEUE_INSERT(app->q_free_workers, worker, retval) ;
|
63
207
|
} else {
|
64
|
-
|
65
|
-
LOG_ERROR(SEVERE,"wr_wrk_allocate: Remove worker with pid %d.", worker->pid);
|
66
|
-
wr_wkr_free(worker);
|
208
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
67
209
|
}
|
68
210
|
}
|
69
211
|
|
70
|
-
|
71
|
-
|
72
|
-
wr_wkr_t* worker = req->wkr;
|
73
|
-
|
74
|
-
LOG_DEBUG(DEBUG,"req %d", req->id);
|
75
|
-
wr_req_free(req);
|
212
|
+
void wr_wkr_req_processed(wr_wkr_t *worker){
|
213
|
+
wr_req_free(worker->req);
|
76
214
|
worker->req = NULL;
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
// Check worker status before allication
|
82
|
-
if(worker->state & WR_WKR_ACTIVE) {
|
83
|
-
wr_wrk_allocate(worker);
|
84
|
-
} else {
|
85
|
-
// Remove worker if it is not active
|
86
|
-
LOG_ERROR(SEVERE,"wr_wkr_release: Remove worker with pid %d", worker->pid);
|
87
|
-
wr_wkr_remove(worker, 0);
|
215
|
+
LOG_DEBUG(DEBUG,"Idle watcher stopped for worker %d", worker->id);
|
216
|
+
// worker is done with current Request
|
217
|
+
if(Config->Server.Worker.idle_time > 0){
|
218
|
+
ev_timer_stop(worker->loop,&worker->t_wait);
|
88
219
|
}
|
220
|
+
wr_wkr_state_machine(worker, WKR_ACTION_REQ_PROCESSED);
|
89
221
|
}
|
90
222
|
|
91
223
|
/** Reads streamed response from Worker */
|
92
|
-
|
224
|
+
void wr_resp_read_cb(struct ev_loop *loop,struct ev_io *w, int revents) {
|
93
225
|
LOG_FUNCTION
|
94
226
|
wr_req_t *req = (wr_req_t*) w->data;
|
95
227
|
wr_wkr_t *worker = req->wkr;
|
@@ -108,10 +240,8 @@ static void wr_resp_read_cb(struct ev_loop *loop,struct ev_io *w, int revents) {
|
|
108
240
|
wr_min(WR_RESP_BUF_SIZE,req->resp_buf_len - req->bytes_received),
|
109
241
|
0);
|
110
242
|
if(read <= 0) {
|
111
|
-
ev_io_stop(loop,w);
|
112
243
|
LOG_ERROR(WARN,"Error reading response:%s",strerror(errno));
|
113
|
-
worker
|
114
|
-
wr_ctl_free(worker->ctl);
|
244
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
115
245
|
return;
|
116
246
|
}
|
117
247
|
|
@@ -128,22 +258,57 @@ static void wr_resp_read_cb(struct ev_loop *loop,struct ev_io *w, int revents) {
|
|
128
258
|
//if(req->bytes_received == req->resp_buf_len) {
|
129
259
|
if(req->bytes_received >= req->resp_buf_len) {
|
130
260
|
ev_io_stop(loop, w);
|
131
|
-
|
132
|
-
// worker is done with current Request
|
133
|
-
worker->req = NULL;
|
134
|
-
req->using_wkr = FALSE;
|
135
|
-
|
136
|
-
worker->state &= (~224);
|
137
|
-
ev_timer_stop(worker->loop,&worker->t_wait);
|
138
|
-
// Close Request once response read
|
139
|
-
wr_wkr_release(req);
|
261
|
+
wr_wkr_req_processed(worker);
|
140
262
|
} else {
|
141
263
|
wr_wait_watcher_start(worker);
|
142
264
|
}
|
143
265
|
}
|
144
266
|
|
267
|
+
int wr_wkr_set_req(wr_wkr_t *worker, wr_req_t* req, scgi_t* scgi){
|
268
|
+
const char *value = scgi_header_value_get(scgi, SCGI_CONTENT_LENGTH);
|
269
|
+
|
270
|
+
// Set response length
|
271
|
+
req->resp_buf_len = (value ? atoi(value) : 0);
|
272
|
+
|
273
|
+
// Set rsponse code
|
274
|
+
value = scgi_header_value_get(scgi, Config->Request.Header.resp_code.str);
|
275
|
+
req->resp_code = (value ? atoi(value) : 0);
|
276
|
+
|
277
|
+
// Set content length
|
278
|
+
value = scgi_header_value_get(scgi, Config->Request.Header.resp_content_len.str);
|
279
|
+
req->resp_body_len = (value ? atoi(value) : 0);
|
280
|
+
|
281
|
+
LOG_DEBUG(DEBUG,"resp_code = %d, content len = %d, resp len = %d",
|
282
|
+
req->resp_code,
|
283
|
+
req->resp_body_len,
|
284
|
+
req->resp_buf_len);
|
285
|
+
// Response length should be greater than 0
|
286
|
+
if(req->resp_buf_len == 0) {
|
287
|
+
//TODO: Render 500 Internal Error, close Request, allocate worker to next Request
|
288
|
+
LOG_ERROR(WARN,"Got response len 0");
|
289
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
290
|
+
return FALSE;
|
291
|
+
}
|
292
|
+
|
293
|
+
if(!req->conn_err && req->app && Config->Server.flag & SERVER_ACCESS_LOG) {
|
294
|
+
wr_access_log(req);
|
295
|
+
}
|
296
|
+
|
297
|
+
scgi_free(req->scgi);
|
298
|
+
req->scgi = NULL;
|
299
|
+
|
300
|
+
req->bytes_received = scgi->body_length;
|
301
|
+
LOG_DEBUG(DEBUG,"wr_resp_len_read_cb() bytes read = %d", req->bytes_received);
|
302
|
+
if(req->bytes_received > 0 && !req->conn_err) {
|
303
|
+
wr_conn_resp_body_add(req->conn, scgi->body, scgi->body_length);
|
304
|
+
}
|
305
|
+
|
306
|
+
scgi_free(scgi);
|
307
|
+
return TRUE;
|
308
|
+
}
|
309
|
+
|
145
310
|
/** Reads the response from worker, deserialize it, render it to the Request. */
|
146
|
-
|
311
|
+
void wr_resp_len_read_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
|
147
312
|
LOG_FUNCTION
|
148
313
|
wr_req_t* req = (wr_req_t*) w->data;
|
149
314
|
wr_wkr_t *worker = req->wkr;
|
@@ -162,8 +327,7 @@ static void wr_resp_len_read_cb(struct ev_loop *loop, struct ev_io *w, int reven
|
|
162
327
|
if(read <= 0) {
|
163
328
|
ev_io_stop(loop,w);
|
164
329
|
LOG_ERROR(WARN,"Error reading response:%s",strerror(errno));
|
165
|
-
worker
|
166
|
-
wr_ctl_free(worker->ctl);
|
330
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
167
331
|
return;
|
168
332
|
}
|
169
333
|
|
@@ -174,82 +338,46 @@ static void wr_resp_len_read_cb(struct ev_loop *loop, struct ev_io *w, int reven
|
|
174
338
|
|
175
339
|
scgi_t* scgi = scgi_parse(req->resp_buf, req->bytes_received);
|
176
340
|
|
177
|
-
if(scgi)
|
178
|
-
|
179
|
-
const char *value = scgi_header_value_get(scgi, SCGI_CONTENT_LENGTH);
|
180
|
-
// Set response length
|
181
|
-
if(value)
|
182
|
-
req->resp_buf_len = atoi(value);
|
183
|
-
else
|
184
|
-
req->resp_buf_len = 0;
|
185
|
-
|
186
|
-
// Set rsponse code
|
187
|
-
value = scgi_header_value_get(scgi, RESP_CODE);
|
188
|
-
if(value)
|
189
|
-
req->resp_code = atoi(value);
|
190
|
-
else
|
191
|
-
req->resp_code = 0;
|
192
|
-
|
193
|
-
// Set content length
|
194
|
-
value = scgi_header_value_get(scgi, RESP_CONTENT_LENGTH);
|
195
|
-
if(value)
|
196
|
-
req->resp_body_len = atoi(value);
|
197
|
-
else
|
198
|
-
req->resp_body_len = 0;
|
199
|
-
|
200
|
-
LOG_DEBUG(DEBUG,"resp_code = %d, content len = %d, resp len = %d",
|
201
|
-
req->resp_code,
|
202
|
-
req->resp_body_len,
|
203
|
-
req->resp_buf_len);
|
204
|
-
// Response length should be greater than 0
|
205
|
-
if(req->resp_buf_len == 0) {
|
206
|
-
//TODO: Render 500 Internal Error, close Request, allocate worker to next Request
|
207
|
-
LOG_ERROR(WARN,"Got response len 0");
|
208
|
-
ev_io_stop(loop,w);
|
209
|
-
worker->state += (WR_WKR_ERROR + WR_WKR_HANG);
|
210
|
-
wr_ctl_free(worker->ctl);
|
211
|
-
return;
|
212
|
-
}
|
213
|
-
|
214
|
-
if(!req->conn_err && req->app && req->app->svr->conf->server->flag & WR_SVR_ACCESS_LOG) {
|
215
|
-
wr_access_log(req);
|
216
|
-
}
|
341
|
+
if(scgi == NULL) return;
|
342
|
+
ev_io_stop(loop,w);
|
217
343
|
|
218
|
-
|
219
|
-
|
344
|
+
if(wr_wkr_set_req(worker, req, scgi) == FALSE) return;
|
345
|
+
|
346
|
+
// Check for response length
|
347
|
+
if(req->resp_buf_len == req->bytes_received) {
|
348
|
+
wr_wkr_req_processed(worker);
|
349
|
+
} else {
|
350
|
+
LOG_DEBUG(DEBUG,"wr_resp_len_read_cb() Request %d, read %d/%d",
|
351
|
+
req->id,
|
352
|
+
req->bytes_received,
|
353
|
+
req->resp_buf_len);
|
354
|
+
ev_io_init(w,wr_resp_read_cb, w->fd,EV_READ);
|
355
|
+
ev_io_start(loop,w);
|
356
|
+
wr_wait_watcher_start(worker);
|
357
|
+
}
|
358
|
+
}
|
220
359
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
wr_conn_resp_body_add(req->conn, scgi->body, scgi->body_length);
|
225
|
-
}
|
360
|
+
void wr_wkr_req_sent(wr_wkr_t *worker){
|
361
|
+
ev_io_stop(worker->loop, &worker->watcher);
|
362
|
+
wr_req_t * req = worker->req;
|
226
363
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
// worker is done with current Request
|
233
|
-
worker->req = NULL;
|
234
|
-
req->using_wkr = FALSE;
|
235
|
-
worker->state &= (~224);
|
236
|
-
ev_timer_stop(worker->loop,&worker->t_wait);
|
237
|
-
// Close Request once complete response read
|
238
|
-
wr_wkr_release(req);
|
239
|
-
} else {
|
240
|
-
LOG_DEBUG(DEBUG,"wr_resp_len_read_cb() Request %d, read %d/%d",
|
241
|
-
req->id,
|
242
|
-
req->bytes_received,
|
243
|
-
req->resp_buf_len);
|
244
|
-
ev_io_init(w,wr_resp_read_cb, w->fd,EV_READ);
|
245
|
-
ev_io_start(loop,w);
|
246
|
-
wr_wait_watcher_start(worker);
|
247
|
-
}
|
364
|
+
if(req->upload_file) {
|
365
|
+
fclose(req->upload_file);
|
366
|
+
remove(req->upload_file_name->str);
|
367
|
+
wr_buffer_free(req->upload_file_name);
|
368
|
+
req->upload_file = NULL;
|
248
369
|
}
|
370
|
+
|
371
|
+
ev_io_init(&worker->watcher, wr_resp_len_read_cb, worker->fd, EV_READ);
|
372
|
+
ev_io_start(worker->loop,&worker->watcher);
|
373
|
+
//We are waiting for response from worker, start idle watcher for it
|
374
|
+
LOG_DEBUG(DEBUG,"Idle watcher started for worker %d", worker->id);
|
375
|
+
wr_wait_watcher_start(worker);
|
249
376
|
}
|
250
377
|
|
251
378
|
/** Send SCGI formatted request stream to Worker*/
|
252
|
-
|
379
|
+
/* Send request body to worker */
|
380
|
+
void wr_req_body_write_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
|
253
381
|
LOG_FUNCTION
|
254
382
|
wr_req_t *req = (wr_req_t*) w->data;
|
255
383
|
wr_wkr_t *worker = req->wkr;
|
@@ -259,22 +387,20 @@ static void wr_req_body_write_cb(struct ev_loop *loop, struct ev_io *w, int reve
|
|
259
387
|
return;
|
260
388
|
|
261
389
|
if(req->upload_file) {
|
262
|
-
char buffer[
|
390
|
+
char buffer[Config->Request.max_body_size];
|
263
391
|
ssize_t read;
|
264
392
|
int rv=fseek(req->upload_file,req->bytes_sent,SEEK_SET);
|
265
393
|
if(rv<0) {
|
266
394
|
LOG_ERROR(WARN,"Error reading file:%s",strerror(errno));
|
267
395
|
return;
|
268
396
|
}
|
269
|
-
read = fread(buffer,1,
|
397
|
+
read = fread(buffer,1,Config->Request.max_body_size,req->upload_file);
|
270
398
|
sent = send(w->fd, buffer, read, 0);
|
271
399
|
}
|
272
400
|
|
273
401
|
if(sent <= 0) {
|
274
|
-
ev_io_stop(loop,w);
|
275
402
|
LOG_ERROR(WARN,"Error sending request:%s",strerror(errno));
|
276
|
-
worker
|
277
|
-
wr_ctl_free(worker->ctl);
|
403
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
278
404
|
return;
|
279
405
|
}
|
280
406
|
|
@@ -282,31 +408,14 @@ static void wr_req_body_write_cb(struct ev_loop *loop, struct ev_io *w, int reve
|
|
282
408
|
LOG_DEBUG(DEBUG,"Request %d sent %d/%d", req->id, req->bytes_sent, req->ebb_req->content_length);
|
283
409
|
|
284
410
|
if(req->ebb_req->content_length == req->bytes_sent) {
|
285
|
-
|
286
|
-
|
287
|
-
LOG_DEBUG(DEBUG,"Sent request body for Request %d to worker %d", req->id, worker->id);
|
288
|
-
if(req->upload_file) {
|
289
|
-
fclose(req->upload_file);
|
290
|
-
remove(req->upload_file_name->str);
|
291
|
-
wr_buffer_free(req->upload_file_name);
|
292
|
-
req->upload_file = NULL;
|
293
|
-
}
|
294
|
-
|
295
|
-
scgi_free(req->scgi);
|
296
|
-
req->scgi = NULL;
|
297
|
-
|
298
|
-
ev_io_init(w,wr_resp_len_read_cb,w->fd,EV_READ);
|
299
|
-
ev_io_start(loop,w);
|
300
|
-
//We are waiting for response from worker, start idle watcher for it
|
301
|
-
LOG_DEBUG(DEBUG,"Idle watcher started for worker %d", worker->id);
|
302
|
-
wr_wait_watcher_start(worker);
|
303
|
-
//wr_wkr_idle_watch_reset(worker);
|
411
|
+
wr_wkr_req_sent(worker);
|
304
412
|
}
|
305
413
|
}
|
306
414
|
|
307
415
|
/** Start writing SCGI formatted request to Worker */
|
416
|
+
/* Send request headers to worker */
|
308
417
|
//whenever there is a pending request for processing and worker's fd is ready for write, it will dump serialized data to worker by this function
|
309
|
-
|
418
|
+
void wr_req_hearer_write_cb(struct ev_loop *loop, struct ev_io *w, int revents) {
|
310
419
|
LOG_FUNCTION
|
311
420
|
wr_req_t* req = (wr_req_t*) w->data;
|
312
421
|
wr_wkr_t *worker = req->wkr;
|
@@ -318,92 +427,64 @@ static void wr_req_hearer_write_cb(struct ev_loop *loop, struct ev_io *w, int re
|
|
318
427
|
if(scgi_send(req->scgi, w->fd) <= 0){
|
319
428
|
ev_io_stop(loop,w);
|
320
429
|
LOG_ERROR(WARN,"Error sending request:%s",strerror(errno));
|
321
|
-
worker
|
322
|
-
wr_ctl_free(worker->ctl);
|
323
|
-
return;
|
430
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
324
431
|
}
|
325
432
|
LOG_DEBUG(DEBUG,"Request %d write %d/%d", req->id, req->scgi->bytes_sent,
|
326
433
|
req->scgi->length);
|
327
434
|
if(req->scgi->bytes_sent == req->scgi->length) {
|
328
|
-
|
435
|
+
|
329
436
|
LOG_DEBUG(DEBUG,"Sent request header for Request %d to worker %d", req->id, worker->id);
|
330
437
|
req->bytes_sent = 0;
|
331
438
|
|
332
439
|
if(req->upload_file) {
|
440
|
+
ev_io_stop(loop,w);
|
333
441
|
ev_io_init(w,wr_req_body_write_cb,w->fd,EV_WRITE);
|
442
|
+
ev_io_start(loop,w);
|
334
443
|
} else {
|
335
|
-
|
336
|
-
//We are waiting for response from worker, start idle watcher for it
|
337
|
-
LOG_DEBUG(DEBUG,"Idle watcher started for worker %d", worker->id);
|
338
|
-
//wr_wkr_idle_watch_reset(worker);
|
339
|
-
wr_wait_watcher_start(worker);
|
444
|
+
wr_wkr_req_sent(worker);
|
340
445
|
}
|
341
|
-
ev_io_start(loop,w);
|
342
446
|
}
|
343
447
|
}
|
344
448
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
static inline void wr_wkr_recreate(wr_wkr_t *worker) {
|
350
|
-
LOG_FUNCTION
|
351
|
-
wr_req_t *req = worker->req;
|
449
|
+
typedef struct {
|
450
|
+
char log_level[STR_SIZE32], controller_path[STR_SIZE32];
|
451
|
+
wr_str_t baseuri;
|
452
|
+
}wr_wkr_create_t;
|
352
453
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
worker->
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
worker->id, req->id, req->conn->id, req->req_uri.str);
|
362
|
-
wr_conn_err_resp(req->conn, WR_HTTP_STATUS_500);
|
363
|
-
}
|
364
|
-
wr_app_t *app = worker->app;
|
365
|
-
worker->state |= WR_WKR_ERROR;
|
366
|
-
wr_wkr_remove(worker, 0);
|
367
|
-
//create new worker if required
|
368
|
-
if(TOTAL_WORKER_COUNT(app) < app->conf->min_worker ||
|
369
|
-
app->q_messages->q_count > app->high_ratio) {
|
370
|
-
wr_app_wkr_add(app);
|
454
|
+
wr_wkr_create_t* wr_wkr_create_init(wr_svr_t *server, config_application_list_t *app_conf){
|
455
|
+
wr_wkr_create_t *worker = wr_malloc(wr_wkr_create_t);
|
456
|
+
|
457
|
+
wr_string_null(worker->baseuri);
|
458
|
+
if(app_conf->baseuri.str) {
|
459
|
+
wr_string_dump(worker->baseuri, app_conf->baseuri);
|
460
|
+
} else {
|
461
|
+
wr_string_new(worker->baseuri, "/", 1);
|
371
462
|
}
|
463
|
+
|
464
|
+
sprintf(worker->log_level, "%d", app_conf->log_level);
|
465
|
+
|
466
|
+
if(Config->Server.flag & SERVER_UDS_SUPPORT) {
|
467
|
+
strcpy(worker->controller_path, server->ctl->sock_path.str);
|
468
|
+
} else {
|
469
|
+
sprintf(worker->controller_path, "%d", server->ctl->port);
|
470
|
+
}
|
471
|
+
|
472
|
+
return worker;
|
372
473
|
}
|
373
474
|
|
374
475
|
/** This would get called when idel time watcher goes timeout */
|
375
|
-
|
476
|
+
void wr_wkr_wait_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
376
477
|
LOG_FUNCTION
|
377
478
|
wr_wkr_t *worker = (wr_wkr_t*)w->data;
|
378
|
-
|
479
|
+
|
379
480
|
//ev_timer_stop(loop, &worker->t_idle);
|
380
481
|
ev_timer_stop(loop, &worker->t_wait);
|
381
|
-
|
482
|
+
|
382
483
|
if(worker->app == NULL) {
|
383
484
|
LOG_INFO("wr_wkr_wait_cb: Worker removed with pid %d", worker->pid);
|
384
|
-
|
385
|
-
}
|
386
|
-
worker
|
387
|
-
LOG_INFO("Worker %d with pid %u ping for trial no %d",
|
388
|
-
worker->id, worker->pid, worker->trials_done);
|
389
|
-
worker->t_wait.repeat = WR_PING_WAIT_TIME;
|
390
|
-
worker->state |= (WR_WKR_HANG | WR_WKR_PING_SENT);
|
391
|
-
if(worker->state & WR_WKR_PING_REPLIED) {
|
392
|
-
worker->state ^= WR_WKR_PING_REPLIED;
|
393
|
-
}
|
394
|
-
scgi_t *scgi = scgi_new();
|
395
|
-
scgi_header_add(scgi, "COMPONENT", strlen("COMPONENT"), "WORKER", strlen("WORKER"));
|
396
|
-
scgi_header_add(scgi, "METHOD", strlen("METHOD"), "PING", strlen("PING"));
|
397
|
-
if(scgi_build(scgi)!=0) {
|
398
|
-
LOG_ERROR(WARN,"SCGI request build failed.");
|
399
|
-
}
|
400
|
-
worker->ctl->scgi = scgi;
|
401
|
-
ev_io_start(loop, &worker->ctl->w_write);
|
402
|
-
//ev_timer_again(loop, &worker->t_ping_wait);
|
403
|
-
ev_timer_again(loop, &worker->t_wait);
|
404
|
-
} else {
|
405
|
-
//render 500 response to Request, kill the worker
|
406
|
-
wr_wkr_recreate(worker);
|
485
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ERROR);
|
486
|
+
}else{
|
487
|
+
wr_wkr_state_machine(worker, WKR_ACTION_PING_TIMEOUT);
|
407
488
|
}
|
408
489
|
}
|
409
490
|
|
@@ -413,7 +494,7 @@ wr_wkr_t* wr_wkr_new(wr_ctl_t *ctl) {
|
|
413
494
|
wr_wkr_t* worker = wr_malloc(wr_wkr_t);
|
414
495
|
if(worker == NULL)
|
415
496
|
return NULL;
|
416
|
-
|
497
|
+
|
417
498
|
// Set default value
|
418
499
|
worker->ctl = ctl;
|
419
500
|
worker->req = NULL;
|
@@ -422,146 +503,199 @@ wr_wkr_t* wr_wkr_new(wr_ctl_t *ctl) {
|
|
422
503
|
worker->pid = 0;
|
423
504
|
worker->app = NULL;
|
424
505
|
worker->watcher.active = 0;
|
425
|
-
worker->state =
|
506
|
+
worker->state = WKR_STATE_CONNECTING;
|
426
507
|
worker->trials_done = 0;
|
427
508
|
worker->t_wait.data = worker;
|
428
509
|
worker->loop = ctl->svr->ebb_svr.loop;
|
429
|
-
|
510
|
+
if(Config->Server.Worker.idle_time > 0){
|
511
|
+
ev_timer_init(&worker->t_wait, wr_wkr_wait_cb, 0., Config->Server.Worker.idle_time);
|
512
|
+
}
|
430
513
|
return worker;
|
431
514
|
}
|
432
515
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
if(ev_is_active(&worker->t_wait))
|
441
|
-
ev_timer_stop(worker->loop,&worker->t_wait);
|
442
|
-
|
443
|
-
//Kill the process
|
444
|
-
if(!(worker->state & WR_WKR_ERROR) &&
|
445
|
-
!(worker->state & WR_WKR_DISCONNECT) &&
|
446
|
-
worker->req == NULL &&
|
447
|
-
worker->pid > 0) {
|
448
|
-
LOG_DEBUG(DEBUG,"Stopping worker %d with pid %d...",worker->id, worker->pid);
|
449
|
-
LOG_INFO("Stopping worker %d with pid %d...",worker->id, worker->pid);
|
450
|
-
scgi_t* remove_req = scgi_new();
|
451
|
-
if(remove_req) {
|
452
|
-
scgi_header_add(remove_req, "METHOD", strlen("METHOD"), "REMOVE", strlen("REMOVE"));
|
453
|
-
scgi_build(remove_req);
|
454
|
-
//TODO: made it asynchronous
|
455
|
-
send(worker->ctl->fd, remove_req->header + remove_req->start_offset, remove_req->length, 0);
|
456
|
-
scgi_free(remove_req);
|
457
|
-
} else {
|
458
|
-
kill(worker->pid,SIGHUP);
|
516
|
+
int wr_wkr_check_uds(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg){
|
517
|
+
if(Config->Server.flag & SERVER_UDS_SUPPORT) {
|
518
|
+
if(strcmp(ctl_msg->msg.wkr.uds.str,"YES")!=0 ||
|
519
|
+
ctl_msg->msg.wkr.sock_path.str == NULL) {
|
520
|
+
scgi_body_add(ctl->scgi, "Invalid UDS, sock path and configuration.", strlen("Invalid UDS, sock path and configuration."));
|
521
|
+
LOG_ERROR(SEVERE,"connect_with_worker()Invalid UDS, sock path and configuration.");
|
522
|
+
return FALSE;
|
459
523
|
}
|
460
|
-
worker->pid = 0;
|
461
|
-
} else if(worker->state & WR_WKR_HANG) {
|
462
|
-
kill(worker->pid,SIGKILL);
|
463
|
-
LOG_DEBUG(DEBUG,"Worker %d with pid %d killed...",worker->id, worker->pid);
|
464
|
-
LOG_INFO("Worker %d with pid %d killed...",worker->id, worker->pid);
|
465
|
-
} else if(worker->req && worker->app) {
|
466
|
-
LOG_DEBUG(DEBUG,"Worker %d with pid %d. Waiting for worker...",worker->id, worker->pid);
|
467
|
-
LOG_INFO("Worker %d with pid %d. Waiting for worker...",worker->id, worker->pid);
|
468
|
-
worker->app = NULL;
|
469
|
-
worker->t_wait.repeat = WR_WKR_KILL_TIMEOUT;
|
470
|
-
ev_timer_again(worker->loop, &worker->t_wait);
|
471
|
-
return;
|
472
|
-
} else if(worker->req) {
|
473
|
-
LOG_DEBUG(DEBUG,"Worker %d with pid %d. Worker cannot served the request.",worker->id, worker->pid);
|
474
|
-
LOG_INFO("Worker %d with pid %d. Worker cannot served the request.",worker->id, worker->pid);
|
475
|
-
if(ev_is_active(&worker->watcher))
|
476
|
-
ev_io_stop(worker->loop,&worker->watcher);
|
477
|
-
worker->req->using_wkr = FALSE;
|
478
|
-
wr_conn_err_resp(worker->req->conn, WR_HTTP_STATUS_500);
|
479
|
-
kill(worker->pid,SIGKILL);
|
480
|
-
LOG_DEBUG(DEBUG,"Worker %d with pid %d killed...",worker->id, worker->pid);
|
481
524
|
} else {
|
482
|
-
|
483
|
-
|
484
|
-
|
525
|
+
if(strcmp(ctl_msg->msg.wkr.uds.str,"NO")!=0 ||
|
526
|
+
ctl_msg->msg.wkr.port.str == NULL) {
|
527
|
+
scgi_body_add(ctl->scgi, "Invalid UDS, sock path and configuration.", strlen("Invalid UDS, sock path and configuration."));
|
528
|
+
LOG_ERROR(SEVERE,"connect_with_worker()Invalid UDS, sock path and configuration.");
|
529
|
+
return FALSE;
|
530
|
+
}
|
485
531
|
}
|
532
|
+
return TRUE;
|
533
|
+
}
|
486
534
|
|
487
|
-
|
488
|
-
|
489
|
-
|
535
|
+
/** Connect to worker using UDS */
|
536
|
+
int wr_wkr_connect_uds(wr_wkr_t* worker, const wr_ctl_msg_t *ctl_msg){
|
537
|
+
struct sockaddr_un addr;
|
538
|
+
int len;
|
539
|
+
|
540
|
+
if((worker->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
541
|
+
perror("socket()");
|
542
|
+
LOG_ERROR(4,"socket() failed");
|
543
|
+
// Worker is not added, Reset the high load ratio
|
544
|
+
return FALSE;
|
545
|
+
}
|
546
|
+
|
547
|
+
LOG_DEBUG(3,"Socket successfully open for worker. File Descriptor is %d",worker->fd);
|
548
|
+
|
549
|
+
setsocketoption(worker->fd);
|
550
|
+
memset(&addr, 0, sizeof(addr));
|
551
|
+
|
552
|
+
addr.sun_family = AF_UNIX;
|
553
|
+
strcpy(addr.sun_path,ctl_msg->msg.wkr.sock_path.str);
|
554
|
+
len = sizeof(addr.sun_family) + strlen(addr.sun_path);
|
555
|
+
|
556
|
+
#ifdef __APPLE__
|
557
|
+
len++;
|
558
|
+
#endif
|
559
|
+
|
560
|
+
if(connect(worker->fd, (struct sockaddr *)&addr,len) == -1) {
|
561
|
+
perror("connect");
|
562
|
+
LOG_ERROR(4,"Unable to connect with worker at socket path %s. %s Closing it.",addr.sun_path, strerror(errno));
|
563
|
+
close_fd(worker->fd);
|
564
|
+
worker->fd=0;
|
565
|
+
// Worker is not added, Reset the high load ratio
|
566
|
+
return FALSE;
|
490
567
|
}
|
491
|
-
|
492
|
-
|
493
|
-
close(worker->fd);
|
494
|
-
|
495
|
-
free(worker);
|
568
|
+
|
569
|
+
return TRUE;
|
496
570
|
}
|
497
571
|
|
498
|
-
/**
|
499
|
-
int
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
572
|
+
/** Connect to worker using internet socket */
|
573
|
+
int wr_wkr_connect_inet(wr_wkr_t* worker, const wr_ctl_msg_t *ctl_msg){
|
574
|
+
struct sockaddr_in addr;
|
575
|
+
if ((worker->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
576
|
+
perror("socket()");
|
577
|
+
LOG_ERROR(4,"socket() failed for worker");
|
578
|
+
// Worker is not added, Reset the high load ratio
|
579
|
+
// return if not able to connect to the first worker
|
580
|
+
return FALSE;
|
581
|
+
}
|
582
|
+
LOG_DEBUG(3,"Socket successfully open for worker. File Descriptor is %d",worker->fd);
|
583
|
+
|
584
|
+
setsocketoption(worker->fd);
|
585
|
+
memset(&addr, 0, sizeof(addr));
|
586
|
+
|
587
|
+
addr.sin_family = AF_INET;
|
588
|
+
addr.sin_port = htons(atoi(ctl_msg->msg.wkr.port.str));
|
589
|
+
addr.sin_addr.s_addr =inet_addr("127.0.0.1");
|
590
|
+
|
591
|
+
if(connect(worker->fd, (struct sockaddr *)&addr,sizeof addr) == -1) {
|
592
|
+
perror("connect");
|
593
|
+
LOG_ERROR(4,"Unable to connect with worker at port %s. %s Closing it.",ctl_msg->msg.wkr.port.str, strerror(errno));
|
594
|
+
close_fd(worker->fd);
|
595
|
+
worker->fd=0;
|
596
|
+
return FALSE;
|
512
597
|
}
|
598
|
+
|
599
|
+
return TRUE;
|
600
|
+
}
|
513
601
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
wr_queue_remove(app->q_free_workers, worker);
|
520
|
-
}
|
521
|
-
wr_wkr_free(worker);
|
522
|
-
return 0;
|
523
|
-
} else if(app == NULL) {
|
524
|
-
wr_wkr_free(worker);
|
525
|
-
return 0;
|
602
|
+
int wr_wkr_set_ratio(wr_ctl_t *ctl, wr_wkr_t* worker){
|
603
|
+
if(setnonblock(worker->fd) < 0) {
|
604
|
+
LOG_ERROR(SEVERE,"Setting worker_fd non-block failed:%s",strerror(errno));
|
605
|
+
close_fd(worker->fd);
|
606
|
+
return FALSE;
|
526
607
|
}
|
527
|
-
|
528
|
-
|
608
|
+
|
609
|
+
if(wr_queue_insert(worker->app->q_workers, worker) < 0){
|
610
|
+
LOG_ERROR(WARN,"Worker queue is full.");
|
611
|
+
return FALSE;
|
612
|
+
}
|
613
|
+
|
614
|
+
//Setting low load ratio for application, refer "wr_worker_remove_cb" in wr_server.c for details.
|
615
|
+
worker->app->low_ratio = worker->app->q_workers->q_count * Config->Application.min_req_ratio;
|
616
|
+
ctl->wkr = worker;
|
617
|
+
LOG_DEBUG(DEBUG,"Added Worker %d",worker->id);
|
618
|
+
|
619
|
+
wr_wkr_state_machine(worker, WKR_ACTION_ADD);
|
620
|
+
|
621
|
+
ev_io_set(&worker->watcher,worker->fd,EV_READ);
|
622
|
+
return TRUE;
|
529
623
|
}
|
530
624
|
|
531
|
-
/**
|
532
|
-
int
|
625
|
+
/** Handle connect request from Worker */
|
626
|
+
int wr_wkr_connect(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
533
627
|
LOG_FUNCTION
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
628
|
+
wr_svr_t* server = ctl->svr;
|
629
|
+
wr_wkr_t* worker = NULL;
|
630
|
+
wr_u_short retval = TRUE;
|
631
|
+
|
632
|
+
if(wr_wkr_check_uds(ctl, ctl_msg) == FALSE) return -1;
|
633
|
+
|
634
|
+
LOG_DEBUG(4,"Sock_path = %s, port=%s, app_name=%s, pid=%s", ctl_msg->msg.wkr.sock_path.str,
|
635
|
+
ctl_msg->msg.wkr.port.str,
|
636
|
+
ctl_msg->msg.wkr.app_name.str,
|
637
|
+
ctl_msg->msg.wkr.pid.str);
|
638
|
+
|
639
|
+
worker = wr_wkr_new(ctl);
|
640
|
+
if(worker == NULL) {
|
641
|
+
LOG_ERROR(WARN,"worker object alloaction failde. Returning ...");
|
642
|
+
return -1;
|
643
|
+
}
|
644
|
+
|
645
|
+
worker->pid = atoi(ctl_msg->msg.wkr.pid.str);
|
646
|
+
|
647
|
+
// Insert newly added Worker to application list*/
|
648
|
+
if(wr_app_wkr_insert(server, worker, ctl_msg)!=0) {
|
649
|
+
LOG_INFO("No more workers required.");
|
650
|
+
free(worker);
|
651
|
+
return -1;
|
652
|
+
}
|
653
|
+
|
654
|
+
LOG_INFO("Worker %d with PID %d for Application %s inserted successfully. control fd = %d",
|
655
|
+
worker->id, worker->pid, worker->app->conf->name.str,worker->ctl->fd);
|
656
|
+
if(Config->Server.flag & SERVER_UDS_SUPPORT) {
|
657
|
+
retval = wr_wkr_connect_uds(worker, ctl_msg);
|
545
658
|
} else {
|
546
|
-
|
659
|
+
retval = wr_wkr_connect_inet(worker, ctl_msg);
|
547
660
|
}
|
661
|
+
|
662
|
+
if(retval == TRUE) retval = wr_wkr_set_ratio(ctl, worker);
|
663
|
+
|
664
|
+
if(retval == FALSE){
|
665
|
+
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * Config->Application.max_req_ratio;
|
666
|
+
free(worker);
|
667
|
+
return -1;
|
668
|
+
}
|
669
|
+
|
670
|
+
LOG_DEBUG(DEBUG,"Allocating task to newly added worker %d",worker->id);
|
671
|
+
//Check for pending requests
|
672
|
+
wr_wrk_allocate(worker);
|
673
|
+
LOG_DEBUG(5,"Successfully connected to worker");
|
674
|
+
LOG_DEBUG(DEBUG,"Allocated task to newly added worker %d",worker->id);
|
675
|
+
wr_app_wkr_balance(worker->app);
|
676
|
+
|
677
|
+
return 0;
|
678
|
+
}
|
548
679
|
|
549
|
-
sprintf(cuid_s, "%d", app_conf->cuid);
|
550
|
-
sprintf(cgid_s, "%d", app_conf->cgid);
|
551
|
-
sprintf(log_level, "%d", app_conf->log_level);
|
552
680
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
681
|
+
/*******************************************
|
682
|
+
* Worker Function Definition *
|
683
|
+
*******************************************/
|
684
|
+
|
685
|
+
/** Create the Worker */
|
686
|
+
/* Fork a new process and start worker in it. */
|
687
|
+
int wr_wkr_create(wr_svr_t *server, config_application_list_t *app_conf) {
|
688
|
+
LOG_FUNCTION
|
689
|
+
pid_t pid;
|
690
|
+
wr_wkr_create_t *worker = wr_wkr_create_init(server, app_conf);
|
691
|
+
|
558
692
|
pid = fork();
|
559
|
-
LOG_DEBUG(DEBUG,"Forked PID is %i,
|
693
|
+
LOG_DEBUG(DEBUG,"Forked PID is %i, app = %s",pid, app_conf->name.str) ;
|
560
694
|
if (pid == 0) {
|
561
695
|
LOG_DEBUG(3,"Child is continuing %i",pid);
|
562
696
|
setsid();
|
563
697
|
int i = 0;
|
564
|
-
for (i=getdtablesize();i>=0;--i) {
|
698
|
+
for (i = getdtablesize();i>=0;--i) {
|
565
699
|
//LOG_DEBUG(DEBUG,"closing fd=%d",i);
|
566
700
|
close(i); //why??
|
567
701
|
}
|
@@ -575,43 +709,100 @@ int wr_wkr_create(wr_svr_t *server, wr_app_conf_t *app_conf) {
|
|
575
709
|
int j = dup(i); // stdout
|
576
710
|
j = dup(i); // stderr
|
577
711
|
|
578
|
-
LOG_DEBUG(DEBUG,"Before execl():Rails application=%s,
|
579
|
-
LOG_DEBUG(DEBUG,"exe file = %s",
|
712
|
+
LOG_DEBUG(DEBUG,"Before execl():Rails application=%s", app_conf->path.str);
|
713
|
+
LOG_DEBUG(DEBUG,"exe file = %s",Config->Server.File.worker_bin.str);
|
580
714
|
int rv;
|
581
|
-
rv=execl(
|
582
|
-
"-
|
583
|
-
"-
|
584
|
-
"-u", cuid_s,
|
585
|
-
"-g", cgid_s,
|
586
|
-
"-c", controller_path,
|
587
|
-
"-i", (server->conf->uds? "y" : "n"),
|
588
|
-
"-t", app_conf->type.str,
|
715
|
+
rv=execl(Config->Server.File.worker_bin.str, Config->Server.File.worker_bin.str,
|
716
|
+
"-c", worker->controller_path,
|
717
|
+
"-i", (Config->Server.flag & SERVER_UDS_SUPPORT ? "y" : "n"),
|
589
718
|
"-n", app_conf->name.str,
|
590
|
-
"-
|
591
|
-
"-
|
592
|
-
"-
|
593
|
-
"-o", server->conf->wr_root_path.str,
|
594
|
-
"-k", (WR_SVR_KEEP_ALIVE? "y" : "n"),
|
595
|
-
"-l", log_level,
|
719
|
+
"-o", Config->Server.Dir.root.str,
|
720
|
+
"-k", (Config->Server.flag & SERVER_KEEP_ALIVE ? "y" : "n"),
|
721
|
+
"-l", worker->log_level,
|
596
722
|
NULL);
|
597
|
-
wr_string_free(baseuri);
|
723
|
+
wr_string_free(worker->baseuri);
|
724
|
+
free(worker);
|
598
725
|
if(rv<0) {
|
599
|
-
LOG_ERROR(5,"Unable to run %s: %s\n",
|
600
|
-
fprintf(stderr, "Unable to run %s: %s\n",
|
726
|
+
LOG_ERROR(5,"Unable to run %s: %s\n", Config->Server.File.worker_bin.str, strerror(errno));
|
727
|
+
fprintf(stderr, "Unable to run %s: %s\n", Config->Server.File.worker_bin.str, strerror(errno));
|
601
728
|
fflush(stderr);
|
602
729
|
_exit(1);
|
603
730
|
}
|
604
731
|
} else if (pid == -1) {
|
605
|
-
wr_string_free(baseuri);
|
732
|
+
wr_string_free(worker->baseuri);
|
733
|
+
free(worker);
|
606
734
|
LOG_ERROR(5,"Cannot fork a new process %i", errno);
|
607
735
|
} else {
|
608
|
-
wr_string_free(baseuri);
|
736
|
+
wr_string_free(worker->baseuri);
|
737
|
+
free(worker);
|
609
738
|
//Temporary Hack
|
610
739
|
return pid;
|
611
740
|
}
|
612
741
|
return -1;
|
613
742
|
}
|
614
743
|
|
744
|
+
/** Destroy worker */
|
745
|
+
void wr_wkr_free(wr_wkr_t *worker) {
|
746
|
+
LOG_FUNCTION
|
747
|
+
|
748
|
+
if(Config->Server.Worker.idle_time > 0 && ev_is_active(&worker->t_wait))
|
749
|
+
ev_timer_stop(worker->loop,&worker->t_wait);
|
750
|
+
|
751
|
+
if(ev_is_active(&worker->watcher))
|
752
|
+
ev_io_stop(worker->loop,&worker->watcher);
|
753
|
+
|
754
|
+
if(worker->req) {
|
755
|
+
LOG_DEBUG(DEBUG,"Worker %d with pid %d. Worker cannot served the request.",worker->id, worker->pid);
|
756
|
+
LOG_INFO("Worker %d with pid %d. Worker cannot served the request.",worker->id, worker->pid);
|
757
|
+
worker->req->using_wkr = FALSE;
|
758
|
+
wr_conn_err_resp(worker->req->conn, WR_HTTP_STATUS_500);
|
759
|
+
}
|
760
|
+
|
761
|
+
if(worker->app){
|
762
|
+
LOG_INFO("Removing worker %d with pid %d...app->q_workers->q_count=%d, q_front=%d, q_rear=%d app=%s",
|
763
|
+
worker->id, worker->pid,worker->app->q_workers->q_count,
|
764
|
+
worker->app->q_workers->q_front,worker->app->q_workers->q_rear,
|
765
|
+
worker->app->conf->name.str);
|
766
|
+
if(wr_queue_remove(worker->app->q_workers, worker) == 0) {
|
767
|
+
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * Config->Application.max_req_ratio;
|
768
|
+
worker->app->low_ratio = WR_QUEUE_SIZE(worker->app->q_workers) * Config->Application.min_req_ratio;
|
769
|
+
}
|
770
|
+
wr_queue_remove(worker->app->q_free_workers, worker);
|
771
|
+
}else{
|
772
|
+
LOG_INFO("Removing worker %d with pid %d", worker->id, worker->pid);
|
773
|
+
}
|
774
|
+
|
775
|
+
if(worker->state == WKR_STATE_DISCONNECTING){
|
776
|
+
LOG_DEBUG(DEBUG,"Stopping worker %d with pid %d...",worker->id, worker->pid);
|
777
|
+
LOG_INFO("Stopping worker %d with pid %d...",worker->id, worker->pid);
|
778
|
+
scgi_t* scgi = scgi_new();
|
779
|
+
if(scgi) {
|
780
|
+
scgi_header_add(scgi, "METHOD", strlen("METHOD"), "REMOVE", strlen("REMOVE"));
|
781
|
+
scgi_build(scgi);
|
782
|
+
//TODO: made it asynchronous
|
783
|
+
scgi_send(scgi, worker->ctl->fd);
|
784
|
+
scgi_free(scgi);
|
785
|
+
} else {
|
786
|
+
kill(worker->pid, SIGHUP);
|
787
|
+
}
|
788
|
+
worker->pid = 0;
|
789
|
+
}else if(worker->state == WKR_STATE_HANGUP){
|
790
|
+
kill(worker->pid, SIGKILL);
|
791
|
+
}else{
|
792
|
+
kill(worker->pid, SIGHUP);
|
793
|
+
}
|
794
|
+
|
795
|
+
if(worker->ctl) {
|
796
|
+
worker->ctl->wkr = NULL;
|
797
|
+
wr_ctl_free(worker->ctl);
|
798
|
+
}
|
799
|
+
//Close socket
|
800
|
+
if(worker->fd > 0)
|
801
|
+
close(worker->fd);
|
802
|
+
|
803
|
+
free(worker);
|
804
|
+
}
|
805
|
+
|
615
806
|
/** Request callback called by ebb Request*/
|
616
807
|
/* It will be called after request is parsed and environment hash is ready.
|
617
808
|
* Request is inserted into application queue, and one of free worker allocated to a Request. */
|
@@ -628,167 +819,12 @@ void wr_wkr_dispatch_req(wr_req_t* req) {
|
|
628
819
|
WR_APP_MSG_DISPATCH(req->app, new_req, worker) ;
|
629
820
|
|
630
821
|
if(new_req && worker) {
|
631
|
-
|
632
|
-
new_req->wkr = worker;
|
633
|
-
new_req->using_wkr = TRUE;
|
634
|
-
|
635
|
-
worker->watcher.data = new_req;
|
636
|
-
//set Request on wich worker is working
|
637
|
-
worker->req = new_req;
|
638
|
-
ev_io_init(&worker->watcher, wr_req_hearer_write_cb, worker->fd, EV_WRITE);
|
639
|
-
ev_io_start(worker->loop, &worker->watcher);
|
822
|
+
wr_wkr_req_processing(worker, new_req);
|
640
823
|
}else{
|
641
824
|
LOG_DEBUG(DEBUG, "Could not dispatch the request");
|
642
825
|
}
|
643
826
|
}
|
644
827
|
|
645
|
-
/** Handle connect request from Worker */
|
646
|
-
int wr_wkr_connect(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
647
|
-
LOG_FUNCTION
|
648
|
-
wr_svr_t* server = ctl->svr;
|
649
|
-
wr_wkr_t* worker = NULL;
|
650
|
-
|
651
|
-
if(server->conf->uds) {
|
652
|
-
if(strcmp(ctl_msg->msg.wkr.uds.str,"YES")!=0 ||
|
653
|
-
ctl_msg->msg.wkr.sock_path.str == NULL) {
|
654
|
-
scgi_body_add(ctl->scgi, "Invalid UDS, sock path and configuration.", strlen("Invalid UDS, sock path and configuration."));
|
655
|
-
LOG_ERROR(SEVERE,"connect_with_worker()Invalid UDS, sock path and configuration.");
|
656
|
-
return -1;
|
657
|
-
}
|
658
|
-
} else {
|
659
|
-
if(strcmp(ctl_msg->msg.wkr.uds.str,"NO")!=0 ||
|
660
|
-
ctl_msg->msg.wkr.port.str == NULL) {
|
661
|
-
scgi_body_add(ctl->scgi, "Invalid UDS, sock path and configuration.", strlen("Invalid UDS, sock path and configuration."));
|
662
|
-
LOG_ERROR(SEVERE,"connect_with_worker()Invalid UDS, sock path and configuration.");
|
663
|
-
return -1;
|
664
|
-
}
|
665
|
-
}
|
666
|
-
|
667
|
-
LOG_DEBUG(4,"Sock_path = %s, port=%s, app_name=%s, pid=%s", ctl_msg->msg.wkr.sock_path.str,
|
668
|
-
ctl_msg->msg.wkr.port.str,
|
669
|
-
ctl_msg->msg.wkr.app_name.str,
|
670
|
-
ctl_msg->msg.wkr.pid.str);
|
671
|
-
|
672
|
-
worker = wr_wkr_new(ctl);
|
673
|
-
if(worker == NULL) {
|
674
|
-
LOG_ERROR(WARN,"worker object alloaction failde. Returning ...");
|
675
|
-
return -1;
|
676
|
-
}
|
677
|
-
|
678
|
-
worker->pid = atoi(ctl_msg->msg.wkr.pid.str);
|
679
|
-
worker->state += WR_WKR_CONNECTING;
|
680
|
-
|
681
|
-
// Insert newly added Worker to application list*/
|
682
|
-
if(wr_app_wkr_insert(server, worker, ctl_msg)!=0) {
|
683
|
-
LOG_INFO("No more workers required.");
|
684
|
-
free(worker);
|
685
|
-
return -1;
|
686
|
-
}
|
687
|
-
|
688
|
-
LOG_INFO("Worker %d with PID %d for Application %s inserted successfully. control fd = %d",
|
689
|
-
worker->id, worker->pid, worker->app->conf->name.str,worker->ctl->fd);
|
690
|
-
if(server->conf->uds) {
|
691
|
-
//Connect to Worker using UNIX domain socket
|
692
|
-
struct sockaddr_un addr;
|
693
|
-
int len;
|
694
|
-
|
695
|
-
if ((worker->fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
696
|
-
perror("socket()");
|
697
|
-
LOG_ERROR(4,"socket() failed");
|
698
|
-
// Worker is not added, Reset the high load ratio
|
699
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
700
|
-
free(worker);
|
701
|
-
return -1;
|
702
|
-
}
|
703
|
-
LOG_DEBUG(3,"Socket successfully open for worker. File Descriptor is %d",worker->fd);
|
704
|
-
|
705
|
-
setsocketoption(worker->fd);
|
706
|
-
memset(&addr, 0, sizeof(addr));
|
707
|
-
|
708
|
-
addr.sun_family = AF_UNIX;
|
709
|
-
strcpy(addr.sun_path,ctl_msg->msg.wkr.sock_path.str);
|
710
|
-
len = sizeof(addr.sun_family) + strlen(addr.sun_path);
|
711
|
-
|
712
|
-
#ifdef __APPLE__
|
713
|
-
len++;
|
714
|
-
#endif
|
715
|
-
|
716
|
-
if(connect(worker->fd, (struct sockaddr *)&addr,len) == -1) {
|
717
|
-
perror("connect");
|
718
|
-
LOG_ERROR(4,"Unable to connect with worker at socket path %s. %s Closing it.",addr.sun_path, strerror(errno));
|
719
|
-
close_fd(worker->fd);
|
720
|
-
worker->fd=0;
|
721
|
-
// Worker is not added, Reset the high load ratio
|
722
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
723
|
-
free(worker);
|
724
|
-
return -1;
|
725
|
-
}
|
726
|
-
} else {
|
727
|
-
//Connect to Worker using internet socket
|
728
|
-
struct sockaddr_in addr;
|
729
|
-
if ((worker->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
730
|
-
perror("socket()");
|
731
|
-
LOG_ERROR(4,"socket() failed for worker");
|
732
|
-
// Worker is not added, Reset the high load ratio
|
733
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
734
|
-
free(worker);
|
735
|
-
// return if not able to connect to the first worker
|
736
|
-
return -1;
|
737
|
-
}
|
738
|
-
LOG_DEBUG(3,"Socket successfully open for worker. File Descriptor is %d",worker->fd);
|
739
|
-
|
740
|
-
setsocketoption(worker->fd);
|
741
|
-
memset(&addr, 0, sizeof(addr));
|
742
|
-
|
743
|
-
addr.sin_family = AF_INET;
|
744
|
-
addr.sin_port = htons(atoi(ctl_msg->msg.wkr.port.str));
|
745
|
-
addr.sin_addr.s_addr =inet_addr("127.0.0.1");
|
746
|
-
|
747
|
-
if(connect(worker->fd, (struct sockaddr *)&addr,sizeof addr) == -1) {
|
748
|
-
perror("connect");
|
749
|
-
LOG_ERROR(4,"Unable to connect with worker at port %s. %s Closing it.",ctl_msg->msg.wkr.port.str, strerror(errno));
|
750
|
-
close_fd(worker->fd);
|
751
|
-
worker->fd=0;
|
752
|
-
free(worker);
|
753
|
-
// Worker is not added, Reset the high load ratio
|
754
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
755
|
-
return -1;
|
756
|
-
}
|
757
|
-
}
|
758
|
-
|
759
|
-
if(setnonblock(worker->fd) < 0) {
|
760
|
-
LOG_ERROR(SEVERE,"Setting worker_fd non-block failed:%s",strerror(errno));
|
761
|
-
close_fd(worker->fd);
|
762
|
-
free(worker);
|
763
|
-
// Worker is not added, Reset the high load ratio
|
764
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
765
|
-
return -1;
|
766
|
-
}
|
767
|
-
|
768
|
-
if(wr_queue_insert(worker->app->q_workers, worker) < 0){
|
769
|
-
LOG_ERROR(WARN,"Worker queue is full.");
|
770
|
-
worker->app->high_ratio = TOTAL_WORKER_COUNT(worker->app) * WR_MAX_REQ_RATIO;
|
771
|
-
return -1;
|
772
|
-
}
|
773
|
-
|
774
|
-
//Setting low load ratio for application, refer "wr_worker_remove_cb" in wr_server.c for details.
|
775
|
-
worker->app->low_ratio = worker->app->q_workers->q_count * WR_MIN_REQ_RATIO;
|
776
|
-
ctl->wkr = worker;
|
777
|
-
LOG_DEBUG(DEBUG,"Added Worker %d",worker->id);
|
778
|
-
|
779
|
-
ev_io_set(&worker->watcher,worker->fd,EV_READ);
|
780
|
-
|
781
|
-
LOG_DEBUG(DEBUG,"Allocating task to newly added worker %d",worker->id);
|
782
|
-
//Check for pending requests
|
783
|
-
wr_wrk_allocate(worker);
|
784
|
-
LOG_DEBUG(5,"Successfully connected to worker");
|
785
|
-
LOG_DEBUG(DEBUG,"Allocated task to newly added worker %d",worker->id);
|
786
|
-
wr_app_wkr_balance(worker->app);
|
787
|
-
//wr_app_wkr_added_cb(worker->app);
|
788
|
-
|
789
|
-
return 0;
|
790
|
-
}
|
791
|
-
|
792
828
|
///** This would get called when worker reply to PING */
|
793
829
|
//void wr_wkr_ping_reply(wr_wkr_t *worker)
|
794
830
|
//{
|
@@ -798,13 +834,15 @@ int wr_wkr_connect(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
798
834
|
// if(worker->state & WR_WKR_PING_SENT)
|
799
835
|
// {
|
800
836
|
// ev_timer_stop(worker->ctl->svr->ebb_svr.loop, &worker->t_wait);
|
801
|
-
// worker->t_wait.repeat =
|
837
|
+
// worker->t_wait.repeat = Config->Server.Worker.idle_time;
|
802
838
|
// worker->state &= (~224);
|
803
839
|
// ev_timer_again(worker->ctl->svr->ebb_svr.loop, &worker->t_wait);
|
804
840
|
// }
|
805
841
|
//}
|
806
842
|
|
807
843
|
/** Worker add callback */
|
844
|
+
/* This callback function called from controller on receiving WORKER ADD control
|
845
|
+
* signal */
|
808
846
|
void wr_wkr_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
809
847
|
LOG_FUNCTION
|
810
848
|
int retval;
|
@@ -819,22 +857,28 @@ void wr_wkr_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
819
857
|
wr_ctl_resp_write(ctl);
|
820
858
|
}
|
821
859
|
|
860
|
+
/** Worker Add error callback */
|
861
|
+
void wr_wkr_add_error_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg){
|
862
|
+
LOG_FUNCTION
|
863
|
+
wr_app_wkr_error(ctl->svr, ctl_msg);
|
864
|
+
scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
|
865
|
+
wr_ctl_resp_write(ctl);
|
866
|
+
}
|
867
|
+
|
822
868
|
/** Worker remove callback */
|
823
869
|
void wr_wkr_remove_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
824
870
|
LOG_FUNCTION
|
825
871
|
wr_app_t *app = NULL;
|
872
|
+
|
826
873
|
if(ctl->wkr ) {
|
827
874
|
app = ctl->wkr->app;
|
828
|
-
ctl->wkr
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
875
|
+
wr_wkr_state_machine(ctl->wkr, WKR_ACTION_REMOVE);
|
876
|
+
scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
|
877
|
+
}else{
|
878
|
+
LOG_ERROR(SEVERE,"failed to connect with worker");
|
879
|
+
scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
|
833
880
|
}
|
834
|
-
|
835
|
-
scgi_free(ctl->scgi);
|
836
|
-
ctl->scgi = NULL;
|
837
|
-
//TODO :Send acknowledgement signal.
|
881
|
+
|
838
882
|
wr_ctl_resp_write(ctl);
|
839
883
|
|
840
884
|
// Create new worker if required
|
@@ -842,17 +886,12 @@ void wr_wkr_remove_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
842
886
|
}
|
843
887
|
|
844
888
|
/** Worker ping callback */
|
889
|
+
/* Get reply for the ping control request */
|
845
890
|
void wr_wkr_ping_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msgs) {
|
846
891
|
LOG_FUNCTION
|
847
892
|
wr_wkr_t *worker = ctl->wkr;
|
848
893
|
LOG_INFO("Worker %d with pid %d replied for trial no %d", worker->id, worker->pid, worker->trials_done);
|
849
|
-
|
850
|
-
if(worker->state & WR_WKR_PING_SENT) {
|
851
|
-
ev_timer_stop(ctl->svr->ebb_svr.loop, &worker->t_wait);
|
852
|
-
worker->t_wait.repeat = WR_WKR_IDLE_TIME;
|
853
|
-
worker->state &= (~224);
|
854
|
-
ev_timer_again(ctl->svr->ebb_svr.loop, &worker->t_wait);
|
855
|
-
}
|
894
|
+
wr_wkr_state_machine(worker, WKR_ACTION_PING_REPLAY);
|
856
895
|
scgi_build(ctl->scgi);
|
857
896
|
scgi_free(ctl->scgi);
|
858
897
|
ctl->scgi = NULL;
|