webroar 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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;
|