webroar 0.3.0 → 0.3.1

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.
@@ -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
+