Defines | Functions

utility.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "portability.h"
#include "utility.h"
Include dependency graph for utility.c:

Go to the source code of this file.

Defines

#define BUFSZ   400

Functions

int gs_versions_incompatible (const char *ver1, const char *ver2)
char * gs_get_line (FILE *in)
char * gs_read_line (FILE *f, int *linecount)
int gs_parse_config_file (char *filename, gs_info_t **tmp)
int gs_open_locked_file (char *filename, short lock_type, int flags)
int gs_unlock_file (int fd)
static void gs_alarm_catch (int sig)
int gs_open_locked_file_timeout (char *lockfile, short lock_type, int flags, int timeout)
long gs_seconds_since_modified (char *filename)
int gs_get_contents_of_file (char *name, char **contents)
static float gs_popen_loadavg (char *cmd)
static float gs_fopen_loadavg (char *filename)
int gs_get_workload ()
 Get workload on machine.

Detailed Description

This file contains various utility routines used by GridSolve.

Definition in file utility.c.


Define Documentation

#define BUFSZ   400

Function Documentation

static void gs_alarm_catch ( int  sig  )  [static]

Empty signal handler for SIGALRM used in gs_open_locked_file_timeout().

Parameters:
sig -- signal number (unused)

Definition at line 299 of file utility.c.

{
  return;
}

static float gs_fopen_loadavg ( char *  filename  )  [static]

Definition at line 457 of file utility.c.

{
  FILE *loadavg_file;
  float tmpf;
  int n;

  if((loadavg_file = fopen(filename, "r")) == NULL)
    return -1;

  n = fscanf(loadavg_file, "%f", &tmpf);

  fclose(loadavg_file);

  if(n != 1)
    return -1;

  return tmpf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_get_contents_of_file ( char *  name,
char **  contents 
)

Definition at line 390 of file utility.c.

{
  struct stat stbuf;
  int cfd, nread;
  char *buf;

  if(stat(name, &stbuf) < 0)
    return -1;

  buf = malloc((int)stbuf.st_size+1);

  if(!buf) {
    ERRPRINTF("malloc failed\n");
    return -1;
  }

  cfd = open(name, O_RDONLY, 0600);

  if(cfd < 0) {
    ERRPRINTF("Warning: failed to open file '%s'\n", name);
    free(buf);
    return -1;
  }

  nread = read(cfd, buf, (int) stbuf.st_size + 1);
  buf[nread] = '\0';

  close(cfd);

  if(nread <= 0) {
    free(buf);
    return -1;
  }

  *contents = buf;
  return nread;
}

Here is the caller graph for this function:

char* gs_get_line ( FILE *  in  ) 

Keeps reading chunks from the specified file until a newline is found. Appends all the chunks to one string and returns that. This code was lifted from f2j.

Parameters:
in -- the file to read from
Returns:
line from the file. returns NULL on EOF or error.

Definition at line 66 of file utility.c.

{
#define BUFSZ 400
  char buf[BUFSZ];
  char *rv, *line, *ltmp;
  int idx = 0, cur_size = BUFSZ;

  if(!in) return NULL;

  line = (char *)malloc(BUFSZ);
  *line = '\0';

  if(!line) return NULL;

  do {
    rv = fgets(buf, BUFSZ, in);

    if(!rv) {
      free(line);
      return NULL;
    }

    memcpy(line+idx, buf, BUFSZ);
    idx += strlen(buf);

    cur_size += BUFSZ;
    ltmp = realloc(line, cur_size);

    if(!ltmp) return NULL;
    line = ltmp;
  } while(buf[strlen(buf)-1] != '\n');

  return line;
}

Here is the caller graph for this function:

int gs_get_workload (  ) 

Get workload on machine.

Call the uptime command to get the system load, and return it as a percentage.

Returns:
the machine's current workload

Definition at line 485 of file utility.c.

{
  char *commands[] = {"uptime", "w", NULL};
  char *files[] = {"/proc/loadavg", NULL};
  float workload;
  int i, scale;

  scale = 100;

  for(i=0;files[i];i++)
    if((workload = gs_fopen_loadavg(files[i])) >= 0)
      return (int) (scale * workload);

  for(i=0;commands[i];i++)
    if((workload = gs_popen_loadavg(commands[i])) >= 0)
      return (int) (scale * workload);

  return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_open_locked_file ( char *  filename,
short  lock_type,
int  flags 
)

Opens and locks the specified file.

Parameters:
filename -- name of the file to lock
lock_type -- type of lock (F_RDLCK, F_WRLCK)
flags -- mode to open the file (O_RDONLY, O_RDWR, etc)
Returns:
file descriptor on success, -1 on failure.

Definition at line 245 of file utility.c.

{
  int fd;

  if(!filename) {
    ERRPRINTF("Invalid arg: null filename\n");
    return -1;
  }

  if((fd = open(filename, flags, 0600)) == -1) {
    ERRPRINTF("open failed\n");
    perror("open");
    return -1;
  }

  
  /* lock file */
  if (gs_lock_fd(fd, lock_type) == -1) {
    perror("lock");
    close(fd);
    return -1;
  }

  return fd;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_open_locked_file_timeout ( char *  lockfile,
short  lock_type,
int  flags,
int  timeout 
)

Opens and locks the specified file. If the lock cannot be obtained within 'timeout' seconds, then -1 is returned.

Parameters:
filename -- name of the file to lock
lock_type -- type of lock (F_RDLCK, F_WRLCK)
flags -- mode to open the file (O_RDONLY, O_RDWR, etc)
timeout -- number of seconds to wait for lock
Returns:
file descriptor on success, -1 on failure.

Definition at line 317 of file utility.c.

{
  struct itimerval tv = {{timeout, 0}, {timeout, 0}};
  struct itimerval cv = {{0, 0}, {0, 0}};
  struct sigaction act, oldact;
  sigset_t set, oldset;
  int fd;

  memset(&act, 0, sizeof(act));
  act.sa_handler = gs_alarm_catch;
  act.sa_flags = 0; /* no SA_RESTART */
  sigfillset(&act.sa_mask);
  if(sigaction(SIGALRM, &act, &oldact) == -1) {
    ERRPRINTF("error setting up SIGALRM\n");
    return -1;
  }

  sigemptyset(&set);
  sigaddset(&set, SIGALRM);
  if(sigprocmask(SIG_UNBLOCK, &set, &oldset) == -1) {
    ERRPRINTF("sigprocmask failed\n");
    sigaction(SIGALRM, &oldact, NULL);
    return -1;
  }

  setitimer(ITIMER_REAL, &tv, 0);

  fd = gs_open_locked_file(lockfile, lock_type, flags);

  if(fd < 0) {
    setitimer(ITIMER_REAL, &cv, 0);
    sigprocmask(SIG_SETMASK, &oldset, NULL);
    return -1;
  }

  setitimer(ITIMER_REAL, &cv, 0);
  sigprocmask(SIG_SETMASK, &oldset, NULL);
  sigaction(SIGALRM, &oldact, NULL);

  return fd;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_parse_config_file ( char *  filename,
gs_info_t **  tmp 
)

Parse server config file and build linked list of attributes

Parameters:
filename -- the name of the config file to be parsed
tmp -- upon return, contains a list of gs_info_t representing all the attributes parsed from the file
Returns:
0 on success, -1 on failure.

Definition at line 139 of file utility.c.

{
  gs_info_t *sa_headNode;  /* server attribute list */
  int i = 0, linecount = 0;
  char *p, *line;
  FILE *sc_file;

  /* Open server configuration file */
  sc_file = fopen(filename, "r");
  if(!sc_file) {
    ERRPRINTF("Could not open %s file\n", filename);
    return -1;
  }

  /* 
   * parse each line with strtok "="
   * store into the linked list
   * also putenv each attribute
   */
 
  sa_headNode = (gs_info_t *)malloc(sizeof(gs_info_t));
  if(!sa_headNode) {
    fclose(sc_file);
    ERRPRINTF("Could not allocate memory for server attributes\n");
    return -1;
  }
  
  *tmp = sa_headNode;
  while((line = gs_read_line(sc_file, &linecount))) {

    (*tmp)->next   = (gs_info_t *)malloc(sizeof(gs_info_t));
    if(!(*tmp)->next){
      free(line);
      free(sa_headNode);
      fclose(sc_file);
      ERRPRINTF("Could not allocate memory for server attributes\n");
      return -1;
    }
    (*tmp) = (*tmp)->next;

    (*tmp)->value = strdup(strpbrk(line,"=")+1);
    if(!(*tmp)->value){
      free(line);
      free(sa_headNode);
      fclose(sc_file);
      ERRPRINTF("Could not strdup for (*tmp)->value\n");
      return -1;
    }

    (*tmp)->type = strdup(strtok(line,"="));
    if(!(*tmp)->type){
      free(line);
      free(sa_headNode);
      fclose(sc_file);
      ERRPRINTF("Could not strdup for (*tmp)->type\n");
      return -1;
    }

    (*tmp)->next= NULL;
  
    while(((*tmp)->value[strlen((*tmp)->value)-1] == ' ') ||
          ((*tmp)->value[strlen((*tmp)->value)-1] == '\n'))
      (*tmp)->value[strlen((*tmp)->value)-1] = '\0';

    i = strspn((*tmp)->value, " ");
    if(i >0){
      for (p = (*tmp)->value; ; p++){
        *p = *(p+i);
        if(*p == '\0') break;
      }
    }

    while((*tmp)->type[strlen((*tmp)->type)-1] == ' ')
      (*tmp)->type[strlen((*tmp)->type)-1] = '\0';

    sprintf(line,"%s=%s",(*tmp)->type,(*tmp)->value);

    if (putenv(strdup(line)) != 0){
      free(line);
      free(sa_headNode);
      fclose(sc_file);
      ERRPRINTF("Could not putenv \n");
      return -1;
    }

    free(line);
  }
  *tmp = sa_headNode->next;
  free(sa_headNode);
  fclose(sc_file);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static float gs_popen_loadavg ( char *  cmd  )  [static]

Definition at line 429 of file utility.c.

{
  float tmpf = -1;
#ifndef WIN32
  char buf[200], *tmp, tmp2[20];
  FILE *pstream;

  if((pstream = popen(cmd, "r")) == NULL)
    return -1;

  tmp = fgets(buf, 200, pstream);
  pclose(pstream);

  if(!tmp)
    return -1;

  tmp = strstr(buf, "average:");
  if(!tmp)
    return -1;

  if(sscanf(tmp, "%s %f", tmp2, &tmpf) != 2)
    return -1;

#endif
  return tmpf;
}

Here is the caller graph for this function:

char* gs_read_line ( FILE *  f,
int *  linecount 
)

Reads a line from a file. Skips lines starting with a '#' or a '
'. Increments an integer for line counting.

Parameters:
f -- the file to read from
linecount -- set upon return to the current line number
Returns:
the line read from the file. returns NULL on EOF.

Definition at line 113 of file utility.c.

{
  char *tmp = NULL;
  do
  {
    if(tmp)
      free(tmp);
    tmp = gs_get_line(f);
    if(!tmp) 
      break;
    (*linecount)++;
  } while((tmp[0] == '\n')||(tmp[0] == '#'));
  return tmp;
}

Here is the call graph for this function:

Here is the caller graph for this function:

long gs_seconds_since_modified ( char *  filename  ) 

Returns the number of seconds since the specified file was modified.

Parameters:
filename -- the file to check
Returns:
number of seconds or -1 on error.

Definition at line 370 of file utility.c.

{
  gs_struct_stat stbuf;
  struct timeval tv;
  long age;

  if(!filename)
    return -1;
  
  if(gs_stat(filename, &stbuf) < 0)
    return -1;

  gettimeofday(&tv, NULL);

  age = tv.tv_sec - stbuf.st_mtime;

  return age;
}

Here is the caller graph for this function:

int gs_unlock_file ( int  fd  ) 

Unlock the previously locked memory-mapped file.

Parameters:
fd -- the file to unlock
Returns:
0 on success, -1 on failure.

Definition at line 281 of file utility.c.

{
  if(gs_unlock_fd(fd) == -1) {
    ERRPRINTF("Warning: could not unlock file\n");
    perror("unlock");
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_versions_incompatible ( const char *  ver1,
const char *  ver2 
)

Check whether the two versions are not compatible with each other. Currently the numbering is: major.minor.revision and the revision number is not considered significant in terms of compatibility, so 0.18.0 would be compatible with 0.18.3, but not with 0.19.0.

Parameters:
ver1 -- one version number to check
ver2 -- another version number to check
Returns:
1 if the versions are NOT compatible, 0 if they are.

Definition at line 33 of file utility.c.

{
  int maj1, min1, rev1, maj2, min2, rev2, n1, n2;

  if(!ver1 || !ver2) {
    ERRPRINTF("Warning: bad args\n");
    return 1;
  }

  maj1 = min1 = rev1 = maj2 = min2 = rev2 = 0;

  n1 = sscanf(ver1, "%d.%d.%d", &maj1, &min1, &rev1);
  n2 = sscanf(ver2, "%d.%d.%d", &maj2, &min2, &rev2);

  if((n1 < 1) || (n2 < 1)) {
    ERRPRINTF("Warning: malformed version number\n");
    return 1;
  }

  return (maj1 != maj2) || (min1 != min2);
}

Here is the caller graph for this function: