Ejemplo n.º 1
0
/** This would get called when idel time watcher goes timeout */
static void wr_wkr_wait_cb(struct ev_loop *loop, ev_timer *w, int revents) {
  LOG_FUNCTION
  wr_wkr_t *worker = (wr_wkr_t*)w->data;

  //ev_timer_stop(loop, &worker->t_idle);
  ev_timer_stop(loop, &worker->t_wait);

  if(worker->app == NULL) {
    LOG_INFO("wr_wkr_wait_cb: Worker removed with pid %d", worker->pid);
    wr_wkr_free(worker);
  } else if(worker->trials_done < WR_PING_TRIALS) {
    worker->trials_done++;
    LOG_INFO("Worker %d with pid %u ping for trial no %d",
             worker->id, worker->pid, worker->trials_done);
    worker->t_wait.repeat = WR_PING_WAIT_TIME;
    worker->state |= (WR_WKR_HANG | WR_WKR_PING_SENT);
    if(worker->state & WR_WKR_PING_REPLIED) {
      worker->state ^= WR_WKR_PING_REPLIED;
    }
    scgi_t *scgi = scgi_new();
    scgi_header_add(scgi, "COMPONENT", strlen("COMPONENT"), "WORKER", strlen("WORKER"));
    scgi_header_add(scgi, "METHOD", strlen("METHOD"), "PING", strlen("PING"));
    if(scgi_build(scgi)!=0) {
      LOG_ERROR(WARN,"SCGI request build failed.");
    }
    worker->ctl->scgi = scgi;
    ev_io_start(loop, &worker->ctl->w_write);
    //ev_timer_again(loop, &worker->t_ping_wait);
    ev_timer_again(loop, &worker->t_wait);
  } else {
    //render 500 response to Request, kill the worker
    wr_wkr_recreate(worker);
  }
}
Ejemplo n.º 2
0
/** Allication add callback */
void wr_app_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
  LOG_FUNCTION

  wr_svr_t* server = ctl->svr;
  wr_app_conf_t* app_conf = NULL;
  wr_app_t* app = server->apps, *tmp_app = NULL;
    
  while(app) {
    if(strcmp(ctl_msg->msg.app.app_name.str, app->conf->name.str)==0)
      break;
    tmp_app = app;
    app = app->next;
  }
  ctl->svr->err_msg[0] = 0;
  if(app) {
    sprintf(ctl->svr->err_msg, "Appliation '%s' is already running.", ctl_msg->msg.app.app_name.str);
  }
  
  if(!app && ctl && ctl->svr && ctl->svr->conf) {
    app_conf = wr_conf_app_read(ctl->svr->conf,
                           ctl_msg->msg.app.app_name.str,
                           ctl->svr->err_msg);
    if(app_conf!=NULL) {
      if(wr_app_insert(ctl->svr, app_conf, ctl) >= 0)
        return;
    } else if(ctl->svr->err_msg[0] == 0) {
      sprintf(ctl->svr->err_msg, "Appliation '%s' is not found.", ctl_msg->msg.app.app_name.str);
    }
  }

  scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
  scgi_body_add(ctl->scgi, ctl->svr->err_msg, strlen(ctl->svr->err_msg));
  wr_ctl_resp_write(ctl);
}
Ejemplo n.º 3
0
/** Add newly created worker to application */
int wr_app_wrk_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl_msg) {
  LOG_FUNCTION
  wr_app_t* app = server->apps;
  const char* app_name = ctl_msg->msg.wkr.app_name.str;
  
  if(strcmp(app_name, WR_STATIC_FILE_SERVER_NAME) == 0){
    app = server->static_app;
  }

  while(app) {
    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));
    LOG_DEBUG(DEBUG, "Application name = %s, Application->config->name =%s", app_name, app->conf->name.str );
    if(app->conf->max_worker > WR_QUEUE_SIZE(app->wkr_que)
        && strcmp(app_name, app->conf->name.str) == 0) {
      int i;
      for(i = 0; i < app->pending_wkr ; i++) {
        if(app->last_wkr_pid[i] == worker->pid)
          break;
      }

      if(i == app->pending_wkr) {
        scgi_body_add(worker->ctl->scgi, "Either worker add timeout or worker PID does not match.",
                              strlen("Either worker add timeout or worker PID does not match."));
        return -1;
      }

      for(; i < app->pending_wkr ; i++) {
        app->last_wkr_pid[i] = app->last_wkr_pid[i+1];
      }
      app->last_wkr_pid[i] = 0;
      app->pending_wkr --;


      worker->id = ++worker_count;
      worker->app = app;
      
      if(app->pending_wkr <= 0)
        ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
      if(!(worker->state& WR_WKR_ACTIVE))
        worker->state += WR_WKR_ACTIVE;

      if(app->in_use == FALSE) {
        app->in_use = TRUE;
        if(app->ctl) {
          LOG_DEBUG(DEBUG,"Send OK status");
          scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
          wr_ctl_resp_write(app->ctl);
          app->ctl = NULL;
        }
      }
      return 0;
    }
    app = app->next;
  }
  LOG_ERROR(SEVERE, "Either queue is full or Baseuri is not matched");
  scgi_body_add(worker->ctl->scgi, "Either queue is full or Baseuri is not matched.",
                        strlen("Either queue is full or Baseuri is not matched."));
  return -1;
}
Ejemplo n.º 4
0
/** Callback function to add worker timeout */
void wr_app_wrk_add_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
  LOG_FUNCTION
  wr_app_t* app = (wr_app_t*) w->data;
  char err_msg[512];
  int err_msg_len = 0;
  
  // Stop add timeout timer
  ev_timer_stop(loop, &app->t_add_timeout);

  // Decreament active worker count
  if(app->pending_wkr > 0) {
    // Kill worker
    int pid = wr_app_fetch_wkr_pid(app);
    LOG_INFO("wr_app_wrk_add_timeout_cb: killing worker, pid = %d", pid);
    if(pid > 0)
      kill(pid ,SIGKILL);
    LOG_DEBUG(DEBUG,"app->pending_wkr = %d", app->pending_wkr);
    app->pending_wkr --;
    if(app->pending_wkr > 0) {
      ev_timer_again(loop, &app->t_add_timeout);
    }

    // Update high load ratio
    app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
  }

  //TODO: Check minimum no. of workers and, cretae worker if needed.
  // Also, do not OK if some worker were failed to connect.
  // For timebeing sending OK even if some worker failed to connect.
  if(app->in_use == FALSE && app->ctl && app->pending_wkr == 0) {
    LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
    scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
    err_msg_len = sprintf(err_msg,"The application could not be started due to an error. Please refer '/var/log/webroar/%s.log' and the application log file for details.", app->conf->name.str); 
    scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
    wr_ctl_resp_write(app->ctl);
    app->ctl = NULL;
  } else if(app->in_use == TRUE && TOTAL_WORKER_COUNT(app) < app->conf->min_worker) {
    wr_app_wkr_add(app);
  }
}
Ejemplo n.º 5
0
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;
}