webroar 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/CHANGELOG +48 -1
  2. data/README +11 -14
  3. data/Rakefile +1 -1
  4. data/conf/mime_type.yml +172 -166
  5. data/conf/server_internal_config.yml +30 -8
  6. data/doc/user-guide.html +294 -153
  7. data/doc/user-guide.txt +9 -13
  8. data/lib/command_runner.rb +1 -0
  9. data/lib/dependencies.rb +18 -15
  10. data/lib/installer.rb +115 -50
  11. data/src/admin_panel/app/controllers/admin_controller.rb +1 -15
  12. data/src/admin_panel/app/controllers/application_controller.rb +2 -2
  13. data/src/admin_panel/app/controllers/application_specification_controller.rb +2 -1
  14. data/src/admin_panel/app/controllers/headers_controller.rb +73 -0
  15. data/src/admin_panel/app/controllers/mail_specification_controller.rb +10 -0
  16. data/src/admin_panel/app/controllers/server_specification_controller.rb +14 -0
  17. data/src/admin_panel/app/helpers/admin_helper.rb +0 -85
  18. data/src/admin_panel/app/models/app.rb +1 -1
  19. data/src/admin_panel/app/models/application_specification.rb +33 -25
  20. data/src/admin_panel/app/models/headers.rb +116 -0
  21. data/src/admin_panel/app/models/mail_specification.rb +20 -5
  22. data/src/admin_panel/app/models/server_specification.rb +2 -7
  23. data/src/admin_panel/app/views/admin/configuration.html.erb +10 -5
  24. data/src/admin_panel/app/views/exceptions/_exception_list_partial.html.erb +4 -4
  25. data/src/admin_panel/app/views/graph/_graph_page.html.erb +3 -0
  26. data/src/admin_panel/app/views/headers/_add_expires_text_box.html.erb +35 -0
  27. data/src/admin_panel/app/views/headers/_expires_by_type_form.html.erb +65 -0
  28. data/src/admin_panel/app/views/headers/_headers_table.html.erb +113 -0
  29. data/src/admin_panel/app/views/mail_specification/_current_spec.html.erb +168 -0
  30. data/src/admin_panel/app/views/{admin → server_specification}/_add_div.html.erb +1 -1
  31. data/src/admin_panel/config/initializers/application_constants.rb +6 -0
  32. data/src/admin_panel/lib/control.rb +6 -3
  33. data/src/admin_panel/lib/scgi.rb +74 -21
  34. data/src/admin_panel/lib/yaml_writer.rb +51 -17
  35. data/src/admin_panel/public/javascripts/application.js +20 -1
  36. data/src/head/wr_access_log.c +2 -2
  37. data/src/head/wr_application.c +294 -236
  38. data/src/head/wr_application.h +8 -8
  39. data/src/head/wr_configurator.c +451 -517
  40. data/src/head/wr_configurator.h +10 -115
  41. data/src/head/wr_connection.c +26 -25
  42. data/src/head/wr_connection.h +2 -3
  43. data/src/head/wr_controller.c +110 -93
  44. data/src/head/wr_controller.h +6 -6
  45. data/src/head/wr_main.c +31 -24
  46. data/src/head/wr_request.c +70 -93
  47. data/src/head/wr_request.h +0 -4
  48. data/src/head/wr_resolver.c +21 -15
  49. data/src/head/wr_resolver.h +2 -2
  50. data/src/head/wr_server.c +36 -26
  51. data/src/head/wr_server.h +5 -5
  52. data/src/head/wr_worker.c +551 -512
  53. data/src/head/wr_worker.h +33 -20
  54. data/src/helper/wr_config.c +316 -0
  55. data/src/helper/wr_config.h +235 -0
  56. data/src/helper/wr_helper.h +1 -5
  57. data/src/helper/wr_logger.c +4 -4
  58. data/src/helper/wr_scgi.c +3 -4
  59. data/src/helper/wr_scgi.h +2 -0
  60. data/src/helper/wr_string.h +2 -2
  61. data/src/helper/wr_util.c +3 -1
  62. data/src/helper/wr_util.h +0 -0
  63. data/src/helper/wr_yaml_parser.c +30 -0
  64. data/src/helper/wr_yaml_parser.h +1 -0
  65. data/src/ruby_lib/exception_tracker/instrumentation/action_controller.rb +2 -1
  66. data/src/ruby_lib/mailer/smtpmail.rb +7 -4
  67. data/src/ruby_lib/profiler/instrumentation/action_controller.rb +2 -1
  68. data/src/ruby_lib/profiler/instrumentation/active_record.rb +3 -0
  69. data/src/ruby_lib/rack/adapter/rails.rb +14 -7
  70. data/src/ruby_lib/ruby_interface/client.rb +1 -1
  71. data/src/ruby_lib/ruby_interface/version.rb +2 -2
  72. data/src/ruby_lib/webroar_app_loader.rb +4 -2
  73. data/src/worker/wkr_controller.c +200 -140
  74. data/src/worker/wkr_http.c +14 -28
  75. data/src/worker/wkr_http.h +4 -4
  76. data/src/worker/wkr_http_request.c +12 -11
  77. data/src/worker/wkr_http_request.h +7 -8
  78. data/src/worker/wkr_http_response.c +10 -14
  79. data/src/worker/wkr_http_response.h +0 -1
  80. data/src/worker/wkr_main.c +74 -140
  81. data/src/worker/wkr_static.c +295 -108
  82. data/src/worker/wkr_static.h +20 -7
  83. data/src/worker/worker.c +245 -70
  84. data/src/worker/worker.h +46 -34
  85. data/tasks/compile.rake +128 -175
  86. data/tasks/test.rake +345 -469
  87. data/test/spec/webroar_command_spec.rb +23 -0
  88. metadata +173 -43
  89. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/README +0 -34
  90. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/Rakefile +0 -13
  91. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/init.rb +0 -5
  92. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/action_mailer_tls.rb +0 -16
  93. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/lib/smtp_tls.rb +0 -123
  94. data/src/admin_panel/vendor/plugins/action_mailer_optional_tls/test/tls_test.rb +0 -42
  95. data/src/head/wr_config.h +0 -165
  96. data/src/ruby_lib/mailer/action_mailer_tls.rb +0 -16
  97. data/src/ruby_lib/mailer/smtp_tls.rb +0 -123
@@ -20,21 +20,20 @@
20
20
 
21
21
  // Worker count
22
22
  static unsigned int worker_count = 0;
23
+ extern config_t *Config;
23
24
 
24
25
  /************** Private Functions ******************/
25
26
 
26
27
  // 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* wr_app_exist(wr_svr_t *server, const char *app_name){
28
29
  wr_app_t* app = server->apps, *tmp_app = NULL;
29
-
30
30
  while(app) {
31
31
  if(strcmp(app_name, app->conf->name.str)==0)
32
32
  return app;
33
33
  tmp_app = app;
34
34
  app = app->next;
35
35
  }
36
-
37
- if(strcmp(app_name, WR_STATIC_FILE_SERVER_NAME) == 0){
36
+ if(strcmp(app_name, Config->Application.Static_server.name.str) == 0){
38
37
  return server->static_app;
39
38
  }
40
39
 
@@ -42,7 +41,7 @@ static inline wr_app_t* wr_app_exist(wr_svr_t *server, const char *app_name){
42
41
  }
43
42
 
44
43
  // Check whether pending worker exist
45
- static inline wr_pending_wkr_t* wr_pending_worker_exist(wr_app_t *app, const int pid){
44
+ wr_pending_wkr_t* wr_pending_worker_exist(wr_app_t *app, const int pid){
46
45
  int i;
47
46
  for(i = 0 ; i < WR_QUEUE_SIZE(app->q_pending_workers); i++){
48
47
  wr_pending_wkr_t* pending = wr_queue_fetch(app->q_pending_workers);
@@ -64,69 +63,121 @@ void wr_app_wkr_add_cb(struct ev_loop *loop, ev_timer *w, int revents) {
64
63
  }
65
64
  }
66
65
 
66
+ /** Set flag to TRUE to kill single pending worker */
67
+ void wr_app_kill_pending_wkr(wr_app_t* app, const int flag){
68
+ int pid = 0;
69
+ wr_pending_wkr_t *pending;
70
+
71
+ while(WR_QUEUE_SIZE(app->q_pending_workers) > 0) {
72
+ pending = wr_queue_fetch(app->q_pending_workers);
73
+ if(pending){
74
+ pid = *pending;
75
+ free(pending);
76
+ }
77
+ LOG_INFO("wr_app_kill_pending_wkr: killing worker, pid = %d", pid);
78
+ if(pid > 0)
79
+ kill(pid ,SIGKILL);
80
+ if(flag) break;
81
+ }
82
+ app->high_ratio = TOTAL_WORKER_COUNT(app) * Config->Application.max_req_ratio;
83
+ }
84
+
85
+ void wr_app_add_error_msg(wr_app_t* app){
86
+ int err_msg_len = 0;
87
+ char err_msg[512];
88
+
89
+ LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
90
+ if(app->ctl){
91
+ scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
92
+ 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);
93
+ scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
94
+ wr_ctl_resp_write(app->ctl);
95
+ }
96
+ app->timeout_counter = 0;
97
+ app->ctl = NULL;
98
+ }
99
+
100
+ /** Remove application from application list */
101
+ int wr_app_remove(wr_svr_t* server, const char* app_name) {
102
+ LOG_FUNCTION
103
+ wr_app_t* app = server->apps, *tmp_app = NULL;
104
+
105
+ LOG_DEBUG(DEBUG, "Removing application %s", app_name);
106
+
107
+ while(app) {
108
+ if(strcmp(app_name, app->conf->name.str)==0)
109
+ break;
110
+ tmp_app = app;
111
+ app = app->next;
112
+ }
113
+ if(app) {
114
+ if(tmp_app) {
115
+ tmp_app->next = app->next;
116
+ } else {
117
+ server->apps = app->next;
118
+ }
119
+
120
+ app->next = NULL;
121
+ wr_app_free(app);
122
+ wr_app_conf_remove(app_name);
123
+ return 0;
124
+ } else if(strcmp(app_name, Config->Application.Static_server.name.str) == 0){
125
+ wr_app_free(server->static_app);
126
+ server->static_app = NULL;
127
+ wr_app_conf_remove(app_name);
128
+ return 0;
129
+ } else {
130
+ LOG_ERROR(WARN,"Aapplication %s didn't found in list", app_name);
131
+ sprintf(server->err_msg, "Application '%s' is not found.", app_name);
132
+ return -1;
133
+ }
134
+ }
135
+
67
136
  /** Callback function to add worker timeout */
68
137
  void wr_app_wkr_add_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
69
138
  LOG_FUNCTION
70
139
  wr_app_t* app = (wr_app_t*) w->data;
71
- char err_msg[512];
72
- int err_msg_len = 0;
73
- int pid = 0;
74
140
 
141
+ LOG_ERROR(SEVERE,"wr_app_wkr_add_timeout_cb");
142
+
75
143
  // Stop add timeout timer and increament timeout counter
76
144
  ev_timer_stop(loop, &app->t_add_timeout);
77
145
  app->timeout_counter ++;
78
146
 
147
+ if(app->timeout_counter > Config->Server.Worker.add_trials){
148
+ LOG_ERROR(SEVERE,"Reset worker timeout counter for %s.", app->conf->name.str);
149
+ app->timeout_counter = 0;
150
+ return;
151
+ }else if(app->timeout_counter == Config->Server.Worker.add_trials){
152
+ LOG_ERROR(SEVERE,"worker timeout counter for %s exceeds limit.", app->conf->name.str);
153
+
154
+ app->timeout_counter ++;
155
+
156
+ wr_app_kill_pending_wkr(app, FALSE);
157
+
158
+ app->t_add_timeout.repeat = Config->Server.Worker.add_wait;
159
+ ev_timer_again(loop, &app->t_add_timeout);
160
+ }
161
+
79
162
  // 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);
87
- if(pid > 0)
88
- kill(pid ,SIGKILL);
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) {
91
- ev_timer_again(loop, &app->t_add_timeout);
92
- }
163
+ wr_app_kill_pending_wkr(app, TRUE);
93
164
 
94
- // Update high load ratio
95
- app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
165
+ if(WR_QUEUE_SIZE(app->q_pending_workers) > 0) {
166
+ ev_timer_again(loop, &app->t_add_timeout);
96
167
  }
97
168
 
98
169
  // If application restarted, rollback all the changes.
99
170
  if(app->state == WR_APP_RESTART){
171
+ wr_application_list_free(app->conf->new);
172
+ app->conf->new = NULL;
100
173
  app->state = WR_APP_ACTIVE;
101
174
  // Send error response
102
- LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
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;
110
- app->ctl = NULL;
175
+ wr_app_add_error_msg(app);
111
176
  return;
112
177
  }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
178
  if(WR_QUEUE_SIZE(app->q_pending_workers) == 0){
120
179
  // 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;
180
+ wr_app_add_error_msg(app);
130
181
  wr_app_remove(app->svr, app->conf->name.str);
131
182
  }
132
183
  return;
@@ -160,8 +211,8 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
160
211
  LOG_DEBUG(DEBUG,"Pending_wkr = %d, app->q_workers->q_count = %d",
161
212
  WR_QUEUE_SIZE(app->q_pending_workers), WR_QUEUE_SIZE(app->q_workers));
162
213
  if(app->q_workers->q_count > app->conf->min_worker) {
163
- char cmd[WR_LONG_LONG_STR_LEN];
164
- char pid_list[WR_LONG_LONG_STR_LEN], pid_c[WR_SHORT_STR_LEN];
214
+ char cmd[STR_SIZE512];
215
+ char pid_list[STR_SIZE512], pid_c[STR_SIZE32];
165
216
  int i,index;
166
217
  i = 0;
167
218
  index = (app->q_workers->q_front + i) % app->q_workers->q_max_size;
@@ -170,7 +221,7 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
170
221
 
171
222
  // Get pid of the worker consuming more resident memory
172
223
  #ifdef __APPLE__
173
- //sprintf(cmd,"ps -o pid -m -p %s | head -n2 | tail -n1 | cut -c-6 > %s",pid_list, WR_HIGH_RSS_PID_FILE);
224
+ //sprintf(cmd,"ps -o pid -m -p %s | head -n2 | tail -n1 | cut -c-6 > %s",pid_list, Config->Server.File.high_rss.str);
174
225
  /* TODO: when any shell command is executed using system(), process goes into wait state. It is
175
226
  observed on only Mac. When tried calling syste() at various interval like after port binding,
176
227
  controller initialization, forking required worker, daemonizing, activating event loop etc, in all
@@ -178,7 +229,7 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
178
229
  goes into infinite wait.
179
230
  In this case we would simply pick the first worker from queue and remove it.
180
231
  */
181
- FILE *wfp = fopen(WR_HIGH_RSS_PID_FILE, "w");
232
+ FILE *wfp = fopen(Config->Server.File.high_rss.str, "w");
182
233
  if(wfp) {
183
234
  fprintf(wfp,"%d", tmp_worker->pid);
184
235
  fclose(wfp);
@@ -193,18 +244,18 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
193
244
  sprintf(pid_c,",%d", tmp_worker->pid);
194
245
  strcat(pid_list, pid_c);
195
246
  }
196
- sprintf(cmd,"ps -o pid --sort=rss -p %s | tail -n1 | cut -c-6 > %s",pid_list, WR_HIGH_RSS_PID_FILE);
247
+ sprintf(cmd,"ps -o pid --sort=rss -p %s | tail -n1 | cut -c-6 > %s",pid_list, Config->Server.File.high_rss.str);
197
248
  LOG_DEBUG(DEBUG,"Formed command to remove worker is %s",cmd);
198
249
  system(cmd);
199
250
  #endif
200
251
 
201
252
  // Read pid from file
202
- FILE *fp = fopen(WR_HIGH_RSS_PID_FILE, "r");
253
+ FILE *fp = fopen(Config->Server.File.high_rss.str, "r");
203
254
  if(fp) {
204
255
  unsigned pid = 0;
205
256
  fscanf(fp, "%u", &pid);
206
257
  fclose(fp);
207
- remove(WR_HIGH_RSS_PID_FILE);
258
+ remove(Config->Server.File.high_rss.str);
208
259
  int flag = 1;
209
260
 
210
261
  // Check for worker in list of free workers. If found remove it.
@@ -217,7 +268,8 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
217
268
  if(tmp_worker->pid == pid) {
218
269
  LOG_DEBUG(DEBUG,"Removing from free worker id=%d", tmp_worker->id);
219
270
  forecasted_count--;
220
- wr_wkr_remove(tmp_worker, 1);
271
+ tmp_worker->state = WKR_STATE_ERROR;
272
+ wr_wkr_free(tmp_worker);
221
273
  LOG_DEBUG(DEBUG,"Worker removed from free worker.");
222
274
  flag = 0;
223
275
  break;
@@ -236,8 +288,7 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
236
288
  if(tmp_worker->pid == pid) {
237
289
  forecasted_count--;
238
290
  LOG_DEBUG(DEBUG,"Remove active status id = %d", tmp_worker->id);
239
- if(tmp_worker->state & WR_WKR_ACTIVE)
240
- tmp_worker->state -= WR_WKR_ACTIVE;
291
+ tmp_worker->state = WKR_STATE_EXPIRED;
241
292
  break;
242
293
  }
243
294
  }
@@ -251,37 +302,19 @@ void wr_app_wkr_remove_cb(struct ev_loop *loop, ev_timer *w, int revents) {
251
302
  }
252
303
 
253
304
  /** Reload the application */
254
- static inline int wr_app_reload(wr_app_t *app){
305
+ int wr_app_reload(wr_app_t *app){
255
306
  LOG_FUNCTION
256
307
  wr_wkr_t *worker;
257
- wr_app_conf_t *app_conf;
258
308
  short count;
259
309
 
260
310
  // Remove an old application from the resolver list.
261
311
  wr_req_resolver_remove(app->svr, app);
262
312
 
263
313
  // Update the application configuration.
264
- app_conf = wr_conf_app_update(app->svr->conf,
265
- app->conf->name.str,
266
- app->svr->err_msg);
267
- if(app_conf == NULL){
268
- LOG_DEBUG(WARN, "Error: %s",app->svr->err_msg);
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;
276
- }
277
-
278
- // Remove old application specification.
279
- app->conf->next = NULL;
280
- wr_conf_app_free(app->conf);
281
- app->conf = app_conf;
282
-
314
+ wr_conf_app_update(app->conf);
315
+
283
316
  // Add the updated application to resolver list.
284
- wr_req_resolver_add(app->svr, app, app_conf);
317
+ wr_req_resolver_add(app->svr, app);
285
318
 
286
319
  // Remove workers based on following logic:
287
320
  // If all the workers are free keep a single worker to process the requests and remove all others.
@@ -291,85 +324,44 @@ static inline int wr_app_reload(wr_app_t *app){
291
324
  while(WR_QUEUE_SIZE(app->q_free_workers) > 0){
292
325
  worker = (wr_wkr_t*)wr_queue_fetch(app->q_free_workers);
293
326
  // The worker is already removed from free workers list so do not pass the flag.
294
- wr_wkr_remove(worker, 0);
327
+ worker->state = WKR_STATE_ERROR;
328
+ wr_wkr_free(worker);
295
329
  }
296
330
 
297
331
  // Mark all existing workers to OLD worker.
298
332
  for(count = 0; count < WR_QUEUE_SIZE(app->q_workers) ; count++) {
299
333
  worker = (wr_wkr_t*)wr_queue_fetch(app->q_workers);
300
334
  wr_queue_insert(app->q_workers, worker);
301
- worker->state |= WR_WKR_OLD;
302
- worker->state -= WR_WKR_ACTIVE;
335
+ worker->state = WKR_STATE_EXPIRED;
303
336
  }
304
337
 
305
338
  app->state = WR_APP_RESTARTING;
306
339
  return TRUE;
307
340
  }
308
341
 
309
- /*************** Application function definition *********/
310
-
311
- /** Destroy application */
312
- void wr_app_free(wr_app_t* app) {
313
- LOG_FUNCTION
314
- wr_app_t* tmp_app;
315
- wr_wkr_t* worker;
316
-
317
- while(app) {
318
- tmp_app = app->next;
319
- app->state = WR_APP_DESTROY;
320
- LOG_DEBUG(4,"Destroying application %s...", app->conf->name.str);
321
- LOG_DEBUG(DEBUG,"Worker count = %d", WR_QUEUE_SIZE(app->q_workers));
322
- //Destroy workers
323
- while(worker = (wr_wkr_t*)wr_queue_fetch(app->q_workers)) {
324
- if(app->svr->is_running==0)
325
- worker->state |= WR_WKR_HANG;
326
- wr_wkr_free(worker);
327
- }
328
-
329
- wr_queue_free(app->q_free_workers);
330
- wr_queue_free(app->q_workers);
331
- wr_queue_free(app->q_pending_workers);
332
-
333
- wr_req_t *req;
334
- WR_QUEUE_FETCH(app->q_messages, req) ;
335
- while(req) {
336
- wr_conn_err_resp(req->conn, WR_HTTP_STATUS_500);
337
- WR_QUEUE_FETCH(app->q_messages, req) ;
338
- }
339
-
340
- wr_queue_free(app->q_messages);
341
-
342
- wr_req_resolver_remove(app->svr, app);
343
-
344
- ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add);
345
- ev_timer_stop(app->svr->ebb_svr.loop, &app->t_remove);
346
- ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
347
-
348
- free(app);
349
- app = tmp_app;
350
- }
351
- }
352
-
353
- /** Display application structure */
354
- void wr_app_print(wr_app_t*app) {
355
- while(app) {
356
- LOG_DEBUG(4,"Application %s", app->conf->name.str);
357
- app = app->next;
358
- }
359
- }
360
-
361
342
  /** Create worker for application */
362
343
  int wr_app_wkr_add(wr_app_t *app) {
363
344
  if(WR_QUEUE_SIZE(app->q_pending_workers) < WR_QUEUE_MAX_SIZE(app->q_pending_workers)) {
364
- int retval = wr_wkr_create(app->svr, app->conf);
345
+ if(app->timeout_counter >= Config->Server.Worker.add_trials){
346
+ LOG_ERROR(SEVERE, "Could not fork worker because previous %d workers got timed out.",
347
+ Config->Server.Worker.add_trials);
348
+ return FALSE;
349
+ }
350
+ config_application_list_t *conf = app->conf;
351
+
352
+ if(app->state == WR_APP_RESTART) conf = app->conf->new;
353
+
354
+ int retval = wr_wkr_create(app->svr, conf);
365
355
  if(retval > 0){
366
356
  wr_pending_wkr_t *pending = wr_malloc(wr_pending_wkr_t);
367
357
  *pending = retval;
368
358
  wr_queue_insert(app->q_pending_workers, pending);
369
- app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
370
- ev_timer_again(app->svr->ebb_svr.loop, &app->t_add_timeout);
371
- LOG_INFO("PID of created worker = %d, Rails application=%s",
372
- retval, app->conf->path.str);
359
+ app->high_ratio = TOTAL_WORKER_COUNT(app) * Config->Application.max_req_ratio;
360
+ if (Config->Server.Worker.add_timeout > 0) {
361
+ ev_timer_again(app->svr->ebb_svr.loop, &app->t_add_timeout);
362
+ }
363
+
364
+ LOG_INFO("PID of created worker = %d", retval);
373
365
  return TRUE;
374
366
  }else{
375
367
  LOG_ERROR(SEVERE,"Could not fork process to start new worker.");
@@ -379,23 +371,23 @@ int wr_app_wkr_add(wr_app_t *app) {
379
371
  }
380
372
 
381
373
  /** Insert application based on application configuration */
382
- static int wr_app_insert(wr_svr_t* server, wr_app_conf_t* config, wr_ctl_t *ctl) {
374
+ int wr_app_insert(wr_svr_t* server, config_application_list_t* config, wr_ctl_t *ctl) {
383
375
  LOG_FUNCTION
384
376
  wr_app_t* app = wr_malloc(wr_app_t);
385
-
377
+
386
378
  if(!app) {
387
379
  LOG_ERROR(WARN, "%s() application object allocation failed. Returning ...", __FUNCTION__);
388
380
  return FALSE;
389
381
  }
390
-
391
- // Queue size is WR_ALLOWED_MAX_WORKERS + 1 to accommodate temporary extra
382
+
383
+ // Queue size is Config->Server.Worker.max + 1 to accommodate temporary extra
392
384
  // 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);
396
-
397
- app->q_messages = wr_queue_new(WR_MSG_QUE_SIZE);
398
-
385
+ app->q_free_workers = wr_queue_new(Config->Server.Worker.max + 1);
386
+ app->q_workers = wr_queue_new(Config->Server.Worker.max + 1);
387
+ app->q_pending_workers = wr_queue_new(Config->Server.Worker.pending);
388
+
389
+ app->q_messages = wr_queue_new(Config->Application.msg_queue_size);
390
+
399
391
  if(app->q_workers == NULL || app->q_pending_workers == NULL ||
400
392
  app->q_free_workers == NULL || app->q_messages == NULL) {
401
393
  free(app);
@@ -415,19 +407,21 @@ static int wr_app_insert(wr_svr_t* server, wr_app_conf_t* config, wr_ctl_t *ctl)
415
407
  /* set application object in control, it would be used at time of freeing control object */
416
408
  if(ctl) ctl->app = app;
417
409
 
418
- if(strcmp(config->name.str, WR_STATIC_FILE_SERVER_NAME) == 0){
410
+ if(strcmp(config->name.str, Config->Application.Static_server.name.str) == 0){
419
411
  app->next = NULL;
420
412
  server->static_app = app;
421
413
  }else{
422
- wr_req_resolver_add(server, app, config);
414
+ wr_req_resolver_add(server, app);
423
415
  app->next = server->apps;
424
416
  server->apps = app;
425
417
  }
426
-
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);
430
-
418
+
419
+ ev_timer_init (&app->t_add, wr_app_wkr_add_cb, 0., Config->Application.high_load);
420
+ ev_timer_init (&app->t_remove, wr_app_wkr_remove_cb, 0., Config->Application.low_load);
421
+ if (Config->Server.Worker.add_timeout > 0) {
422
+ ev_timer_init (&app->t_add_timeout, wr_app_wkr_add_timeout_cb, 0., Config->Server.Worker.add_timeout);
423
+ }
424
+
431
425
  LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, config->name.str);
432
426
 
433
427
  wr_app_wkr_balance(app);
@@ -435,17 +429,73 @@ static int wr_app_insert(wr_svr_t* server, wr_app_conf_t* config, wr_ctl_t *ctl)
435
429
  return TRUE;
436
430
  }
437
431
 
432
+ /*************** Application function definition *********/
433
+
434
+ /** Destroy application */
435
+ void wr_app_free(wr_app_t* app) {
436
+ LOG_FUNCTION
437
+ wr_app_t* tmp_app;
438
+ wr_wkr_t* worker;
439
+
440
+ while(app) {
441
+ tmp_app = app->next;
442
+ app->state = WR_APP_DESTROY;
443
+ LOG_DEBUG(4,"Destroying application %s...", app->conf->name.str);
444
+ LOG_DEBUG(DEBUG,"Worker count = %d", WR_QUEUE_SIZE(app->q_workers));
445
+ //Destroy workers
446
+ while(worker = (wr_wkr_t*)wr_queue_fetch(app->q_workers)) {
447
+ if(app->svr->is_running == 0)
448
+ worker->state = WKR_STATE_ERROR;
449
+ wr_wkr_free(worker);
450
+ }
451
+
452
+ wr_queue_free(app->q_free_workers);
453
+ wr_queue_free(app->q_workers);
454
+ wr_queue_free(app->q_pending_workers);
455
+
456
+ wr_req_t *req;
457
+ WR_QUEUE_FETCH(app->q_messages, req) ;
458
+ while(req) {
459
+ wr_conn_err_resp(req->conn, WR_HTTP_STATUS_500);
460
+ WR_QUEUE_FETCH(app->q_messages, req) ;
461
+ }
462
+
463
+ wr_queue_free(app->q_messages);
464
+
465
+ wr_req_resolver_remove(app->svr, app);
466
+
467
+ ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add);
468
+ ev_timer_stop(app->svr->ebb_svr.loop, &app->t_remove);
469
+ if (Config->Server.Worker.add_timeout > 0) {
470
+ ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
471
+ }
472
+ free(app);
473
+ app = tmp_app;
474
+ }
475
+ }
476
+
477
+ /** Display application structure */
478
+ void wr_app_print(wr_app_t*app) {
479
+ while(app) {
480
+ LOG_DEBUG(4,"Application %s", app->conf->name.str);
481
+ app = app->next;
482
+ }
483
+ }
484
+
438
485
  /** Balance number of workers */
439
486
  void wr_app_wkr_balance(wr_app_t *app){
440
487
  // Maintain minimum number of workers
441
- //while(TOTAL_WORKER_COUNT(app) < app->conf->min_worker && app->timeout_counter < WR_MAX_ADD_TIMEOUT_COUNTER){
488
+ //while(TOTAL_WORKER_COUNT(app) < app->conf->min_worker && app->timeout_counter < Config->Server.Worker.add_trials){
442
489
  while(TOTAL_WORKER_COUNT(app) < app->conf->min_worker){
443
490
  if(wr_app_wkr_add(app) == FALSE) break;
444
- app->low_ratio = TOTAL_WORKER_COUNT(app) * WR_MIN_REQ_RATIO;
491
+ app->low_ratio = TOTAL_WORKER_COUNT(app) * Config->Application.min_req_ratio;
445
492
  }
446
493
 
447
- if(WR_QUEUE_SIZE(app->q_workers) >= app->conf->min_worker && app->state == WR_APP_RESTART)
448
- app->state == WR_APP_ACTIVE;
494
+ if(WR_QUEUE_SIZE(app->q_workers) >= app->conf->min_worker && app->state == WR_APP_RESTART){
495
+ app->state = WR_APP_ACTIVE;
496
+ wr_application_list_free(app->conf->new);
497
+ app->conf->new = NULL;
498
+ }
449
499
 
450
500
  // Create worker if application is high loaded
451
501
  /*
@@ -455,6 +505,37 @@ void wr_app_wkr_balance(wr_app_t *app){
455
505
  */
456
506
  }
457
507
 
508
+ /** Got worker add error */
509
+ int wr_app_wkr_error(wr_svr_t *server, const wr_ctl_msg_t *ctl_msg) {
510
+ LOG_FUNCTION
511
+ const char* app_name = ctl_msg->msg.wkr.app_name.str;
512
+ wr_app_t* app = wr_app_exist(server, app_name);
513
+
514
+ if(app == NULL){
515
+ return -1;
516
+ }
517
+
518
+ if(app->state == WR_APP_RESTART){
519
+ app->state = WR_APP_ACTIVE;
520
+ wr_application_list_free(app->conf->new);
521
+ app->conf->new = NULL;
522
+ // Send error response
523
+ wr_app_add_error_msg(app);
524
+ }else if(app->state == WR_APP_NEW){
525
+ // Send error response
526
+ wr_app_add_error_msg(app);
527
+ wr_app_remove(app->svr, app->conf->name.str);
528
+ }else{
529
+ wr_pending_wkr_t *pending = wr_pending_worker_exist(app, atoi(ctl_msg->msg.wkr.pid.str));
530
+ if(pending != NULL) free(pending);
531
+ app->timeout_counter = 0;
532
+
533
+ if(WR_QUEUE_SIZE(app->q_pending_workers) <= 0 && Config->Server.Worker.add_timeout > 0)
534
+ ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
535
+ }
536
+ return 0;
537
+ }
538
+
458
539
  /** Add newly created worker to application */
459
540
  int wr_app_wkr_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl_msg) {
460
541
  LOG_FUNCTION
@@ -478,15 +559,16 @@ int wr_app_wkr_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl
478
559
  scgi_body_add(worker->ctl->scgi, "Either worker add timeout or worker PID does not match.",
479
560
  strlen("Either worker add timeout or worker PID does not match."));
480
561
  return -1;
562
+ }else{
563
+ free(pending);
481
564
  }
482
565
 
483
566
  worker->id = ++worker_count;
484
567
  worker->app = app;
485
- if(!(worker->state & WR_WKR_ACTIVE)) worker->state += WR_WKR_ACTIVE;
486
-
568
+
487
569
  app->timeout_counter = 0;
488
570
 
489
- if(WR_QUEUE_SIZE(app->q_pending_workers) <= 0)
571
+ if(WR_QUEUE_SIZE(app->q_pending_workers) <= 0 && Config->Server.Worker.add_timeout > 0)
490
572
  ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
491
573
 
492
574
  if(app->state == WR_APP_RESTART){
@@ -516,37 +598,6 @@ int wr_app_wkr_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl
516
598
  return -1;
517
599
  }
518
600
 
519
- /** Remove application from application list */
520
- int wr_app_remove(wr_svr_t* server, const char* app_name) {
521
- LOG_FUNCTION
522
- wr_app_t* app = server->apps, *tmp_app = NULL;
523
-
524
- LOG_DEBUG(DEBUG, "Removing application %s", app_name);
525
-
526
- while(app) {
527
- if(strcmp(app_name, app->conf->name.str)==0)
528
- break;
529
- tmp_app = app;
530
- app = app->next;
531
- }
532
- if(app) {
533
- if(tmp_app) {
534
- tmp_app->next = app->next;
535
- } else {
536
- server->apps = app->next;
537
- }
538
-
539
- app->next = NULL;
540
- wr_app_free(app);
541
- wr_app_conf_remove(server->conf, app_name);
542
- return 0;
543
- } else {
544
- LOG_ERROR(WARN,"Aapplication %s didn't found in list", app_name);
545
- sprintf(server->err_msg, "Application '%s' is not found.", app_name);
546
- return -1;
547
- }
548
- }
549
-
550
601
  /** Check load balance to add the worker */
551
602
  void wr_app_chk_load_to_add_wkr(wr_app_t *app) {
552
603
  if(TOTAL_WORKER_COUNT(app) < app->conf->max_worker) {
@@ -581,7 +632,7 @@ void wr_app_chk_load_to_remove_wkr(wr_app_t *app) {
581
632
  /** Initialize the applications */
582
633
  void wr_app_init(wr_svr_t *server) {
583
634
  LOG_FUNCTION
584
- wr_app_conf_t *app = server->conf->apps;
635
+ config_application_list_t *app = Config->Application.list;
585
636
 
586
637
  while(app) {
587
638
  wr_app_insert(server, app, NULL);
@@ -595,7 +646,7 @@ void wr_app_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
595
646
  LOG_FUNCTION
596
647
 
597
648
  wr_svr_t* server = ctl->svr;
598
- wr_app_conf_t* app_conf = NULL;
649
+ config_application_list_t* app_conf = NULL;
599
650
  wr_app_t* app = wr_app_exist(server, ctl_msg->msg.app.app_name.str);
600
651
 
601
652
  // Reset the error message
@@ -604,10 +655,9 @@ void wr_app_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
604
655
  /* set application object in control, it would be used at time of freeing control object */
605
656
  ctl->app = app;
606
657
  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,
609
- ctl_msg->msg.app.app_name.str,
610
- ctl->svr->err_msg);
658
+ }else if(ctl && server) {
659
+ app_conf = wr_conf_app_read(ctl_msg->msg.app.app_name.str,
660
+ ctl->svr->err_msg, FALSE);
611
661
  if(app_conf!=NULL) {
612
662
  if(wr_app_insert(ctl->svr, app_conf, ctl) == TRUE) return;
613
663
  } else if(ctl->svr->err_msg[0] == 0) {
@@ -635,64 +685,72 @@ void wr_app_remove_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
635
685
  /** Allication reload callback */
636
686
  void wr_app_reload_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg){
637
687
  LOG_FUNCTION
638
- wr_app_conf_t* app_config = NULL;
639
688
  wr_app_t *app = wr_app_exist(ctl->svr, ctl_msg->msg.app.app_name.str);
640
689
 
641
- // Read new application configuration.
642
- app_config = wr_conf_app_update(ctl->svr->conf,
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);
647
- // Report error on not getting the application configuration.
648
- if(app_config == NULL){
649
- LOG_ERROR(WARN, "Error: %s",ctl->svr->err_msg);
650
- scgi_body_add(ctl->scgi, ctl->svr->err_msg, strlen(ctl->svr->err_msg));
651
- scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
652
- wr_ctl_resp_write(ctl);
653
- // Add old application configuration to server configuration.
654
- if(app){
655
- LOG_DEBUG(WARN,"Replace the application configuration with old one.");
656
- wr_conf_app_replace(app->svr->conf, app->conf);
657
- }
658
- return;
659
- }
660
-
661
690
  if(app){
662
- int i;
663
- wr_app_conf_t *tmp_app_conf = app->conf;
664
- // Set variables to restart the application.
665
- LOG_DEBUG(DEBUG,"Set variables to restart an existing application.");
666
- app->conf = app_config;
691
+
692
+ LOG_INFO("Reload the application %s", ctl_msg->msg.app.app_name.str);
693
+ // Read new application configuration.
694
+ // Report error on not getting the application configuration.
695
+ if(wr_conf_app_read(ctl_msg->msg.app.app_name.str, ctl->svr->err_msg, TRUE) == NULL){
696
+ LOG_ERROR(WARN, "Error: %s",ctl->svr->err_msg);
697
+ scgi_body_add(ctl->scgi, ctl->svr->err_msg, strlen(ctl->svr->err_msg));
698
+ scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
699
+ wr_ctl_resp_write(ctl);
700
+ return;
701
+ }
702
+
667
703
  app->state = WR_APP_RESTART;
704
+ app->timeout_counter = 0;
668
705
  while(WR_QUEUE_SIZE(app->q_pending_workers) > 0){
669
706
  wr_pending_wkr_t* pending = wr_queue_fetch(app->q_pending_workers);
670
707
  free(pending);
671
708
  }
672
709
 
673
710
  app->ctl = ctl;
674
- LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, app->conf->name.str);
711
+ LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, app->conf->new->name.str);
675
712
 
676
713
  // Add single worker with updated application.
677
714
  LOG_DEBUG(DEBUG, "Add first worker on application restart.");
678
- wr_app_wkr_add(app);
679
-
680
- // Replace the application configuration with older configuration object.
681
- wr_conf_app_replace(app->svr->conf, tmp_app_conf);
682
- app->conf = tmp_app_conf;
715
+ wr_app_wkr_add(app);
683
716
  return;
684
717
  }else{
685
718
  // If application didn't found, report an error and create new application.
686
719
  LOG_ERROR(WARN,"Aapplication %s didn't found in list", ctl_msg->msg.app.app_name.str);
687
720
  sprintf(ctl->svr->err_msg, "Application '%s' is not found.", ctl_msg->msg.app.app_name.str);
688
- scgi_body_add(ctl->scgi,
689
- "Couldn't remove application. But trying to start application.",
721
+ scgi_body_add(ctl->scgi, "Couldn't remove application. But trying to start application.",
690
722
  strlen("Couldn't remove application. But trying to start application."));
691
- if(wr_app_insert(ctl->svr, app_config, ctl) == TRUE) return;
723
+
724
+ config_application_list_t *app_config = wr_conf_app_read(ctl_msg->msg.app.app_name.str, ctl->svr->err_msg, FALSE);
725
+ if(app_config){
726
+ if(wr_app_insert(ctl->svr, app_config, ctl) == TRUE) return;
727
+ }else{
728
+ LOG_ERROR(WARN, "Error: %s",ctl->svr->err_msg);
729
+ scgi_body_add(ctl->scgi, ctl->svr->err_msg, strlen(ctl->svr->err_msg));
730
+ }
692
731
  }
693
732
 
694
733
  // Return ERROR status.
695
734
  scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
696
735
  wr_ctl_resp_write(ctl);
697
736
  }
698
-
737
+
738
+ /** Application configuration requset */
739
+ void wr_app_conf_req_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg){
740
+ config_application_list_t* app_conf = NULL;
741
+ wr_app_t* app = wr_app_exist(ctl->svr, ctl_msg->msg.app.app_name.str);
742
+
743
+ if(app && app->conf->scgi){
744
+ scgi_build(ctl->scgi);
745
+ scgi_free(ctl->scgi);
746
+ ctl->destroy_scgi = FALSE;
747
+ if(app->state == WR_APP_RESTART){
748
+ ctl->scgi = app->conf->new->scgi;
749
+ }else{
750
+ ctl->scgi = app->conf->scgi;
751
+ }
752
+ }else{
753
+ scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
754
+ }
755
+ wr_ctl_resp_write(ctl);
756
+ }