webroar 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -0
- data/README +116 -86
- data/doc/user-guide.html +2 -2
- data/doc/user-guide.txt +65 -65
- data/lib/command_runner.rb +5 -3
- data/src/head/wr_application.c +249 -294
- data/src/head/wr_application.h +28 -21
- data/src/head/wr_config.h +7 -1
- data/src/head/wr_connection.c +1 -1
- data/src/head/wr_controller.c +2 -4
- data/src/head/wr_request.c +1 -1
- data/src/head/wr_request.h +3 -3
- data/src/head/wr_resolver.c +2 -2
- data/src/head/wr_worker.c +16 -17
- data/src/ruby_lib/ruby_interface/version.rb +1 -1
- data/tasks/gem.rake +1 -1
- metadata +3 -3
data/src/head/wr_application.c
CHANGED
@@ -23,19 +23,37 @@ static unsigned int worker_count = 0;
|
|
23
23
|
|
24
24
|
/************** Private Functions ******************/
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
// Check whether application already exist
|
27
|
+
static inline wr_app_t* wr_app_exist(wr_svr_t *server, const char *app_name){
|
28
|
+
wr_app_t* app = server->apps, *tmp_app = NULL;
|
29
|
+
|
30
|
+
while(app) {
|
31
|
+
if(strcmp(app_name, app->conf->name.str)==0)
|
32
|
+
return app;
|
33
|
+
tmp_app = app;
|
34
|
+
app = app->next;
|
31
35
|
}
|
32
|
-
|
36
|
+
|
37
|
+
if(strcmp(app_name, WR_STATIC_FILE_SERVER_NAME) == 0){
|
38
|
+
return server->static_app;
|
39
|
+
}
|
40
|
+
|
41
|
+
return NULL;
|
42
|
+
}
|
33
43
|
|
34
|
-
|
44
|
+
// Check whether pending worker exist
|
45
|
+
static inline wr_pending_wkr_t* wr_pending_worker_exist(wr_app_t *app, const int pid){
|
46
|
+
int i;
|
47
|
+
for(i = 0 ; i < WR_QUEUE_SIZE(app->q_pending_workers); i++){
|
48
|
+
wr_pending_wkr_t* pending = wr_queue_fetch(app->q_pending_workers);
|
49
|
+
if(pending && *pending == pid) return pending;
|
50
|
+
wr_queue_insert(app->q_pending_workers, pending);
|
51
|
+
}
|
52
|
+
return NULL;
|
35
53
|
}
|
36
54
|
|
37
55
|
/** Callback function to add worker to application */
|
38
|
-
void
|
56
|
+
void wr_app_wkr_add_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
39
57
|
LOG_FUNCTION
|
40
58
|
wr_app_t* app = (wr_app_t*) w->data;
|
41
59
|
ev_timer_stop(loop, &app->t_add);
|
@@ -47,64 +65,86 @@ void wr_app_wrk_add_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
47
65
|
}
|
48
66
|
|
49
67
|
/** Callback function to add worker timeout */
|
50
|
-
void
|
68
|
+
void wr_app_wkr_add_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
51
69
|
LOG_FUNCTION
|
52
70
|
wr_app_t* app = (wr_app_t*) w->data;
|
53
71
|
char err_msg[512];
|
54
72
|
int err_msg_len = 0;
|
73
|
+
int pid = 0;
|
55
74
|
|
56
|
-
// Stop add timeout timer
|
75
|
+
// Stop add timeout timer and increament timeout counter
|
57
76
|
ev_timer_stop(loop, &app->t_add_timeout);
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
77
|
+
app->timeout_counter ++;
|
78
|
+
|
79
|
+
// Kill oldest pending worker
|
80
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) > 0) {
|
81
|
+
wr_pending_wkr_t *pending = wr_queue_fetch(app->q_pending_workers);
|
82
|
+
if(pending){
|
83
|
+
pid = *pending;
|
84
|
+
free(pending);
|
85
|
+
}
|
86
|
+
LOG_INFO("wr_app_wkr_add_timeout_cb: killing worker, pid = %d", pid);
|
64
87
|
if(pid > 0)
|
65
88
|
kill(pid ,SIGKILL);
|
66
|
-
LOG_DEBUG(DEBUG,"app->pending_wkr = %d", app->
|
67
|
-
app->
|
68
|
-
if(app->pending_wkr > 0) {
|
89
|
+
LOG_DEBUG(DEBUG,"app->pending_wkr = %d", WR_QUEUE_SIZE(app->q_pending_workers));
|
90
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) > 0) {
|
69
91
|
ev_timer_again(loop, &app->t_add_timeout);
|
70
92
|
}
|
71
93
|
|
72
94
|
// Update high load ratio
|
73
95
|
app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
|
74
96
|
}
|
75
|
-
|
76
|
-
//
|
77
|
-
|
78
|
-
|
79
|
-
|
97
|
+
|
98
|
+
// If application restarted, rollback all the changes.
|
99
|
+
if(app->state == WR_APP_RESTART){
|
100
|
+
app->state = WR_APP_ACTIVE;
|
101
|
+
// Send error response
|
80
102
|
LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
103
|
+
if(app->ctl){
|
104
|
+
scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
|
105
|
+
err_msg_len = sprintf(err_msg,"The application could not be started due to the following error. Please refer '/var/log/webroar/%s.log' and the application log file for more details.", app->conf->name.str);
|
106
|
+
scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
|
107
|
+
wr_ctl_resp_write(app->ctl);
|
108
|
+
}
|
109
|
+
app->timeout_counter = 0;
|
85
110
|
app->ctl = NULL;
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
111
|
+
return;
|
112
|
+
}else if(app->state == WR_APP_NEW){
|
113
|
+
// Try out upto MAX timeout count
|
114
|
+
/*
|
115
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) == 0 && app->timeout_counter < WR_MAX_ADD_TIMEOUT_COUNTER){
|
116
|
+
wr_app_wkr_add(app);
|
117
|
+
}else{
|
118
|
+
*/
|
119
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) == 0){
|
120
|
+
// Send error response
|
121
|
+
LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
|
122
|
+
if(app->ctl){
|
123
|
+
scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
|
124
|
+
err_msg_len = sprintf(err_msg,"The application could not be started due to the following error. Please refer '/var/log/webroar/%s.log' and the application log file for more details.", app->conf->name.str);
|
125
|
+
scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
|
126
|
+
wr_ctl_resp_write(app->ctl);
|
127
|
+
}
|
128
|
+
app->timeout_counter = 0;
|
129
|
+
app->ctl = NULL;
|
130
|
+
wr_app_remove(app->svr, app->conf->name.str);
|
90
131
|
}
|
91
|
-
|
92
|
-
wr_app_remove(app->svr, app->conf->name.str);
|
93
|
-
} else if(app->in_use == TRUE && (TOTAL_WORKER_COUNT(app) < app->conf->min_worker || app->add_workers)) {
|
94
|
-
wr_app_wkr_add(app);
|
132
|
+
return;
|
95
133
|
}
|
134
|
+
|
135
|
+
wr_app_wkr_balance(app);
|
96
136
|
}
|
97
137
|
|
98
138
|
/** Callback function to remove worker from application */
|
99
|
-
void
|
139
|
+
void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
100
140
|
LOG_FUNCTION
|
101
141
|
wr_app_t* app = (wr_app_t*) w->data;
|
102
142
|
|
103
143
|
ev_timer_stop(loop, &app->t_remove);
|
104
144
|
|
105
|
-
// Following variable helps in removing unncecessary call to
|
106
|
-
int forecasted_count=app->
|
107
|
-
// Its a known bug - At any time app->active_worker should equals to app->
|
145
|
+
// Following variable helps in removing unncecessary call to wr_app_wkr_remove_cb
|
146
|
+
int forecasted_count=app->q_workers->q_count;
|
147
|
+
// Its a known bug - At any time app->active_worker should equals to app->q_workers->q_count
|
108
148
|
// Scenario: We are forking new worker due to high load and also increasing active worker count.
|
109
149
|
// It took some time to get register with Head, and actual queue count incremented after Head
|
110
150
|
// register the newly created worker. Now, mean while load goes down, and we are ready to remove the
|
@@ -117,15 +157,15 @@ void wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
117
157
|
// when new worker is actually get registered with Head also, we reset active worker with
|
118
158
|
// application worker queue count, whenever worker is actually removed.
|
119
159
|
// TODO: Handle above bug properly.
|
120
|
-
LOG_DEBUG(DEBUG,"Pending_wkr = %d, app->
|
121
|
-
app->
|
122
|
-
if(app->
|
160
|
+
LOG_DEBUG(DEBUG,"Pending_wkr = %d, app->q_workers->q_count = %d",
|
161
|
+
WR_QUEUE_SIZE(app->q_pending_workers), WR_QUEUE_SIZE(app->q_workers));
|
162
|
+
if(app->q_workers->q_count > app->conf->min_worker) {
|
123
163
|
char cmd[WR_LONG_LONG_STR_LEN];
|
124
164
|
char pid_list[WR_LONG_LONG_STR_LEN], pid_c[WR_SHORT_STR_LEN];
|
125
165
|
int i,index;
|
126
166
|
i = 0;
|
127
|
-
index = (app->
|
128
|
-
wr_wkr_t *tmp_worker = (wr_wkr_t*)app->
|
167
|
+
index = (app->q_workers->q_front + i) % app->q_workers->q_max_size;
|
168
|
+
wr_wkr_t *tmp_worker = (wr_wkr_t*)app->q_workers->q_elements[index];
|
129
169
|
|
130
170
|
|
131
171
|
// Get pid of the worker consuming more resident memory
|
@@ -147,9 +187,9 @@ void wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
147
187
|
sprintf(pid_c,"%d",tmp_worker->pid);
|
148
188
|
strcpy(pid_list, pid_c);
|
149
189
|
i++;
|
150
|
-
for(;i < app->
|
151
|
-
index = (app->
|
152
|
-
tmp_worker = (wr_wkr_t*)app->
|
190
|
+
for(;i < app->q_workers->q_count ; i++) {
|
191
|
+
index = (app->q_workers->q_front + i) % app->q_workers->q_max_size;
|
192
|
+
tmp_worker = (wr_wkr_t*)app->q_workers->q_elements[index];
|
153
193
|
sprintf(pid_c,",%d", tmp_worker->pid);
|
154
194
|
strcat(pid_list, pid_c);
|
155
195
|
}
|
@@ -168,12 +208,12 @@ void wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
168
208
|
int flag = 1;
|
169
209
|
|
170
210
|
// Check for worker in list of free workers. If found remove it.
|
171
|
-
if(app->
|
211
|
+
if(app->q_free_workers->q_count > 0) {
|
172
212
|
LOG_DEBUG(DEBUG,", pid = %d find in free worker", pid);
|
173
213
|
//int i, index;
|
174
|
-
for( i = 0; i < app->
|
175
|
-
index = (app->
|
176
|
-
tmp_worker = (wr_wkr_t*)app->
|
214
|
+
for( i = 0; i < app->q_free_workers->q_count ; i++) {
|
215
|
+
index = (app->q_free_workers->q_front + i) % app->q_free_workers->q_max_size;
|
216
|
+
tmp_worker = (wr_wkr_t*)app->q_free_workers->q_elements[index];
|
177
217
|
if(tmp_worker->pid == pid) {
|
178
218
|
LOG_DEBUG(DEBUG,"Removing from free worker id=%d", tmp_worker->id);
|
179
219
|
forecasted_count--;
|
@@ -187,12 +227,12 @@ void wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
187
227
|
|
188
228
|
// Check for worker in the list of all the worker. If found mark it as in-active.
|
189
229
|
// In-active worker will be removed once current request is processed.
|
190
|
-
if(flag && app->
|
230
|
+
if(flag && app->q_workers->q_count > 0) {
|
191
231
|
LOG_DEBUG(DEBUG,"pid = %d find in active worker", pid);
|
192
232
|
//int i, index;
|
193
|
-
for( i = 0; i < app->
|
194
|
-
index = (app->
|
195
|
-
tmp_worker = (wr_wkr_t*)app->
|
233
|
+
for( i = 0; i < app->q_workers->q_count ; i++) {
|
234
|
+
index = (app->q_workers->q_front + i) % app->q_workers->q_max_size;
|
235
|
+
tmp_worker = (wr_wkr_t*)app->q_workers->q_elements[index];
|
196
236
|
if(tmp_worker->pid == pid) {
|
197
237
|
forecasted_count--;
|
198
238
|
LOG_DEBUG(DEBUG,"Remove active status id = %d", tmp_worker->id);
|
@@ -217,7 +257,6 @@ static inline int wr_app_reload(wr_app_t *app){
|
|
217
257
|
wr_app_conf_t *app_conf;
|
218
258
|
short count;
|
219
259
|
|
220
|
-
app->restarted = FALSE;
|
221
260
|
// Remove an old application from the resolver list.
|
222
261
|
wr_req_resolver_remove(app->svr, app);
|
223
262
|
|
@@ -227,10 +266,13 @@ static inline int wr_app_reload(wr_app_t *app){
|
|
227
266
|
app->svr->err_msg);
|
228
267
|
if(app_conf == NULL){
|
229
268
|
LOG_DEBUG(WARN, "Error: %s",app->svr->err_msg);
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
269
|
+
if(app->ctl){
|
270
|
+
scgi_body_add(app->ctl->scgi, app->svr->err_msg, strlen(app->svr->err_msg));
|
271
|
+
scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
|
272
|
+
wr_ctl_resp_write(app->ctl);
|
273
|
+
}
|
274
|
+
app->state = WR_APP_ACTIVE;
|
275
|
+
return FALSE;
|
234
276
|
}
|
235
277
|
|
236
278
|
// Remove old application specification.
|
@@ -244,29 +286,24 @@ static inline int wr_app_reload(wr_app_t *app){
|
|
244
286
|
// Remove workers based on following logic:
|
245
287
|
// If all the workers are free keep a single worker to process the requests and remove all others.
|
246
288
|
// Else remove all the free workers.
|
247
|
-
count = (app->free_wkr_que->q_count == app->wkr_que->q_count ? 1 :0 );
|
248
289
|
|
249
|
-
LOG_DEBUG(DEBUG,"Free workers queue count is %d. Active worker count is %d.", WR_QUEUE_SIZE(app->
|
250
|
-
|
251
|
-
|
252
|
-
worker = (wr_wkr_t*)wr_queue_fetch(app->free_wkr_que);
|
290
|
+
LOG_DEBUG(DEBUG,"Free workers queue count is %d. Active worker count is %d.", WR_QUEUE_SIZE(app->q_free_workers), WR_QUEUE_SIZE(app->q_workers));
|
291
|
+
while(WR_QUEUE_SIZE(app->q_free_workers) > 0){
|
292
|
+
worker = (wr_wkr_t*)wr_queue_fetch(app->q_free_workers);
|
253
293
|
// The worker is already removed from free workers list so do not pass the flag.
|
254
294
|
wr_wkr_remove(worker, 0);
|
255
295
|
}
|
256
296
|
|
257
|
-
// Set the number of workers to be removed.
|
258
|
-
app->old_workers = WR_QUEUE_SIZE(app->wkr_que);
|
259
|
-
// Set the number of workers to be added.
|
260
|
-
app->add_workers = app->conf->min_worker;
|
261
297
|
// Mark all existing workers to OLD worker.
|
262
|
-
for(count = 0; count < app->
|
263
|
-
worker = (wr_wkr_t*)wr_queue_fetch(app->
|
264
|
-
wr_queue_insert(app->
|
298
|
+
for(count = 0; count < WR_QUEUE_SIZE(app->q_workers) ; count++) {
|
299
|
+
worker = (wr_wkr_t*)wr_queue_fetch(app->q_workers);
|
300
|
+
wr_queue_insert(app->q_workers, worker);
|
265
301
|
worker->state |= WR_WKR_OLD;
|
302
|
+
worker->state -= WR_WKR_ACTIVE;
|
266
303
|
}
|
267
304
|
|
268
|
-
|
269
|
-
return
|
305
|
+
app->state = WR_APP_RESTARTING;
|
306
|
+
return TRUE;
|
270
307
|
}
|
271
308
|
|
272
309
|
/*************** Application function definition *********/
|
@@ -277,31 +314,30 @@ void wr_app_free(wr_app_t* app) {
|
|
277
314
|
wr_app_t* tmp_app;
|
278
315
|
wr_wkr_t* worker;
|
279
316
|
|
280
|
-
//wr_application_print(app);
|
281
|
-
|
282
317
|
while(app) {
|
283
318
|
tmp_app = app->next;
|
284
|
-
app->
|
319
|
+
app->state = WR_APP_DESTROY;
|
285
320
|
LOG_DEBUG(4,"Destroying application %s...", app->conf->name.str);
|
286
|
-
LOG_DEBUG(DEBUG,"Worker count = %d", WR_QUEUE_SIZE(app->
|
321
|
+
LOG_DEBUG(DEBUG,"Worker count = %d", WR_QUEUE_SIZE(app->q_workers));
|
287
322
|
//Destroy workers
|
288
|
-
while(worker = (wr_wkr_t*)wr_queue_fetch(app->
|
323
|
+
while(worker = (wr_wkr_t*)wr_queue_fetch(app->q_workers)) {
|
289
324
|
if(app->svr->is_running==0)
|
290
325
|
worker->state |= WR_WKR_HANG;
|
291
326
|
wr_wkr_free(worker);
|
292
327
|
}
|
293
328
|
|
294
|
-
wr_queue_free(app->
|
295
|
-
wr_queue_free(app->
|
329
|
+
wr_queue_free(app->q_free_workers);
|
330
|
+
wr_queue_free(app->q_workers);
|
331
|
+
wr_queue_free(app->q_pending_workers);
|
296
332
|
|
297
333
|
wr_req_t *req;
|
298
|
-
WR_QUEUE_FETCH(app->
|
334
|
+
WR_QUEUE_FETCH(app->q_messages, req) ;
|
299
335
|
while(req) {
|
300
336
|
wr_conn_err_resp(req->conn, WR_HTTP_STATUS_500);
|
301
|
-
WR_QUEUE_FETCH(app->
|
337
|
+
WR_QUEUE_FETCH(app->q_messages, req) ;
|
302
338
|
}
|
303
339
|
|
304
|
-
wr_queue_free(app->
|
340
|
+
wr_queue_free(app->q_messages);
|
305
341
|
|
306
342
|
wr_req_resolver_remove(app->svr, app);
|
307
343
|
|
@@ -324,225 +360,159 @@ void wr_app_print(wr_app_t*app) {
|
|
324
360
|
|
325
361
|
/** Create worker for application */
|
326
362
|
int wr_app_wkr_add(wr_app_t *app) {
|
327
|
-
if(app->
|
363
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) < WR_QUEUE_MAX_SIZE(app->q_pending_workers)) {
|
328
364
|
int retval = wr_wkr_create(app->svr, app->conf);
|
329
365
|
if(retval > 0){
|
330
|
-
|
366
|
+
wr_pending_wkr_t *pending = wr_malloc(wr_pending_wkr_t);
|
367
|
+
*pending = retval;
|
368
|
+
wr_queue_insert(app->q_pending_workers, pending);
|
331
369
|
app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
|
332
|
-
app->last_wkr_pid[app->pending_wkr-1] = retval;
|
333
370
|
ev_timer_again(app->svr->ebb_svr.loop, &app->t_add_timeout);
|
334
371
|
LOG_INFO("PID of created worker = %d, Rails application=%s",
|
335
|
-
|
336
|
-
return
|
372
|
+
retval, app->conf->path.str);
|
373
|
+
return TRUE;
|
337
374
|
}else{
|
338
375
|
LOG_ERROR(SEVERE,"Could not fork process to start new worker.");
|
339
376
|
}
|
340
377
|
}
|
341
|
-
return
|
378
|
+
return FALSE;
|
342
379
|
}
|
343
380
|
|
344
381
|
/** Insert application based on application configuration */
|
345
382
|
static int wr_app_insert(wr_svr_t* server, wr_app_conf_t* config, wr_ctl_t *ctl) {
|
346
383
|
LOG_FUNCTION
|
347
384
|
wr_app_t* app = wr_malloc(wr_app_t);
|
348
|
-
short is_static_server = 0;
|
349
385
|
|
350
386
|
if(!app) {
|
351
387
|
LOG_ERROR(WARN, "%s() application object allocation failed. Returning ...", __FUNCTION__);
|
352
|
-
return
|
388
|
+
return FALSE;
|
353
389
|
}
|
354
390
|
|
355
|
-
|
356
|
-
|
357
|
-
|
391
|
+
// Queue size is WR_ALLOWED_MAX_WORKERS + 1 to accommodate temporary extra
|
392
|
+
// worker, created during application restart
|
393
|
+
app->q_free_workers = wr_queue_new(WR_ALLOWED_MAX_WORKERS + 1);
|
394
|
+
app->q_workers = wr_queue_new(WR_ALLOWED_MAX_WORKERS + 1);
|
395
|
+
app->q_pending_workers = wr_queue_new(WR_MAX_PENDING_WKR);
|
358
396
|
|
359
|
-
|
360
|
-
app->free_wkr_que = wr_queue_new(WR_ALLOWED_MAX_WORKERS + 1);
|
361
|
-
app->wkr_que = wr_queue_new(WR_ALLOWED_MAX_WORKERS + 1);
|
362
|
-
app->msg_que = wr_queue_new(WR_MSG_QUE_SIZE);
|
397
|
+
app->q_messages = wr_queue_new(WR_MSG_QUE_SIZE);
|
363
398
|
|
364
|
-
if(
|
365
|
-
|
366
|
-
app->msg_que == NULL) {
|
399
|
+
if(app->q_workers == NULL || app->q_pending_workers == NULL ||
|
400
|
+
app->q_free_workers == NULL || app->q_messages == NULL) {
|
367
401
|
free(app);
|
368
402
|
app = NULL;
|
369
403
|
LOG_ERROR(WARN, "application object initialization failed. Returning ...");
|
370
|
-
return
|
404
|
+
return FALSE;
|
371
405
|
}
|
406
|
+
|
372
407
|
app->svr = server;
|
373
408
|
app->conf = config;
|
374
409
|
app->ctl = ctl;
|
410
|
+
app->state = WR_APP_NEW;
|
411
|
+
app->timeout_counter = 0;
|
412
|
+
app->high_ratio = 0;
|
413
|
+
app->t_add.data = app->t_remove.data = app->t_add_timeout.data = app;
|
414
|
+
|
375
415
|
/* set application object in control, it would be used at time of freeing control object */
|
376
|
-
if(ctl)
|
377
|
-
|
378
|
-
|
379
|
-
|
416
|
+
if(ctl) ctl->app = app;
|
417
|
+
|
418
|
+
if(strcmp(config->name.str, WR_STATIC_FILE_SERVER_NAME) == 0){
|
419
|
+
app->next = NULL;
|
420
|
+
server->static_app = app;
|
421
|
+
}else{
|
380
422
|
wr_req_resolver_add(server, app, config);
|
381
423
|
app->next = server->apps;
|
382
424
|
server->apps = app;
|
383
|
-
}else{
|
384
|
-
app->next = NULL;
|
385
|
-
server->static_app = app;
|
386
425
|
}
|
387
426
|
|
388
|
-
app->t_add
|
389
|
-
|
390
|
-
ev_timer_init (&app->
|
391
|
-
ev_timer_init (&app->t_remove, wr_app_wrk_remove_cb, 0., WR_LOW_LOAD_LIMIT);
|
392
|
-
ev_timer_init (&app->t_add_timeout, wr_app_wrk_add_timeout_cb, 0., WR_WKR_ADD_TIMEOUT);
|
427
|
+
ev_timer_init (&app->t_add, wr_app_wkr_add_cb, 0., WR_HIGH_LOAD_LIMIT);
|
428
|
+
ev_timer_init (&app->t_remove, wr_app_wkr_remove_cb, 0., WR_LOW_LOAD_LIMIT);
|
429
|
+
ev_timer_init (&app->t_add_timeout, wr_app_wkr_add_timeout_cb, 0., WR_WKR_ADD_TIMEOUT);
|
393
430
|
|
394
|
-
//app->next = server->apps;
|
395
|
-
//server->apps = app;
|
396
431
|
LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, config->name.str);
|
397
432
|
|
398
|
-
app
|
399
|
-
|
400
|
-
|
401
|
-
app->old_workers = 0;
|
402
|
-
app->add_workers = 0;
|
403
|
-
|
404
|
-
int i;
|
405
|
-
for(i = 0; i < WR_MAX_PENDING_WKR ; i ++) {
|
406
|
-
app->last_wkr_pid[i] = 0;
|
407
|
-
}
|
408
|
-
|
409
|
-
/** Creating workers */
|
410
|
-
for(i=0; i < config->min_worker; i++) {
|
411
|
-
//Create a new Worker
|
412
|
-
wr_app_wkr_add(app);
|
413
|
-
// int pid = wr_wkr_create(server, config);
|
414
|
-
// LOG_DEBUG(DEBUG,"Rails application=%s", config->path.str);
|
415
|
-
// LOG_DEBUG(4,"PID of created process is %i",pid);
|
416
|
-
}
|
417
|
-
|
418
|
-
//app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
|
419
|
-
app->low_ratio = TOTAL_WORKER_COUNT(app) * WR_MIN_REQ_RATIO;
|
420
|
-
return 0;
|
433
|
+
wr_app_wkr_balance(app);
|
434
|
+
|
435
|
+
return TRUE;
|
421
436
|
}
|
422
437
|
|
423
|
-
/**
|
424
|
-
void
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
LOG_DEBUG(DEBUG, "Number of add workers is %d.", app->add_workers);
|
431
|
-
app->add_workers --;
|
438
|
+
/** Balance number of workers */
|
439
|
+
void wr_app_wkr_balance(wr_app_t *app){
|
440
|
+
// Maintain minimum number of workers
|
441
|
+
//while(TOTAL_WORKER_COUNT(app) < app->conf->min_worker && app->timeout_counter < WR_MAX_ADD_TIMEOUT_COUNTER){
|
442
|
+
while(TOTAL_WORKER_COUNT(app) < app->conf->min_worker){
|
443
|
+
if(wr_app_wkr_add(app) == FALSE) break;
|
444
|
+
app->low_ratio = TOTAL_WORKER_COUNT(app) * WR_MIN_REQ_RATIO;
|
432
445
|
}
|
433
446
|
|
434
|
-
|
435
|
-
|
436
|
-
|
447
|
+
if(WR_QUEUE_SIZE(app->q_workers) >= app->conf->min_worker && app->state == WR_APP_RESTART)
|
448
|
+
app->state == WR_APP_ACTIVE;
|
449
|
+
|
450
|
+
// Create worker if application is high loaded
|
451
|
+
/*
|
452
|
+
if(TOTAL_WORKER_COUNT(app) < app->conf->max_worker && WR_QUEUE_SIZE(app->q_messages) > app->high_ratio){
|
437
453
|
wr_app_wkr_add(app);
|
438
|
-
}else{
|
439
|
-
if(app->old_workers){
|
440
|
-
short count, i;
|
441
|
-
// Remove all the old workers, if there is no more workers to add.
|
442
|
-
LOG_DEBUG(DEBUG, "Number of old workers is %d.", app->old_workers);
|
443
|
-
count = WR_QUEUE_SIZE(app->wkr_que);
|
444
|
-
for( i = 0 ; i < count ; i ++){
|
445
|
-
worker = (wr_wkr_t*) wr_queue_fetch(app->wkr_que);
|
446
|
-
wr_queue_insert(app->wkr_que, worker);
|
447
|
-
if(worker->state & WR_WKR_OLD){
|
448
|
-
// Pass flag to remove worker from the worker free list.
|
449
|
-
wr_wkr_remove(worker, 1);
|
450
|
-
app->old_workers --;
|
451
|
-
}
|
452
|
-
}
|
453
|
-
app->old_workers = 0;
|
454
|
-
}
|
455
|
-
|
456
|
-
// Add worker if total number of worker is less than minimum number of workes.
|
457
|
-
if(TOTAL_WORKER_COUNT(app) < app->conf->min_worker){
|
458
|
-
LOG_DEBUG(DEBUG, "Application does not have minimum number of workes.");
|
459
|
-
wr_app_wkr_add(app);
|
460
|
-
}
|
461
|
-
return;
|
462
|
-
}
|
463
|
-
|
464
|
-
// Remove old worker.
|
465
|
-
if(app->old_workers){
|
466
|
-
short count, i;
|
467
|
-
LOG_DEBUG(DEBUG, "Number of old workers is %d.", app->old_workers);
|
468
|
-
count = WR_QUEUE_SIZE(app->wkr_que);
|
469
|
-
for( i = 0 ; i < count ; i ++){
|
470
|
-
worker = (wr_wkr_t*) wr_queue_fetch(app->wkr_que);
|
471
|
-
wr_queue_insert(app->wkr_que, worker);
|
472
|
-
LOG_DEBUG(DEBUG,"Worker PID is %d and state is %d.", worker->pid, worker->state);
|
473
|
-
if(worker->state & WR_WKR_OLD){
|
474
|
-
// Pass flag to remove worker from the worker free list.
|
475
|
-
wr_wkr_remove(worker, 1);
|
476
|
-
app->old_workers --;
|
477
|
-
break;
|
478
|
-
}
|
479
|
-
}
|
480
454
|
}
|
455
|
+
*/
|
481
456
|
}
|
482
457
|
|
483
458
|
/** Add newly created worker to application */
|
484
|
-
int
|
459
|
+
int wr_app_wkr_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl_msg) {
|
485
460
|
LOG_FUNCTION
|
486
|
-
wr_app_t* app = server->apps;
|
487
461
|
const char* app_name = ctl_msg->msg.wkr.app_name.str;
|
462
|
+
wr_app_t* app = wr_app_exist(server, app_name);
|
488
463
|
|
489
|
-
if(
|
490
|
-
|
464
|
+
if(app == NULL){
|
465
|
+
LOG_ERROR(SEVERE, "Either queue is full or Baseuri is not matched");
|
466
|
+
scgi_body_add(worker->ctl->scgi, "Either queue is full or Baseuri is not matched.",
|
467
|
+
strlen("Either queue is full or Baseuri is not matched."));
|
468
|
+
return -1;
|
491
469
|
}
|
492
470
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
if(i == app->pending_wkr) {
|
505
|
-
scgi_body_add(worker->ctl->scgi, "Either worker add timeout or worker PID does not match.",
|
506
|
-
strlen("Either worker add timeout or worker PID does not match."));
|
507
|
-
return -1;
|
508
|
-
}
|
509
|
-
|
510
|
-
for(; i < app->pending_wkr ; i++) {
|
511
|
-
app->last_wkr_pid[i] = app->last_wkr_pid[i+1];
|
512
|
-
}
|
513
|
-
app->last_wkr_pid[i] = 0;
|
514
|
-
app->pending_wkr --;
|
471
|
+
LOG_DEBUG(DEBUG,"app->a_config->max_worker = %d, app->q_workers->q_count =%d", app->conf->max_worker, WR_QUEUE_SIZE(app->q_workers));
|
472
|
+
LOG_DEBUG(DEBUG, "Application name = %s, Application->config->name =%s", app_name, app->conf->name.str );
|
473
|
+
|
474
|
+
if(app->conf->max_worker > WR_QUEUE_SIZE(app->q_workers) || app->state == WR_APP_RESTART) {
|
475
|
+
wr_pending_wkr_t *pending = wr_pending_worker_exist(app, worker->pid);
|
476
|
+
|
477
|
+
if(pending == NULL){
|
478
|
+
scgi_body_add(worker->ctl->scgi, "Either worker add timeout or worker PID does not match.",
|
479
|
+
strlen("Either worker add timeout or worker PID does not match."));
|
480
|
+
return -1;
|
481
|
+
}
|
515
482
|
|
483
|
+
worker->id = ++worker_count;
|
484
|
+
worker->app = app;
|
485
|
+
if(!(worker->state & WR_WKR_ACTIVE)) worker->state += WR_WKR_ACTIVE;
|
516
486
|
|
517
|
-
|
518
|
-
worker->app = app;
|
487
|
+
app->timeout_counter = 0;
|
519
488
|
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
if(app->
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
wr_ctl_resp_write(app->ctl);
|
531
|
-
app->ctl = NULL;
|
532
|
-
}
|
533
|
-
}
|
534
|
-
|
535
|
-
if(app->restarted == TRUE){
|
536
|
-
return wr_app_reload(app);
|
489
|
+
if(WR_QUEUE_SIZE(app->q_pending_workers) <= 0)
|
490
|
+
ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
|
491
|
+
|
492
|
+
if(app->state == WR_APP_RESTART){
|
493
|
+
if(wr_app_reload(app) == FALSE) return -1;
|
494
|
+
if(app->ctl) {
|
495
|
+
LOG_DEBUG(DEBUG,"Send OK status");
|
496
|
+
scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
|
497
|
+
wr_ctl_resp_write(app->ctl);
|
498
|
+
app->ctl = NULL;
|
537
499
|
}
|
538
|
-
|
539
500
|
return 0;
|
540
501
|
}
|
541
|
-
|
502
|
+
|
503
|
+
if(app->state == WR_APP_NEW){
|
504
|
+
if(app->ctl) {
|
505
|
+
LOG_DEBUG(DEBUG,"Send OK status");
|
506
|
+
scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
|
507
|
+
wr_ctl_resp_write(app->ctl);
|
508
|
+
app->ctl = NULL;
|
509
|
+
}
|
510
|
+
|
511
|
+
app->state = WR_APP_ACTIVE;
|
512
|
+
}
|
513
|
+
return 0;
|
542
514
|
}
|
543
|
-
|
544
|
-
scgi_body_add(worker->ctl->scgi, "Either queue is full or Baseuri is not matched.",
|
545
|
-
strlen("Either queue is full or Baseuri is not matched."));
|
515
|
+
|
546
516
|
return -1;
|
547
517
|
}
|
548
518
|
|
@@ -580,7 +550,7 @@ int wr_app_remove(wr_svr_t* server, const char* app_name) {
|
|
580
550
|
/** Check load balance to add the worker */
|
581
551
|
void wr_app_chk_load_to_add_wkr(wr_app_t *app) {
|
582
552
|
if(TOTAL_WORKER_COUNT(app) < app->conf->max_worker) {
|
583
|
-
if(app->
|
553
|
+
if(app->q_messages->q_count > app->high_ratio) {
|
584
554
|
if(!ev_is_active(&app->t_add)) {
|
585
555
|
LOG_DEBUG(DEBUG,"%s() Timer set", __FUNCTION__);
|
586
556
|
ev_timer_again(app->svr->ebb_svr.loop, &app->t_add);
|
@@ -595,8 +565,8 @@ void wr_app_chk_load_to_add_wkr(wr_app_t *app) {
|
|
595
565
|
/** Check load balance to remove the worker */
|
596
566
|
void wr_app_chk_load_to_remove_wkr(wr_app_t *app) {
|
597
567
|
//Check load
|
598
|
-
if(WR_QUEUE_SIZE(app->
|
599
|
-
if(app->
|
568
|
+
if(WR_QUEUE_SIZE(app->q_workers) > app->conf->min_worker) {
|
569
|
+
if(app->q_messages->q_count < app->low_ratio) {
|
600
570
|
if(!ev_is_active(&app->t_remove)) {
|
601
571
|
LOG_DEBUG(DEBUG,"%s() Timer set", __FUNCTION__);
|
602
572
|
ev_timer_again(app->svr->ebb_svr.loop, &app->t_remove);
|
@@ -619,34 +589,27 @@ void wr_app_init(wr_svr_t *server) {
|
|
619
589
|
}
|
620
590
|
}
|
621
591
|
|
622
|
-
/**
|
592
|
+
/** Apllication add callback */
|
593
|
+
/* Deploy an application on the server */
|
623
594
|
void wr_app_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
624
595
|
LOG_FUNCTION
|
625
596
|
|
626
597
|
wr_svr_t* server = ctl->svr;
|
627
598
|
wr_app_conf_t* app_conf = NULL;
|
628
|
-
wr_app_t* app = server
|
629
|
-
|
630
|
-
while(app) {
|
631
|
-
if(strcmp(ctl_msg->msg.app.app_name.str, app->conf->name.str)==0)
|
632
|
-
break;
|
633
|
-
tmp_app = app;
|
634
|
-
app = app->next;
|
635
|
-
}
|
636
|
-
ctl->svr->err_msg[0] = 0;
|
637
|
-
if(app) {
|
638
|
-
/* set application object in control, it would be used at time of freeing control object */
|
639
|
-
ctl->app = app;
|
640
|
-
sprintf(ctl->svr->err_msg, "Application '%s' is already running.", ctl_msg->msg.app.app_name.str);
|
641
|
-
}
|
599
|
+
wr_app_t* app = wr_app_exist(server, ctl_msg->msg.app.app_name.str);
|
642
600
|
|
643
|
-
|
644
|
-
|
601
|
+
// Reset the error message
|
602
|
+
ctl->svr->err_msg[0] = 0;
|
603
|
+
if(app){
|
604
|
+
/* set application object in control, it would be used at time of freeing control object */
|
605
|
+
ctl->app = app;
|
606
|
+
sprintf(ctl->svr->err_msg, "Application '%s' is already running.", ctl_msg->msg.app.app_name.str);
|
607
|
+
}else if(ctl && server && server->conf) {
|
608
|
+
app_conf = wr_conf_app_read(server->conf,
|
645
609
|
ctl_msg->msg.app.app_name.str,
|
646
610
|
ctl->svr->err_msg);
|
647
611
|
if(app_conf!=NULL) {
|
648
|
-
if(wr_app_insert(ctl->svr, app_conf, ctl)
|
649
|
-
return;
|
612
|
+
if(wr_app_insert(ctl->svr, app_conf, ctl) == TRUE) return;
|
650
613
|
} else if(ctl->svr->err_msg[0] == 0) {
|
651
614
|
sprintf(ctl->svr->err_msg, "Application '%s' is not found.", ctl_msg->msg.app.app_name.str);
|
652
615
|
}
|
@@ -670,25 +633,17 @@ void wr_app_remove_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
670
633
|
}
|
671
634
|
|
672
635
|
/** Allication reload callback */
|
673
|
-
void wr_app_reload_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg)
|
636
|
+
void wr_app_reload_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg){
|
674
637
|
LOG_FUNCTION
|
675
|
-
wr_app_t *app = ctl->svr->apps;
|
676
638
|
wr_app_conf_t* app_config = NULL;
|
677
|
-
|
678
|
-
// Find the application.
|
679
|
-
while(app) {
|
680
|
-
if(strcmp(ctl_msg->msg.app.app_name.str, app->conf->name.str)==0){
|
681
|
-
/* set application object in control, it would be used at time of freeing control object */
|
682
|
-
ctl->app = app;
|
683
|
-
break;
|
684
|
-
}
|
685
|
-
app = app->next;
|
686
|
-
}
|
639
|
+
wr_app_t *app = wr_app_exist(ctl->svr, ctl_msg->msg.app.app_name.str);
|
687
640
|
|
688
641
|
// Read new application configuration.
|
689
642
|
app_config = wr_conf_app_update(ctl->svr->conf,
|
690
|
-
|
691
|
-
|
643
|
+
ctl_msg->msg.app.app_name.str,
|
644
|
+
ctl->svr->err_msg);
|
645
|
+
|
646
|
+
LOG_INFO("Reload the application %s", ctl_msg->msg.app.app_name.str);
|
692
647
|
// Report error on not getting the application configuration.
|
693
648
|
if(app_config == NULL){
|
694
649
|
LOG_ERROR(WARN, "Error: %s",ctl->svr->err_msg);
|
@@ -702,26 +657,26 @@ void wr_app_reload_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
702
657
|
}
|
703
658
|
return;
|
704
659
|
}
|
705
|
-
|
706
|
-
if(app)
|
660
|
+
|
661
|
+
if(app){
|
707
662
|
int i;
|
708
663
|
wr_app_conf_t *tmp_app_conf = app->conf;
|
709
664
|
// Set variables to restart the application.
|
710
665
|
LOG_DEBUG(DEBUG,"Set variables to restart an existing application.");
|
711
666
|
app->conf = app_config;
|
712
|
-
app->
|
713
|
-
app->
|
714
|
-
|
715
|
-
|
716
|
-
app->last_wkr_pid[i] = 0;
|
667
|
+
app->state = WR_APP_RESTART;
|
668
|
+
while(WR_QUEUE_SIZE(app->q_pending_workers) > 0){
|
669
|
+
wr_pending_wkr_t* pending = wr_queue_fetch(app->q_pending_workers);
|
670
|
+
free(pending);
|
717
671
|
}
|
672
|
+
|
718
673
|
app->ctl = ctl;
|
719
674
|
LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, app->conf->name.str);
|
720
|
-
|
675
|
+
|
721
676
|
// Add single worker with updated application.
|
722
677
|
LOG_DEBUG(DEBUG, "Add first worker on application restart.");
|
723
678
|
wr_app_wkr_add(app);
|
724
|
-
|
679
|
+
|
725
680
|
// Replace the application configuration with older configuration object.
|
726
681
|
wr_conf_app_replace(app->svr->conf, tmp_app_conf);
|
727
682
|
app->conf = tmp_app_conf;
|
@@ -731,13 +686,13 @@ void wr_app_reload_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
|
|
731
686
|
LOG_ERROR(WARN,"Aapplication %s didn't found in list", ctl_msg->msg.app.app_name.str);
|
732
687
|
sprintf(ctl->svr->err_msg, "Application '%s' is not found.", ctl_msg->msg.app.app_name.str);
|
733
688
|
scgi_body_add(ctl->scgi,
|
734
|
-
|
735
|
-
|
736
|
-
if(wr_app_insert(ctl->svr, app_config, ctl) ==
|
737
|
-
return;
|
689
|
+
"Couldn't remove application. But trying to start application.",
|
690
|
+
strlen("Couldn't remove application. But trying to start application."));
|
691
|
+
if(wr_app_insert(ctl->svr, app_config, ctl) == TRUE) return;
|
738
692
|
}
|
739
693
|
|
740
694
|
// Return ERROR status.
|
741
695
|
scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
|
742
696
|
wr_ctl_resp_write(ctl);
|
743
697
|
}
|
698
|
+
|