/*
Usage:  lookup name in the database, send reply back to the requester
Return: none
*/
void lookup_name(int sockfd, int dbfd, int logfd, struct name_prtl *name_request)
{
    int flag, result;
    char *attr;

    lock_file(dbfd);

    write_log(logfd, "[Info] lookup_name -- start to lookup a name in database");

    flag = database_lookup(dbfd, name_request->name, &attr);
    printf("[Info] lookup_name -- search database\n");
    if (flag == 0) { // found
        // send the attribute as the reply data back
        result = pkt_write(sockfd, 5, name_request->name, attr);
    } else if (flag == 1) {
        result = pkt_write(sockfd, 6, name_request->name, 
            "the name is not found");
    } else if (flag == -1) {
        result = pkt_write(sockfd, 8, name_request->name, 
            "fail to read the datebase, please try it later");
    }

    unlock_file(dbfd);
    write_log(logfd, "[Info] lookup_name -- finish lookup");
    
    if (result < 0) {
        fprintf(stderr, "[Error] lookup_name -- send reply fail\n");
        write_log(logfd, "[Error] lookup_name -- send reply fail");
    } else {
        fprintf(stdout, "[Info] lookup_name -- send reply ok: %s\n", 
            name_request->name);
        write_log(logfd, "[Info] lookup_name -- send reply ok");
    }
    return;
}
/*
Usage:  add name operation, add the name to database if possible, 
        and send the reply back
Return: none
*/
void add_name(int sockfd, int dbfd, int logfd, struct name_prtl *name_request)
{
    int len, n, flag, result;
    char *buf;

    write_log(logfd, "[Info] add_name -- adding name to database");

    lock_file(dbfd);

    /* check wheter a same name is in database, and send reply */
    flag = is_in_database(dbfd, name_request->name);
    printf("[Info] add_name -- finish search database\n");
    write_log(logfd, "[Info] add_name -- finish search database");
    if (flag == 0) { /* found */
        pkt_write(sockfd, 8, name_request->name, 
            "the name is already in database");
        return;
    } else if (flag == -1) { /* fail to search */
        pkt_write(sockfd, 8, name_request->name, 
            "fail to read the datebase, please try it later");
        return;
    }

    /* not find existing name, execute the add operation */
    len = strlen(name_request->name) + 2 + strlen(name_request->data);
    if ((buf = (char*) malloc(len + 1)) == NULL) {
        perror("[Error] add_name: malloc error");
        write_log(logfd, "[Error] add_name: malloc error");
        return;
    }

    // generate the new line string
    sprintf(buf, "%s: %s", name_request->name, name_request->data);

    if ((n = write(dbfd, buf, len)) == -1) {
        result = pkt_write(sockfd, 8, name_request->name, 
            "fail to add the name pair into database");
    } else {
        result = pkt_write(sockfd, 7, name_request->name, 
            "ok, the name has been added into database");
    }
    unlock_file(dbfd);

    write_log(logfd, "[Info] add_name: finish adding");

    if (result < 0) {
        fprintf(stderr, "[Error] add_name -- send reply fail\n");
        write_log(logfd, "[Error] add_name -- send reply fail");
    } else {
        fprintf(stdout, "[Info] add_name -- send reply ok\n");
        write_log(logfd, "[Info] add_name -- send reply ok");
    }
    return;
}
void update_name(int sockfd, int dbfd, int logfd, struct name_prtl *name_request)
{
    int len, n, flag, result;
    char *buf;

    lock_file(dbfd);
    write_log(logfd, "[Info] update_name -- start searching the database");

    flag = is_in_database(dbfd, name_request->name);
    printf("[Info] update_name -- finish searching database\n");
    if (flag == 0) { /* found */
        if (delete_line(dbfd, name_request->name) != 0) {
            result = pkt_write(sockfd, 8, name_request->name, 
            "fail to operate read or write the database");    
        } else { /* deleting the old line succeed */

            // write a new line to the datebase
            len = strlen(name_request->name) + 2 + strlen(name_request->data);
            if ((buf = (char*) malloc(len + 1)) == NULL) {
                perror("[Error] add_name -- malloc error");
                write_log(logfd, "[Error] add_name -- malloc error");
                return;
            }
            sprintf(buf, "%s: %s", name_request->name, name_request->data);

            if ((n = write(dbfd, buf, len)) == -1) {
                result = pkt_write(sockfd, 8, name_request->name, 
                    "fail to update the name pair in database");
            } else {
                result = pkt_write(sockfd, 7, name_request->name, 
                    "ok, the name pair has been updated");
            }
        }
    } else if (flag == 1) {
        result = pkt_write(sockfd, 8, name_request->name, 
            "the name is not found");
    } else if (flag == -1) {
        result = pkt_write(sockfd, 8, name_request->name, 
            "fail to read the datebase, please try it later");
    }

    unlock_file(dbfd);
    if (result < 0) {
        fprintf(stderr, "[Error] update_name -- send reply fail\n");
    } else {
        fprintf(stdout, "[Info] update_name -- send reply ok: %s\n", 
            name_request->name);
    }
    return;
}
/*
Usage:  delete a name pair from database, send the reply
Return: none
*/
void delete_name(int sockfd, int dbfd, int logfd, struct name_prtl *name_request)
{
    int flag, result;

    lock_file(dbfd);
    write_log(logfd, "[Info] delete_name -- start searching the database");

    flag = is_in_database(dbfd, name_request->name);
    printf("[Info] delete_name -- finish searching database\n");
    if (flag == 0) { /* found */
        if (delete_line(dbfd, name_request->name) != 0) {
            result = pkt_write(sockfd, 8, name_request->name, 
            "fail to operate read or write the database");    
        } else { /* delete name pair */
            result = pkt_write(sockfd, 7, name_request->name, 
            "delete the name successfully");
        }
    } else if (flag == 1) { /* not find such name */
        result = pkt_write(sockfd, 8, name_request->name, 
            "the name is in database");
    } else if (flag == -1) { /* error */
        result = pkt_write(sockfd, 8, name_request->name, 
            "fail to read the datebase, please try it later");
    }

    unlock_file(dbfd);
    if (result < 0) {
        fprintf(stderr, "[Error] delete_name -- send reply fail\n");
        write_log(logfd, "[Error] delete_name -- send reply fail");
    } else {
        fprintf(stdout, "[Info] delete_name -- send reply ok: %s\n", 
            name_request->name);
        write_log(logfd, "[Info] delete_name -- send reply ok");
    }
    return;
}
/*
Usage:  name server main logical func for each server process, 
        receive the pkt and decide what to do
Return: none
*/
void name_server(int sockfd, int dbfd, int itemfd, int rservfd, int logfd, 
    int port)
{
    ssize_t n;
    int result, i, flag, k, m;
    char buf[MAXBYTE];
    char *data;
    char hostipaddr[16];
    struct name_prtl name_request, name_reply;

    if ((n = read(sockfd, buf, MAXBYTE)) <= 0) {
        return;
    }

    if (buf[0] == '1') {
        printf("[Info] receive name request\n");
        if ((data = (char *) malloc(n + 1)) == NULL) {
            perror("malloc error");
            return;
        }
        for (i = 0; i < n; i ++) {
            data[i] = buf[i];
        }
        
        name_request.protocol = 1;
        if ((result = parse_name_pkt(&name_request, data)) == -1) {
            fprintf(stderr, "[Error] fail to parse the pkt, invalid format\n");
            pkt_write(sockfd, 8, name_request.name, "[Error] unknown pkt");
            return;
        }

        if (name_request.type > 4 || name_request.type <= 0) {
            // ignore
            fprintf(stderr, "[Error] invalid type: %d\n", name_request.type);
            return;     
        } else {
            handle_request(&name_request, itemfd, dbfd, rservfd, sockfd, logfd, 
                n, port, data);
        }

    } else {
        fprintf(stderr, "[Error] unknown pkt received\n");
    }
}
/*
Usage:  follow the protocol to handle a request, and call right func
Return: none
*/
void handle_request(struct name_prtl *name_request, int itemfd, int dbfd, 
    int rservfd, int sockfd, int logfd, ssize_t n, int port, char *data)
{
    int flag, result, m;
    char hostipaddr[16];

    // chech which server should be responsible for the request
    flag = is_local(itemfd, name_request->name);
    if (flag == -1) { /* not have this kind of names */
        // ask route server
        printf("[Info] ask routing server for the name\n");
        result = route(rservfd, logfd, name_request->name[0], hostipaddr);
        if (result == -1) { /* fail */
            fprintf(stderr, "[Error] route check failed\n");
            write_log(logfd, "[Error] handle_request -- route check failed");
            pkt_write(sockfd, 8, name_request->name, 
                "fail to check route table");
        } else if (result == 0) { /* new kind of names, add it locally */
            // add new mapping first
            printf("[Info] find the corresponding server\n");
            m = add_nameitem(itemfd, name_request->name[0]);
            if (m == -1) {
                fprintf(stderr, "[Error] fail to update indextable\n");
                write_log(logfd, 
                    "[Error] handle_request -- update indextable error");
                pkt_write(sockfd, 8, name_request->name, 
                    "fail to updata indextable");
            } else {
                if (name_request->type == 2) { /* add new name */
                    printf("[Info] adding new name: %s\n", name_request->name);
                    add_name(sockfd, dbfd, logfd, name_request);
                } else if (name_request->type == 1) { /* lookup */
                    printf("[Info] lookup name: %s\n", name_request->name);
                    lookup_name(sockfd, dbfd, logfd, name_request);
                } else if (name_request->type == 3) { /* delete */
                    printf("[Info] delete name: %s\n", name_request->name);
                    delete_name(sockfd, dbfd, logfd, name_request);
                } else if (name_request->type == 4) { /* update */
                    printf("[Info] update name: %s\n", name_request->name);
                    update_name(sockfd, dbfd, logfd, name_request);
                }
            }
        } else if (result == 1) { /* there is another server which is 
                                    responsible for this kind of names */
            printf("[Info] forward request\n"); 
            m = forward_request(sockfd, logfd, data, hostipaddr, 
                port, n);
            if (m == -1) { /* fail */
                fprintf(stderr, "[Error] fail to forward request\n");
                pkt_write(sockfd, 8, name_request->name, 
                    "[Error] fail to forward pkt");
            }
        }
    } else { /* find this kind of name locally */
        if (name_request->type == 2) { /* add new name */
            printf("[Info] adding new name: %s\n", name_request->name);
            add_name(sockfd, dbfd, logfd, name_request);
        } else if (name_request->type == 1) { /* lookup */
            printf("[Info] lookup name: %s\n", name_request->name);
            lookup_name(sockfd, dbfd, logfd, name_request);
        } else if (name_request->type == 3) { /* delete */
            printf("[Info] delete name: %s\n", name_request->name);
            delete_name(sockfd, dbfd, logfd, name_request);
        } else if (name_request->type == 4) { /* update */
            printf("[Info] update name: %s\n", name_request->name);
            update_name(sockfd, dbfd, logfd, name_request);
        }
    }
}
Пример #7
0
/* do_control()
**   send cmd to list of services given in argv
*/
void
do_control(uchar_t cmd[], char *argv[]){
  char     pathbuf[256];
  size_t   n;
  int      fd_conn;
  int      e;

  /* connect to control socket: */
  n = cstr_vlen(basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  if(!(n < sizeof pathbuf)){
      errno = ENAMETOOLONG;
      fatal_syserr("failure locating perpd control socket ",
                   basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  }
  cstr_vcopy(pathbuf, basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  fd_conn = domsock_connect(pathbuf);
  if(fd_conn == -1){
      if(errno == ECONNREFUSED){
          fatal_syserr("perpd not running on control socket ", pathbuf);
      } else {
          fatal_syserr("failure connecting to perpd control socket ", pathbuf);
      }
  }

  /* loop through service directory arguments and send control packet: */
  for(; *argv != NULL; ++argv){
      pkt_t        pkt = pkt_INIT(2, 'C', 18);
      struct stat  st;

      if(stat(*argv, &st) == -1){
          ++errs;
          eputs("error: ", *argv, ": service directory not found");
          continue;
      }

      if(! S_ISDIR(st.st_mode)){
          ++errs;
          eputs("error: ", *argv, ": not a directory");
          continue;
      }

      if(!(S_ISVTX & st.st_mode)){
          ++errs;
          eputs("error: ", *argv, ": service directory not activated");
          continue;
      }

      /* control packet for this directory: */
      upak_pack(pkt_data(pkt), "LLbb",
                (uint64_t)st.st_dev, (uint64_t)st.st_ino, cmd[0], cmd[1]);

      if(pkt_write(fd_conn, pkt, 0) == -1){
          ++errs;
          eputs_syserr("error: ", *argv, ": error writing request");
          continue;
      }

      if(pkt_read(fd_conn, pkt, 0) == -1){
          ++errs;
          eputs_syserr("error: ", *argv, ": error reading response");
          continue;
      }

      if(pkt[0] != 2){
          ++errs;
          eputs("error: ", *argv, ": unknown packet protocol in reply");
          continue;
      }
      if(pkt[1] != 'E'){
          ++errs;
          eputs("error: ", *argv, ": unknown packet type in reply");
          continue;
      }

      e = (int)upak32_unpack(&pkt[3]);
      if(e != 0){
          ++errs;
          errno = e;
          eputs_syserr("error: ", *argv, ": error reported in reply");
          continue;
      }

      /* success: */
      report(*argv, ": ok");
  }

  return; 
}
Пример #8
0
int
main(int argc, char *argv[])
{
  nextopt_t    nopt = nextopt_INIT(argc, argv, ":hVb:");
  char         opt;
  const char  *basedir = NULL;
  char         pathbuf[256];
  tain_t       now;
  size_t       n;
  int          fd_conn;

  progname = nextopt_progname(&nopt);
  while((opt = nextopt(&nopt))){
      char  optc[2] = {nopt.opt_got, '\0'};
      switch(opt){
      case 'h': usage(); die(0); break;
      case 'V': version(); die(0); break;
      case 'b': basedir = nopt.opt_arg; break;
      case ':':
          fatal_usage("missing argument for option -", optc);
          break;
      case '?':
          if(nopt.opt_got != '?'){
              fatal_usage("invalid option -", optc);
          }
          /* else fallthrough: */
      default : die_usage(); break;
      }
  }

  argc -= nopt.arg_ndx;
  argv += nopt.arg_ndx;

  if(!*argv){
      fatal_usage("missing argument");
  }

  if(!basedir)
      basedir = getenv("PERP_BASE");
  if(!basedir)
      basedir = ".";

  if(chdir(basedir) != 0){
      fatal_syserr("fail chdir() to ", basedir);
  }

  /* connect to control socket: */
  n = cstr_vlen(basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  if(!(n < sizeof pathbuf)){
      errno = ENAMETOOLONG;
      fatal_syserr("failure locating perpd control socket ",
                   basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  }
  cstr_vcopy(pathbuf, basedir, "/", PERP_CONTROL, "/", PERPD_SOCKET);
  fd_conn = domsock_connect(pathbuf);
  if(fd_conn == -1){
      if(errno == ECONNREFUSED){
          fatal_syserr("perpd not running on control socket ", pathbuf);
      }else{
          fatal_syserr("failure connecting to perpd control socket ", pathbuf);
      }
  }
 
  /* uptimes compared to now: */
  tain_now(&now);

  /* loop through service directory arguments and display report: */
  for(; *argv != NULL; ++argv){
      pkt_t        pkt = pkt_INIT(2, 'Q', 16);
      struct stat  st;

      if(stat(*argv, &st) == -1){
          eputs(*argv, ": error: service directory not found");
          continue;
      }

      if(! S_ISDIR(st.st_mode)){
          eputs(*argv, ": error: not a directory");
          continue;
      }

      if(!(S_ISVTX & st.st_mode)){
          vputs(*argv, ": not activated\n");
          continue;
      }

      upak_pack(pkt_data(pkt), "LL", (uint64_t)st.st_dev, (uint64_t)st.st_ino);

      if(pkt_write(fd_conn, pkt, 0) == -1){
          eputs_syserr("error: ", *argv, ": error writing query");
          continue;
      }

      if(pkt_read(fd_conn, pkt, 0) == -1){
          eputs_syserr("error: ", *argv, ": error reading response");
          continue;
      }

      if(pkt[0] != 2){
          eputs("error: ", *argv, ": unknown packet protocol in reply");
          continue;
      }
      if(pkt[1] != 'S'){
          if(pkt[1] == 'E'){
              errno = (int)upak32_unpack(&pkt[3]);
              eputs_syserr("error: ", *argv, ": error reported in reply");
          } else {
              eputs("error: ", *argv, ": unknown packet type in reply");
          }
          continue;
      }

      report(*argv, pkt_data(pkt), &now);
  }

  vputs_flush();
  die(0);
}