webroar 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,19 +23,37 @@ static unsigned int worker_count = 0;
23
23
 
24
24
  /************** Private Functions ******************/
25
25
 
26
- static inline int wr_app_fetch_wkr_pid(wr_app_t *app) {
27
- int pid = app->last_wkr_pid[0], i;
28
-
29
- for(i = 0 ; i < (app->pending_wkr-1) ; i ++) {
30
- app->last_wkr_pid[i] = app->last_wkr_pid[i+1];
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
- app->last_wkr_pid[i] = 0;
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
- return pid;
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 wr_app_wrk_add_cb(struct ev_loop *loop, ev_timer *w, int revents) {
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 wr_app_wrk_add_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
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
- // Decreament active worker count
60
- if(app->pending_wkr > 0) {
61
- // Kill worker
62
- int pid = wr_app_fetch_wkr_pid(app);
63
- LOG_INFO("wr_app_wrk_add_timeout_cb: killing worker, pid = %d", pid);
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->pending_wkr);
67
- app->pending_wkr --;
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
- //TODO: Check minimum no. of workers and, create worker if needed.
77
- // Also, do not OK if some worker were failed to connect.
78
- // For timebeing sending OK even if some worker failed to connect.
79
- if(app->in_use == FALSE && app->ctl && app->pending_wkr == 0) {
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
- scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
82
- 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);
83
- scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
84
- wr_ctl_resp_write(app->ctl);
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
- if(app->restarted == TRUE){
87
- app->old_workers = 0;
88
- app->add_workers = 0;
89
- app->restarted = FALSE;
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
- //Remove application from the server application list, otherwise it won't allow to add the application with same name, unless stopping it
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 wr_app_wrk_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
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 wr_app_wrk_remove_cb
106
- int forecasted_count=app->wkr_que->q_count;
107
- // Its a known bug - At any time app->active_worker should equals to app->wkr_que->q_count
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->wkr_que->q_count = %d",
121
- app->pending_wkr, app->wkr_que->q_count);
122
- if(app->wkr_que->q_count > app->conf->min_worker) {
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->wkr_que->q_front + i) % app->wkr_que->q_max_size;
128
- wr_wkr_t *tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
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->wkr_que->q_count ; i++) {
151
- index = (app->wkr_que->q_front + i) % app->wkr_que->q_max_size;
152
- tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
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->free_wkr_que->q_count > 0) {
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->free_wkr_que->q_count ; i++) {
175
- index = (app->free_wkr_que->q_front + i) % app->free_wkr_que->q_max_size;
176
- tmp_worker = (wr_wkr_t*)app->free_wkr_que->q_elements[index];
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->wkr_que->q_count > 0) {
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->wkr_que->q_count ; i++) {
194
- index = (app->wkr_que->q_front + i) % app->wkr_que->q_max_size;
195
- tmp_worker = (wr_wkr_t*)app->wkr_que->q_elements[index];
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
- scgi_body_add(app->ctl->scgi, app->svr->err_msg, strlen(app->svr->err_msg));
231
- scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
232
- wr_ctl_resp_write(app->ctl);
233
- return -1;
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->free_wkr_que), WR_QUEUE_SIZE(app->wkr_que));
250
- LOG_DEBUG(DEBUG,"The %d worker(s) to be removed from free workers list.", WR_QUEUE_SIZE(app->free_wkr_que) - count);
251
- while(WR_QUEUE_SIZE(app->free_wkr_que) > count){
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->old_workers ; count++) {
263
- worker = (wr_wkr_t*)wr_queue_fetch(app->wkr_que);
264
- wr_queue_insert(app->wkr_que, worker);
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
- LOG_DEBUG(DEBUG,"Number of old and add workers are %d and %d respectively", app->old_workers, app->add_workers);
269
- return 0;
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->in_use = FALSE;
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->wkr_que));
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->wkr_que)) {
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->free_wkr_que);
295
- wr_queue_free(app->wkr_que);
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->msg_que, req) ;
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->msg_que, req) ;
337
+ WR_QUEUE_FETCH(app->q_messages, req) ;
302
338
  }
303
339
 
304
- wr_queue_free(app->msg_que);
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->pending_wkr < WR_MAX_PENDING_WKR) {
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
- app->pending_wkr++;
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
- app->last_wkr_pid[app->pending_wkr-1],app->conf->path.str);
336
- return 0;
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 -1;
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 -1;
388
+ return FALSE;
353
389
  }
354
390
 
355
- if(strcmp(config->name.str, WR_STATIC_FILE_SERVER_NAME) == 0){
356
- is_static_server = 1;
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
- // Queue size is WR_ALLOWED_MAX_WORKERS + 1 to accommodate temporary extra worker, created during application restart
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( app->wkr_que == NULL ||
365
- app->free_wkr_que == NULL ||
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 -1;
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
- ctl->app = app;
378
- }
379
- if(!is_static_server){
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.data = app->t_remove.data = app->t_add_timeout.data = app;
389
-
390
- ev_timer_init (&app->t_add, wr_app_wrk_add_cb, 0., WR_HIGH_LOAD_LIMIT);
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->pending_wkr = 0;
399
- app->in_use = FALSE;
400
- app->restarted = FALSE;
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
- /** Worker added to application callback */
424
- void wr_app_wkr_added_cb(wr_app_t *app){
425
- LOG_FUNCTION
426
- wr_wkr_t *worker;
427
-
428
- // Decrease the add workers count.
429
- if(app->add_workers){
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
- // Add a worker if required.
435
- if(app->add_workers){
436
- LOG_DEBUG(DEBUG,"Add a worker to a reloaded application.");
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 wr_app_wrk_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl_msg) {
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(strcmp(app_name, WR_STATIC_FILE_SERVER_NAME) == 0){
490
- app = server->static_app;
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
- while(app) {
494
- LOG_DEBUG(DEBUG,"app->a_config->max_worker = %d, app->wkr_que->q_count =%d", app->conf->max_worker, WR_QUEUE_SIZE(app->wkr_que));
495
- LOG_DEBUG(DEBUG, "Application name = %s, Application->config->name =%s", app_name, app->conf->name.str );
496
- if((app->conf->max_worker > WR_QUEUE_SIZE(app->wkr_que) || app->restarted == TRUE || app->add_workers > 0)
497
- && strcmp(app_name, app->conf->name.str) == 0) {
498
- int i;
499
- for(i = 0; i < app->pending_wkr ; i++) {
500
- if(app->last_wkr_pid[i] == worker->pid)
501
- break;
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
- worker->id = ++worker_count;
518
- worker->app = app;
487
+ app->timeout_counter = 0;
519
488
 
520
- if(app->pending_wkr <= 0)
521
- ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
522
- if(!(worker->state& WR_WKR_ACTIVE))
523
- worker->state += WR_WKR_ACTIVE;
524
-
525
- if(app->in_use == FALSE) {
526
- app->in_use = TRUE;
527
- if(app->ctl) {
528
- LOG_DEBUG(DEBUG,"Send OK status");
529
- scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
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
- app = app->next;
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
- LOG_ERROR(SEVERE, "Either queue is full or Baseuri is not matched");
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->msg_que->q_count > app->high_ratio) {
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->wkr_que) > app->conf->min_worker) {
599
- if(app->msg_que->q_count < app->low_ratio) {
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
- /** Allication add callback */
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->apps, *tmp_app = NULL;
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
- if(!app && ctl && ctl->svr && ctl->svr->conf) {
644
- app_conf = wr_conf_app_read(ctl->svr->conf,
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) >= 0)
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
- ctl_msg->msg.app.app_name.str,
691
- ctl->svr->err_msg);
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->in_use = FALSE;
713
- app->restarted = TRUE;
714
- app->pending_wkr = 0;
715
- for(i = 0; i < WR_MAX_PENDING_WKR ; i ++) {
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
- "Couldn't remove application. But trying to start application.",
735
- strlen("Couldn't remove application. But trying to start application."));
736
- if(wr_app_insert(ctl->svr, app_config, ctl) == 0)
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
+