wkr_tmp_t* wkr_tmp_new() { LOG_FUNCTION wkr_tmp_t *tmp = wr_malloc(wkr_tmp_t); if(tmp == NULL) { return NULL; } wr_string_null(tmp->path); wr_string_null(tmp->env); wr_string_null(tmp->type); wr_string_null(tmp->name); wr_string_null(tmp->resolver); wr_string_null(tmp->root_path); wr_string_null(tmp->ctl_path); wr_string_null(tmp->log_file); tmp->profiler = 'n'; tmp->gid = tmp->uid = 0; // HTTP1.1 assumes persistent connection by default tmp->keep_alive = TRUE; tmp->is_uds = FALSE; tmp->is_static = 0; #ifdef W_ZLIB tmp->lower_limit = tmp->upper_limit = 0; #ifdef W_REGEX wr_string_null(tmp->r_user_agent); wr_string_null(tmp->r_content_type); #endif #endif return tmp; }
/** Create new worker */ wr_wkr_t* wr_wkr_new(wr_ctl_t *ctl) { LOG_FUNCTION wr_wkr_t* worker = wr_malloc(wr_wkr_t); if(worker == NULL) return NULL; // Set default value worker->ctl = ctl; worker->req = NULL; worker->fd = 0; worker->id = 0; worker->pid = 0; worker->app = NULL; worker->watcher.active = 0; worker->state = WR_WKR_CLEAR; worker->trials_done = 0; worker->t_wait.data = worker; worker->loop = ctl->svr->ebb_svr.loop; ev_timer_init(&worker->t_wait, wr_wkr_wait_cb, 0., WR_WKR_IDLE_TIME); return worker; }
/** Create new Worker */ wkr_t* worker_new(struct ev_loop *loop, wkr_tmp_t *tmp) { LOG_FUNCTION wkr_t* w = wr_malloc(wkr_t); assert(w!=NULL); w->req_fd = -1; w->listen_fd = -1; w->is_uds = tmp->is_uds; w->loop = loop; wr_string_null(w->sock_path); w->listen_port = 0; w->w_accept.active = 0; w->w_req.active = 0; w->http = NULL; w->tmp = tmp; assert(w->tmp!=NULL); w->env_var = NULL; w->ctl = wkr_ctl_new(w); assert(w->ctl!=NULL); if(connect_to_head(w) == FALSE){ worker_free(&w); return NULL; } start_ctl_watcher(w); /* if(w->tmp->is_static){ w->ctl->scgi = scgi_new(); load_application(w); } else */ if(send_config_req_msg(w) < 0){ worker_free(&w); return NULL; } // Connect to head controller UDS socket before user previliges get lowered. return w; }
wr_ctl_msg_t* wr_ctl_msg_validate(scgi_t* request, wr_ctl_t* ctl) { LOG_FUNCTION wr_ctl_msg_t* ctl_msg = wr_malloc(wr_ctl_msg_t); char *val; char error[STR_SIZE64]; ctl->type = WR_CTL_MSG_NONE; ctl->scgi = scgi_new(); val = (char*) scgi_header_value_get(request,"COMPONENT"); if(val == NULL) { memcpy(error,"COMPONENT missing.", strlen("COMPONENT missing.")+1); goto ctl_msg_err; } scgi_header_add(ctl->scgi, "COMPONENT", strlen("COMPONENT"), val, strlen(val)); if(strcmp(val,"APPLICATION")==0) { val = (char*) scgi_header_value_get(request,"METHOD"); if(val == NULL) { memcpy(error,"METHOD missing.", strlen("METHOD missing.")+1); goto ctl_msg_err; } scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), val, strlen(val)); ctl_msg->msg.app.app_name.str = (char*) scgi_header_value_get(request,"APP_NAME"); if(ctl_msg->msg.app.app_name.str) ctl_msg->msg.app.app_name.len = strlen(ctl_msg->msg.app.app_name.str); if(ctl_msg->msg.app.app_name.str == NULL) { memcpy(error,"Application name is missing.", strlen("Application name is missing.")+1); goto ctl_msg_err; } // Application Add if(strcmp(val,"ADD")==0) { ctl->type = WR_CTL_MSG_APPLICATION_ADD; } else if(strcmp(val,"REMOVE")==0) { ctl->type = WR_CTL_MSG_APPLICATION_REMOVE; } else if(strcmp(val,"RELOAD")==0) { ctl->type = WR_CTL_MSG_APPLICATION_RELOAD; }else { memcpy(error, "Invalid METHOD.", strlen("Invalid METHOD.")+1); goto ctl_msg_err; } } else if(strcmp(val,"WORKER")==0) { val = (char*) scgi_header_value_get(request,"METHOD"); if(val == NULL) { memcpy(error, "METHOD missing.", strlen("METHOD missing.")+1); goto ctl_msg_err; } if(strcmp(val,"ERROR")==0) { scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), "ACK", strlen("ACK")); }else{ scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), val, strlen(val)); } // Worker Add if(strcmp(val,"ADD")==0) { ctl->type = WR_CTL_MSG_WORKER_ADD; ctl_msg->msg.wkr.app_name.str = (char*) scgi_header_value_get(request,"APPLICATION"); if(ctl_msg->msg.wkr.app_name.str) ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str); ctl_msg->msg.wkr.pid.str = (char*) scgi_header_value_get(request,"PID"); if(ctl_msg->msg.wkr.pid.str) ctl_msg->msg.wkr.pid.len = strlen(ctl_msg->msg.wkr.pid.str); ctl_msg->msg.wkr.port.str = (char*) scgi_header_value_get(request,"PORT"); if(ctl_msg->msg.wkr.port.str) ctl_msg->msg.wkr.port.len = strlen(ctl_msg->msg.wkr.port.str); ctl_msg->msg.wkr.sock_path.str = (char*) scgi_header_value_get(request,"SOCK_PATH"); if(ctl_msg->msg.wkr.sock_path.str) ctl_msg->msg.wkr.sock_path.len = strlen(ctl_msg->msg.wkr.sock_path.str); ctl_msg->msg.wkr.uds.str = (char*) scgi_header_value_get(request,"UDS"); if(ctl_msg->msg.wkr.uds.str) ctl_msg->msg.wkr.uds.len = strlen(ctl_msg->msg.wkr.uds.str); if(ctl_msg->msg.wkr.app_name.str == NULL || ctl_msg->msg.wkr.pid.str == NULL || ctl_msg->msg.wkr.uds.str == NULL) { memcpy(error, "Missing some headers.", strlen("Missing some headers.")+1); goto ctl_msg_err; } } else if(strcmp(val,"REMOVE")==0) { ctl->type = WR_CTL_MSG_WORKER_REMOVE; } else if(strcmp(val,"PING") == 0) { ctl->type = WR_CTL_MSG_WORKER_PING; } else if(strcmp(val,"CONF_REQ") == 0){ ctl->type = WR_CTL_MSG_WORKER_CONF_REQ; ctl_msg->msg.wkr.app_name.str = (char*) scgi_header_value_get(request,"APPLICATION"); if(ctl_msg->msg.wkr.app_name.str) ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str); } else if(strcmp(val,"ERROR") == 0) { ctl->type = WR_CTL_MSG_WORKER_ADD_ERROR; ctl_msg->msg.wkr.app_name.str = (char*) scgi_header_value_get(request,"APPLICATION"); if(ctl_msg->msg.wkr.app_name.str) ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str); ctl_msg->msg.wkr.pid.str = (char*) scgi_header_value_get(request,"PID"); if(ctl_msg->msg.wkr.pid.str) ctl_msg->msg.wkr.pid.len = strlen(ctl_msg->msg.wkr.pid.str); ctl_msg->msg.wkr.port.str = (char*) scgi_header_value_get(request,"PORT"); if(ctl_msg->msg.wkr.port.str) ctl_msg->msg.wkr.port.len = strlen(ctl_msg->msg.wkr.port.str); ctl_msg->msg.wkr.sock_path.str = (char*) scgi_header_value_get(request,"SOCK_PATH"); if(ctl_msg->msg.wkr.sock_path.str) ctl_msg->msg.wkr.sock_path.len = strlen(ctl_msg->msg.wkr.sock_path.str); ctl_msg->msg.wkr.uds.str = (char*) scgi_header_value_get(request,"UDS"); if(ctl_msg->msg.wkr.uds.str) ctl_msg->msg.wkr.uds.len = strlen(ctl_msg->msg.wkr.uds.str); if(ctl_msg->msg.wkr.app_name.str == NULL || ctl_msg->msg.wkr.pid.str == NULL || ctl_msg->msg.wkr.uds.str == NULL) { memcpy(error, "Missing some headers.", strlen("Missing some headers.")+1); goto ctl_msg_err; } }else { memcpy(error,"Invalid METHOD.", strlen("Invalid METHOD.")+1); goto ctl_msg_err; } } else { memcpy(error,"Invalid COMPONENT.", strlen("Invalid COMPONENT.")+1); goto ctl_msg_err; } return ctl_msg; ctl_msg_err: LOG_ERROR(WARN,"Error found in controller message"); ctl->type = WR_CTL_MSG_TYPE_ERROR; scgi_body_add(ctl->scgi, error, strlen(error)); scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR")); return ctl_msg; }
/** Insert application based on application configuration */ static int wr_app_insert(wr_svr_t* server, wr_app_conf_t* config, wr_ctl_t *ctl) { LOG_FUNCTION wr_app_t* app = wr_malloc(wr_app_t); short is_static_server = 0; if(!app) { LOG_ERROR(WARN, "%s() application object allocation failed. Returning ...", __FUNCTION__); return -1; } if(strcmp(config->name.str, WR_STATIC_FILE_SERVER_NAME) == 0){ is_static_server = 1; } app->free_wkr_que = wr_queue_new(config->max_worker); app->wkr_que = wr_queue_new(config->max_worker); app->msg_que = wr_queue_new(WR_MSG_QUE_SIZE); if( app->wkr_que == NULL || app->free_wkr_que == NULL || app->msg_que == NULL) { free(app); app = NULL; LOG_ERROR(WARN, "application object initialization failed. Returning ..."); return -1; } app->svr = server; app->conf = config; app->ctl = ctl; if(!is_static_server){ wr_req_resolver_add(server, app, config); app->next = server->apps; server->apps = app; }else{ app->next = NULL; server->static_app = app; } app->t_add.data = app->t_remove.data = app->t_add_timeout.data = app; ev_timer_init (&app->t_add, wr_app_wrk_add_cb, 0., WR_HIGH_LOAD_LIMIT); ev_timer_init (&app->t_remove, wr_app_wrk_remove_cb, 0., WR_LOW_LOAD_LIMIT); ev_timer_init (&app->t_add_timeout, wr_app_wrk_add_timeout_cb, 0., WR_WKR_ADD_TIMEOUT); //app->next = server->apps; //server->apps = app; LOG_DEBUG(4,"%s() Application Added:%s", __FUNCTION__, config->name.str); app->pending_wkr = 0; app->in_use = FALSE; int i; for(i = 0; i < WR_MAX_PENDING_WKR ; i ++) { app->last_wkr_pid[i] = 0; } /** Creating workers */ for(i=0; i < config->min_worker; i++) { //Create a new Worker wr_app_wkr_add(app); // int pid = wr_wkr_create(server, config); // LOG_DEBUG(DEBUG,"Rails application=%s", config->path.str); // LOG_DEBUG(4,"PID of created process is %i",pid); } //app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO; app->low_ratio = TOTAL_WORKER_COUNT(app) * WR_MIN_REQ_RATIO; return 0; }