Defines | Functions | Variables

gs_storage_sqlite.c File Reference

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include "gs_storage.h"
#include "utility.h"
#include "server.h"
#include "problem.h"
#include "agent.h"
#include "comm_basics.h"
#include "comm_encode.h"
#include "gs_storage_sql_tables.h"
#include "sqlite3.h"
Include dependency graph for gs_storage_sqlite.c:

Go to the source code of this file.

Defines

#define GS_QUERY_RETRIES   120
#define FREE_TABLE(x)

Functions

int sqliteIsNumber (char *)
int gs_create_criteria_table (char *name, char *description, char *firstValue)
static int gs_insert_task (char *, char *, int, double, double, double, double, int, int, char *, int)
int gs_add_single_problem (gs_agent_t *gs_agent, gs_problem_t *gs_problem, char *cid_string)
 Associated a problem w/ a server, adding the problem if it is unknown.
int gs_init_tables (sqlite3 *db)
int gs_init_db (sqlite3 **db)
int gs_random_sleep (long lo_usec, long hi_usec)
int gs_db_mgr_run_query (sqlite3 *db, char *query, int sz[3], char ***tbl, char **dbErrMsg)
int gs_sqlite_submit_query (char *sql, char ***table, int *nrows, int *ncols, char **dbErrMsg)
 Submits a query to the database manager over unix domain socket.
int gs_storage_init (gs_agent_t *gs_agent)
 Initializes the connection to the database manager.
int gs_sqlite_begin_transaction ()
int gs_sqlite_commit_transaction ()
void gs_storage_finalize (gs_agent_t *gs_agent)
 Finalizes the database.
int gs_add_server (gs_agent_t *gs_agent, gs_server_t *gs_server)
 Add a server to the database.
int gs_delete_problem_if_last_mapping (gs_agent_t *gs_agent, char *problemname)
int gs_delete_server_problems (gs_agent_t *gs_agent, char *cid_string)
int gs_delete_server (gs_agent_t *gs_agent, gs_server_t *gs_server)
 Removes a server and all problem associations from the database.
int gs_insert_submitted_task (char *cid_string, char *taskid, int agent_taskid, double start, double duration, double remaining, double end, int active, int finished)
int gs_insert_submitted_task_guess (char *cid_string, char *taskid, int agent_taskid, double start, double duration, double remaining, double end, int active, int finished)
int gs_insert_completed_task (char *cid_string, char *taskid, int agent_taskid, double start, double duration, double remaining, double end, int active, int finished)
int gs_update_task (char *cid_string, char *old_taskid, char *new_taskid, int agent_taskid, double start, double duration, double remaining, double end, int active, int finished)
int gs_insert_problem (gs_problem_t *gs_problem)
int gs_register_problem_changes (gs_agent_t *gs_agent, gs_problem_t **gs_problem, int num_services, char **models, char **rm_prob, int num_removed, char *cid_string)
int gs_delete_problem (gs_agent_t *gs_agent, char *probname, char *cid_string)
 Disassociate a problem w/ a server.
int gs_update_perf_expr (char *srv_cid, char *probname, char *expr)
int gs_update_ping_list (gs_agent_t *gs_agent, char *cid, char *pings)
 Update a server ping list.
int gs_update_workload (gs_agent_t *gs_agent, gs_server_t *gs_server)
 Update a server workload.
int gs_server_exists (gs_agent_t *gs_agent, gs_server_t *gs_server)
void gs_server_expiration (void **args)
 Called periodically by mfork to expire servers.
void gs_server_expiration_pre (void **args)
 This is called by mfork one time before it begins looping on gs_server_expiration.
void gs_server_expiration_post (void **args)
 This is called by mfork one time when closing out the server expiration process.
int gs_server_expire (gs_agent_t *gs_agent, int timeout)
 Expires all servers that have not updated recently.
int gs_get_server_list (gs_agent_t *gs_agent, gs_problem_t *gs_problem, char *client_criteria, gs_server_t ***servers, int *count)
 Returns a list of servers tha can solve a given problem.
int task_start_compare_function (const void *p1, const void *p2)
int gs_get_tasks_for_server (char *cid_string, gs_htm_task ***tasks, int *count, int sync)
int OLD_gs_get_tasks_for_server (char *cid_string, gs_htm_task ***tasks, int *count)
int gs_get_server_ping_list (gs_agent_t *gs_agent, gs_server_t ***servers, char *cid, int *count)
 Returns a list of servers to be pinged. This is currently going to be all servers with componentIDs less than the requesting server and with SmartGridSolve enabled.
int gs_get_all_smart_servers (gs_agent_t *gs_agent, gs_server_t ***servers, int *count)
 Returns a list of all known SmartGridSolve servers.
int gs_get_all_servers (gs_agent_t *gs_agent, gs_server_t ***servers, int *count)
 Returns a list of all known servers.
int gs_get_problem_list (gs_agent_t *gs_agent, gs_server_t *gs_server, gs_problem_t ***problems, int *count)
 Returns a list of all problems the a given server can solve.
int gs_get_all_problems (gs_agent_t *gs_agent, gs_problem_t ***problems, int *count)
 Get a complete list of all problems.
int gs_get_problem_info (gs_agent_t *gs_agent, gs_problem_t ***problems, int *count, char *name)
 Get a list of problems.
int gs_get_server (gs_agent_t *gs_agent, char *name, gs_server_t *server)
int gs_get_all_servers_by_hostname (gs_agent_t *gs_agent, char *hostname, gs_server_t ***servers, int *count)
int gs_get_task_by_agent_taskid (int agent_taskid, gs_htm_task *task)
int gs_get_server_by_cid (gs_agent_t *gs_agent, char *cid, gs_server_t *server)

Variables

struct sockaddr_un GS_SQL_SOCKADDR
sqlite3 * global_db

Define Documentation

#define FREE_TABLE (  ) 
Value:
do { \
    if(x) { \
      sqlite3_free_table(x); \
      x = NULL; \
    } \
  } while(0);

Definition at line 35 of file gs_storage_sqlite.c.

#define GS_QUERY_RETRIES   120

Definition at line 33 of file gs_storage_sqlite.c.


Function Documentation

int gs_add_server ( gs_agent_t *  gs_agent,
gs_server_t *  gs_server 
)

Add a server to the database.

This is the first step of registering a server. The problems must still be registered. If the server is already in the database success is returned.

Parameters:
gs_agent The agent structure.
gs_server The structure of the server being added.
Returns:
0 on success, -1 on error.

Definition at line 317 of file gs_storage_sqlite.c.

{
  int err, now, nrows, ncols, i;
  char *sql, *dbErrMsg = NULL, cid_string[2 * CID_LEN + 1],
      server_dottedIP[20], proxy_dottedIP[20], **table, *sa_str, *sp_str;
  gs_info_t *attrs;

  DBGPRINTF("Adding Server.\n");

  proxy_cid_to_str(cid_string, gs_server->componentid);
  proxy_ip_to_str(gs_server->ipaddress, server_dottedIP);
  proxy_ip_to_str(gs_server->proxyip, proxy_dottedIP);
  sa_str = strdup("");
  sp_str = strdup(GS_NO_SERVER_PING_UPDATE);
  gs_encode_infolist(&sa_str, gs_server->sa_list);

  now = time(0);
  sql =
      sqlite3_mprintf
      ("INSERT INTO servers (hostname,ipaddress,port,proxyip,proxyport,componentid,arch,data_format,kflops,workload,ncpu,status,availcpu,availmem,nproblems,agenthost,agentport,smart,lastupdate,addedat,infolist,server_pings) VALUES (%Q,%Q,\"%d\",%Q,\"%d\",%Q,%Q,\"%d\",\"%d\",\"%d\",\"%d\",\"%d\",\"%lf\",\"%lf\",\"%d\",%Q,\"%d\",\"%d\",\"%d\",\"%d\",%Q,%Q);",
       gs_server->hostname, server_dottedIP, gs_server->port, proxy_dottedIP,
       gs_server->proxyport, cid_string, gs_server->arch,
       gs_server->data_format, gs_server->kflops, gs_server->workload,
       gs_server->ncpu, gs_server->status, gs_server->availcpu,
       gs_server->availmem, gs_server->nproblems, gs_server->agenthost,
       gs_server->agentport, gs_server->smart, now, now, sa_str, sp_str);

  free(sa_str);

  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);

  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("SQL ERROR: %s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }  
    sqlite3_free(sql);
    return -1;
  }
  sqlite3_free(sql);

  SENSORPRINTF("SRV_UP %s %s\n", gs_server->hostname, cid_string);
  DBGPRINTF("Added Server, now adding attributes.\n");

  /* 
   * Add attributes
   */
  attrs = gs_server->sa_list;
  while(attrs != NULL) {
    i=0;
    while ( !isspace((int)attrs->type[i]) && attrs->type[i] != '\0') i++;
    attrs->type[i] = '\0';
    i=0;
    while ( !isspace((int)attrs->value[i]) && attrs->value[i] != '\0') i++;
    attrs->value[i] = '\0';
    err = gs_create_criteria_table(attrs->type, "", attrs->value);
    if(err < 0) {
      ERRPRINTF("Error adding criteria table.\n");
      return -1;
    }
    if ( sqliteIsNumber(attrs->value) )
      sql =
        sqlite3_mprintf
        ("INSERT INTO %s (value,componentid) values (%s,%Q);",
         attrs->type, attrs->value, cid_string);
    else
      sql =
        sqlite3_mprintf
        ("INSERT INTO %s (value,componentid) values (%Q,%Q);",
         attrs->type, attrs->value, cid_string);
    DBGPRINTF("Submitting Attribute Query.\n");
    err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
    sqlite3_free(sql);
    if(err < 0) {
      ERRPRINTF("SQL Error: %s\n", dbErrMsg);
      if(dbErrMsg) sqlite3_free(dbErrMsg);
      return -1;
    }
    DBGPRINTF("Attribute added: %s.\n", attrs->type);
    attrs = attrs->next;
  }

  return 0;
}

Here is the call graph for this function:

int gs_add_single_problem ( gs_agent_t *  gs_agent,
gs_problem_t *  gs_problem,
char *  cid_string 
)

Associated a problem w/ a server, adding the problem if it is unknown.

Associates problems with servers. If the problem is already in the database, this problem will be checked against the database to confirm that there is no conflict. If the problem is already registered to the server, success is returned.

Parameters:
gs_agent The agent structure.
gs_problem The complete problem structure.
cid_string The component id of the server.
Returns:
0 on success, -1 on error.

Definition at line 904 of file gs_storage_sqlite.c.

{
  int err = 0, pid = 0, nrows = 0, ncols = 0;
  char *sql = 0, *dbErrMsg = 0, **table = 0, *penc = 0;

  DBGPRINTF("ADDING %s to %s\n", gs_problem->name, cid_string);
  /* 
   * encode the problem
   */
  gs_encode_problem(&penc, gs_problem);

  /* 
   * Check if problem already exists
   */
  sql = sqlite3_mprintf("SELECT encoding FROM problems WHERE problemname=%Q;",
                       gs_problem->name);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if(dbErrMsg != NULL)
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    ERRPRINTF("Failed to submit query '%s'\n", sql);
    free(penc);
    sqlite3_free(sql);
    return -1;
  }
  sqlite3_free(sql);
  if(nrows == 1) {
    pid = 1;
  }
  else {
    FREE_TABLE(table);
  }

  /* 
   * If problem is not in db, insert it
   */
  if(!pid) {
    if(gs_insert_problem(gs_problem) < 0) {
      free(penc);
      ERRPRINTF("Failed to insert new problem.\n");
      return -1;
    }
  }
  else {
    int comparison_result;
    char *new_prot, *db_prot;

    /* 
     * Check encoding for differences, looking only at the actual prototype
     */
    gs_problem_t *gs_problem_in_db  = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
    if(!gs_problem_in_db) {
      ERRPRINTF("couldn't malloc space for problem to compare\n");
      return -1;
    }

    if(gs_decode_problem(table[1], gs_problem_in_db) < 0) {
      ERRPRINTF("decoding problem from database failed\n");
      return -1;
    }

    new_prot = gs_problem_prototype(gs_problem);
    db_prot = gs_problem_prototype(gs_problem_in_db);

    comparison_result = strcmp(new_prot, db_prot);

    gs_free_problem(gs_problem_in_db);
    free(new_prot);
    free(db_prot);

    if(comparison_result != 0) {
      gs_server_t **server_list = NULL;
      int server_match, count, i;

      /* this problem exists, but is different than the problem being
       * registered.  if this is the only server that has the problem
       * then allow the new version to be registered.
       */
      count = gs_get_server_list(gs_agent, gs_problem, NULL, &server_list,
                 &count);

      server_match = 0;

      if(server_list) {
        char srv_cid[CID_LEN];

        proxy_str_to_cid(srv_cid, cid_string);

        for(i = 0; i < count; i++) {
          if(!memcmp(srv_cid, server_list[i]->componentid, CID_LEN))
            server_match = 1;

          gs_server_free(server_list[i]);
        }
        free(server_list);
      }

      /* if only one server has the problem and it matches the
       * current server name, then delete the old problem and
       * allow registration of the new version of the problem.
       */
      if((count == 1) && server_match &&
          (gs_delete_problem(gs_agent, gs_problem->name, cid_string) >= 0) &&
          (gs_insert_problem(gs_problem) >= 0))
      {
        LOGPRINTF("Successfully replaced old version of problem %s\n",
           gs_problem->name);
      }
      else {
        FREE_TABLE(table);
        ERRPRINTF("Failed to replace old version of problem '%s'.\n",
          gs_problem->name);
        gs_delete_problem(gs_agent, gs_problem->name, cid_string);
        free(penc);
        return -1;
      }
    }
  }

  free(penc);
  FREE_TABLE(table);

  /* 
   * Associate the problem with the server.
   */
  sql =
      sqlite3_mprintf
      ("INSERT INTO problem_server (problemname,componentid,perf_model_expr) VALUES (%Q,%Q,%Q);",
       gs_problem->name, cid_string, "-1");
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    /* 
     * If we violated a contraint, then the problem must already
     * be registered to this server.  Return success.
     */
    if((err * -1) == SQLITE_CONSTRAINT) {
      return 0;
    }
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    ERRPRINTF("failed to associate problem.. query = '%s'\n", sql);
    sqlite3_free(sql);
    return -1;
  }
  sqlite3_free(sql);

  return 0;
}

Here is the call graph for this function:

int gs_create_criteria_table ( char *  name,
char *  description,
char *  firstValue 
)

Creates a table for the specified attribute.

Parameters:
name -- the name of the attribute (also used for the table name)
description -- description of the attribute
firstValue -- the value of this attribute
Returns:
0 on success, -1 on failure.

Definition at line 2067 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols;

  if(gs_sqlite_begin_transaction() < 0)
    ERRPRINTF("Warning: table lock failed\n");

  /* 
   * Check if criteria is already in db
   */
  sql = sqlite3_mprintf("SELECT 1 FROM criteria WHERE critname = %Q;", name);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    gs_sqlite_commit_transaction();
    return -1;
  }

  FREE_TABLE(table);

  if(nrows > 0) {
    gs_sqlite_commit_transaction();
    return 0;
  }

  /* 
   * Create table, if it's not already there.
   */
  if ( sqliteIsNumber(firstValue) )
  {
    sql =
      sqlite3_mprintf
      ("CREATE TABLE %s (value NUMERIC NOT NULL, componentid VARCHAR(128) NOT NULL, UNIQUE('componentid'));",
       name);
  } else
  {
    sql =
      sqlite3_mprintf
      ("CREATE TABLE %s (value VARCHAR(128) NOT NULL, componentid VARCHAR(128) NOT NULL, UNIQUE('componentid'));",
       name);
  }
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    gs_sqlite_commit_transaction();
    return -1;
  }

  sql =
    sqlite3_mprintf
    ("INSERT INTO criteria (critname,description) VALUES (%Q,%Q);", 
     name, description);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    gs_sqlite_commit_transaction();
    return -1;
  }

  gs_sqlite_commit_transaction();

  return 0;
}

Here is the call graph for this function:

int gs_db_mgr_run_query ( sqlite3 *  db,
char *  query,
int  sz[3],
char ***  tbl,
char **  dbErrMsg 
)

Definition at line 131 of file gs_storage_sqlite.c.

{
  int err, nrows, ncols, retval, continueTrying;
  char **table, *errMsg;
  double wait_time;

  retval = 0;
  *dbErrMsg = NULL;

  DBGPRINTF("About to run query: %s\n", query);

  continueTrying = GS_QUERY_RETRIES;

  wait_time = walltime();

  while(continueTrying) {
    err = sqlite3_get_table(db, query, &table, &nrows, &ncols, &errMsg);

    switch (err) {
      case SQLITE_BUSY:
        DBGPRINTF("[%d] SQLITE_BUSY: sleeping for a while...\n",
          (int)getpid());
        continueTrying--;
        gs_random_sleep(40000, 200000);
        break;
      case SQLITE_OK:
        continueTrying = 0;
        break;
      default:
        continueTrying = 0;
        break;
    }
  }

  wait_time = walltime() - wait_time;

  if(err == SQLITE_BUSY)
    ERRPRINTF("Number of retries exceeded (%d).. total time spent = %g\n",
        GS_QUERY_RETRIES, wait_time);

  if(err != SQLITE_OK) {
    if(errMsg != NULL) {
      ERRPRINTF("SQL Error %d: %s.\n", err, errMsg);
      *dbErrMsg = errMsg;
    }

    sz[0] = err * -1;
    sz[1] = strlen(errMsg);;
    sz[2] = sz[0];

    *tbl = NULL;

    retval = -1;
  }
  else {
    sz[0] = nrows;
    sz[1] = ncols;
    sz[2] = sqlite3_changes(db);

    *tbl = table;
  }

  return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_delete_problem ( gs_agent_t *  gs_agent,
char *  probname,
char *  cid_string 
)

Disassociate a problem w/ a server.

When a problem is disassociated from its last server, it is automatically removed by the database.

Parameters:
gs_agent The agent structure.
probname The name of the problem to delete.
cid_string The server component id to disassociate with.
Returns:
0 on success, -1 on error.

Definition at line 1071 of file gs_storage_sqlite.c.

{
  int err, nrows, ncols;
  char *sql, *dbErrMsg = NULL, **table = NULL;

  if(gs_delete_problem_if_last_mapping(gs_agent, probname) < 0)
    ERRPRINTF("Warning: failed to delete last problem mapping (if needed)\n");

  /* 
   * delete association
   */
  sql =
      sqlite3_mprintf
      ("DELETE FROM problem_server WHERE componentid=%Q AND problemname=%Q;",
       cid_string, probname);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  return 0;
}

Here is the call graph for this function:

int gs_delete_problem_if_last_mapping ( gs_agent_t *  gs_agent,
char *  problemname 
)

This checks whether the last problem-server mapping has been deleted. if so, we go ahead and delete the problem entry from the 'problems' table. This used to be done with a trigger, but it wasn't portable between sqlite and mysql, so it's done manually here.

Definition at line 412 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, ncols, nrows;

  if(gs_sqlite_begin_transaction() < 0)
    ERRPRINTF("Warning: table lock failed\n");

  sql = sqlite3_mprintf("SELECT 1 FROM problem_server WHERE problemname=%Q;",
                       problemname);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);

  sqlite3_free(sql);

  FREE_TABLE(table);

  if(err < 0) {
    if ( dbErrMsg != NULL ) {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }

    gs_sqlite_commit_transaction();

    return -1;
  }

  if(nrows == 1) {
    sql = sqlite3_mprintf("DELETE FROM problems WHERE problemname=%Q;",
                       problemname);
    err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);

    sqlite3_free(sql);

    FREE_TABLE(table);

    if(err < 0) {
      if ( dbErrMsg != NULL ) {
        ERRPRINTF("%s\n", dbErrMsg);
        sqlite3_free(dbErrMsg);
      }

      gs_sqlite_commit_transaction();

      return -1;
    }
  }

  gs_sqlite_commit_transaction();

  return 0;
}

Here is the call graph for this function:

int gs_delete_server ( gs_agent_t *  gs_agent,
gs_server_t *  gs_server 
)

Removes a server and all problem associations from the database.

When a server is removed, the database automatically handles unregistering the related problems and removing problems that no longer have servers.

Parameters:
gs_agent The agent structure.
gs_server The server to remove. Only componentid needs to be filled in.
Returns:
0 on success, -1 on error.

Definition at line 533 of file gs_storage_sqlite.c.

{
  int err, ncols, nrows;
  char *sql, *dbErrMsg = NULL, cid_string[2 * CID_LEN + 1], **table = NULL;
  gs_info_t *attrs, *tmp;

  proxy_cid_to_str(cid_string, gs_server->componentid);

  /* 
   * remove server attributes from their tables.
   */

  sql = sqlite3_mprintf("SELECT infolist FROM servers WHERE componentid=%Q;",
                       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }

    FREE_TABLE(table);

    return -1;
  }

  attrs = NULL;
  err = gs_decode_infolist(table[1], &attrs);

  FREE_TABLE(table);

  while(attrs != NULL) {
    sql = sqlite3_mprintf("DELETE FROM %Q WHERE componentid=%Q;",
                         attrs->type, cid_string);
    err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
    sqlite3_free(sql);
    if(err < 0) {
      if ( dbErrMsg != NULL )
    sqlite3_free(dbErrMsg);
    }
    tmp = attrs;
    attrs = attrs->next;

    FREE_TABLE(table);

    if(tmp) {
      if(tmp->type) free(tmp->type);
      if(tmp->value) free(tmp->value);
      free(tmp);
    }
  }

  /* DELETE SERVER */
  sql = sqlite3_mprintf("DELETE FROM servers WHERE componentid=%Q;",
                       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);

  sqlite3_free(sql);

  FREE_TABLE(table);

  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  if(gs_delete_server_problems(gs_agent, cid_string) < 0) {
    ERRPRINTF("Failed to delete server-problem mappings\n");
    return -1;
  }

  SENSORPRINTF("SRV_RM %s unknown\n", cid_string);

  return 0;
}

Here is the call graph for this function:

int gs_delete_server_problems ( gs_agent_t *  gs_agent,
char *  cid_string 
)

Deletes the problem-server mappings when a server is deleted. This used to be done with a trigger, but it wasn't portable between sqlite and mysql, so it's done manually here.

Definition at line 473 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;

  sql = sqlite3_mprintf("SELECT problemname FROM problem_server WHERE componentid=%Q;",
                       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;

    if(gs_delete_problem_if_last_mapping(gs_agent, table[i]) < 0)
      ERRPRINTF("Warning: could not delete unreferenced problems (if needed)\n");
  }

  FREE_TABLE(table);

  sql = sqlite3_mprintf("DELETE FROM problem_server WHERE componentid=%Q;",
                       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

int gs_get_all_problems ( gs_agent_t *  gs_agent,
gs_problem_t ***  problems,
int *  count 
)

Get a complete list of all problems.

Parameters:
gs_agent The agent structure.
problems The list of problem structures for all known problems. This is allocated by the function.
count The number of known problems.
Returns:
The number of known problems or -1 on error.

Definition at line 1994 of file gs_storage_sqlite.c.

{
  return gs_get_problem_info(gs_agent, problems, count, NULL);
}

Here is the call graph for this function:

int gs_get_all_servers ( gs_agent_t *  gs_agent,
gs_server_t ***  servers,
int *  count 
)

Returns a list of all known servers.

Parameters:
gs_agent The agent structure.
servers A list of all server structures, allocated by the function.
count The number of servers in servers list.
Returns:
number of servers or -1 on error.

Definition at line 1858 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_server_t **server_list;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE 1;");
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;
  server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));

  if(server_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    server_list[nrows-1] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
    if(!server_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    server_list[nrows - 1]->hostname = strdup(table[i]);
    proxy_str_to_ip(&(server_list[nrows - 1]->ipaddress), table[i + 1]);
    server_list[nrows - 1]->port = atoi(table[i + 2]);
    proxy_str_to_ip(&(server_list[nrows - 1]->proxyip), table[i + 3]);
    server_list[nrows - 1]->proxyport = atoi(table[i + 4]);
    proxy_str_to_cid(server_list[nrows - 1]->componentid, table[i + 5]);
    server_list[nrows - 1]->arch = strdup(table[i + 6]);
    server_list[nrows - 1]->data_format = atoi(table[i + 7]);
    server_list[nrows - 1]->kflops = atoi(table[i + 8]);
    server_list[nrows - 1]->workload = atoi(table[i + 9]);
    server_list[nrows - 1]->ncpu = atoi(table[i + 10]);
    server_list[nrows - 1]->status = atoi(table[i + 11]);
    server_list[nrows - 1]->availcpu = atof(table[i + 12]);
    server_list[nrows - 1]->availmem = atof(table[i + 13]);
    server_list[nrows - 1]->nproblems = atoi(table[i + 14]);
    server_list[nrows - 1]->agenthost = strdup(table[i + 15]);
    server_list[nrows - 1]->agentport = atoi(table[i + 16]);
    server_list[nrows - 1]->smart = atoi(table[i + 17]);
    server_list[nrows - 1]->last_update = atoi(table[i + 18]);
#ifdef GS_SMART_GRIDSOLVE
   if(server_list[nrows - 1]->smart==1){
     server_list[nrows - 1]->my_ping_str = strdup(table[i + 21]);
   }
#endif
  }

  FREE_TABLE(table);

  *servers = server_list;
  return *count;
}

Here is the call graph for this function:

int gs_get_all_servers_by_hostname ( gs_agent_t *  gs_agent,
char *  hostname,
gs_server_t ***  servers,
int *  count 
)

Gets a list of all servers with the specified hostname. There can easily be multiple servers with the same name, e.g.:

gridsolve> ./GS_config localhost AGENT: localhost [2 servers] SERVER: localhost.localdomain (192.168.0.103:9000) [cid=20206a66691be13f] SERVER: localhost.localdomain (192.168.0.103:9002) [cid=40409434e7f9d73f]

So we will have to ask the user to disambiguate by using the cid.

Definition at line 2231 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_server_t **server_list;

  *count = -1;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE hostname=%Q;", 
    hostname);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;
  server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));

  if(server_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    server_list[nrows-1] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
    if(!server_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    server_list[nrows - 1]->hostname = strdup(table[i]);
    proxy_str_to_ip(&(server_list[nrows - 1]->ipaddress), table[i + 1]);
    server_list[nrows - 1]->port = atoi(table[i + 2]);
    proxy_str_to_ip(&(server_list[nrows - 1]->proxyip), table[i + 3]);
    server_list[nrows - 1]->proxyport = atoi(table[i + 4]);
    proxy_str_to_cid(server_list[nrows - 1]->componentid, table[i + 5]);
    server_list[nrows - 1]->arch = strdup(table[i + 6]);
    server_list[nrows - 1]->data_format = atoi(table[i + 7]);
    server_list[nrows - 1]->kflops = atoi(table[i + 8]);
    server_list[nrows - 1]->workload = atoi(table[i + 9]);
    server_list[nrows - 1]->ncpu = atoi(table[i + 10]);
    server_list[nrows - 1]->status = atoi(table[i + 11]);
    server_list[nrows - 1]->availcpu = atof(table[i + 12]);
    server_list[nrows - 1]->availmem = atof(table[i + 13]);
    server_list[nrows - 1]->nproblems = atoi(table[i + 14]);
    server_list[nrows - 1]->agenthost = strdup(table[i + 15]);
    server_list[nrows - 1]->agentport = atoi(table[i + 16]);
    server_list[nrows - 1]->last_update = atol(table[i + 17]);
  }

  FREE_TABLE(table);

  *servers = server_list;
  return *count;
}

Here is the call graph for this function:

int gs_get_all_smart_servers ( gs_agent_t *  gs_agent,
gs_server_t ***  servers,
int *  count 
)

Returns a list of all known SmartGridSolve servers.

Parameters:
gs_agent The agent structure.
servers A list of all server structures, allocated by the function.
count The number of servers in servers list.
Returns:
number of servers or -1 on error.

Definition at line 1782 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_server_t **server_list;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE smart=\"1\";");
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;
  server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));

  if(server_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    server_list[nrows-1] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
    if(!server_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    server_list[nrows - 1]->hostname = strdup(table[i]);
    proxy_str_to_ip(&(server_list[nrows - 1]->ipaddress), table[i + 1]);
    server_list[nrows - 1]->port = atoi(table[i + 2]);
    proxy_str_to_ip(&(server_list[nrows - 1]->proxyip), table[i + 3]);
    server_list[nrows - 1]->proxyport = atoi(table[i + 4]);
    proxy_str_to_cid(server_list[nrows - 1]->componentid, table[i + 5]);
    server_list[nrows - 1]->arch = strdup(table[i + 6]);
    server_list[nrows - 1]->data_format = atoi(table[i + 7]);
    server_list[nrows - 1]->kflops = atoi(table[i + 8]);
    server_list[nrows - 1]->workload = atoi(table[i + 9]);
    server_list[nrows - 1]->ncpu = atoi(table[i + 10]);
    server_list[nrows - 1]->status = atoi(table[i + 11]);
    server_list[nrows - 1]->availcpu = atof(table[i + 12]);
    server_list[nrows - 1]->availmem = atof(table[i + 13]);
    server_list[nrows - 1]->nproblems = atoi(table[i + 14]);
    server_list[nrows - 1]->agenthost = strdup(table[i + 15]);
    server_list[nrows - 1]->agentport = atoi(table[i + 16]);
    server_list[nrows - 1]->smart = atoi(table[i + 17]);
    server_list[nrows - 1]->last_update = atoi(table[i + 18]);
    /* skip 19 - addedat */
    /* skip 20 - infolist */
    server_list[nrows - 1]->my_ping_str = strdup(table[i + 21]);
  }

  FREE_TABLE(table);

  *servers = server_list;
  return *count;
}

Here is the call graph for this function:

int gs_get_problem_info ( gs_agent_t *  gs_agent,
gs_problem_t ***  problems,
int *  count,
char *  name 
)

Get a list of problems.

Parameters:
gs_agent The agent structure.
problems The list of problem structures for all known problems. This is allocated by the function.
count The number of known problems.
name Problem name to select.
Returns:
The number of known problems or -1 on error.

Definition at line 2010 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_problem_t **problem_list;

  if(name)
    sql = sqlite3_mprintf("SELECT encoding FROM problems WHERE problemname=%Q;", name);
  else
    sql = sqlite3_mprintf("SELECT encoding FROM problems WHERE 1;");

  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;
  problem_list = (gs_problem_t **) CALLOC(nrows, sizeof(gs_problem_t *));
  if(problem_list == NULL) {
    ERRPRINTF("malloc error in gs_get_problem_list\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    problem_list[nrows - 1] = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
    gs_decode_problem(table[i], problem_list[nrows - 1]);
  }

  FREE_TABLE(table);

  *problems = problem_list;

  return *count;
}

Here is the call graph for this function:

int gs_get_problem_list ( gs_agent_t *  gs_agent,
gs_server_t *  gs_server,
gs_problem_t ***  problems,
int *  count 
)

Returns a list of all problems the a given server can solve.

Parameters:
gs_agent The agent structure.
gs_server The server structure. At least componentid is needed.
problems A list of problem structures known by this server. This is allocated by the function.
count The number of problems in the list.
Returns:
The number on problems or -1 on error.

Definition at line 1938 of file gs_storage_sqlite.c.

{
  int els, err, i, nrows, ncols;
  char *sql, *dbErrMsg = NULL, **table = NULL, cid_string[2 * CID_LEN + 1];
  gs_problem_t **problem_list;

  proxy_cid_to_str(cid_string, gs_server->componentid);
  sql =
      sqlite3_mprintf
      ("SELECT problems.encoding FROM problem_server JOIN problems ON problem_server.problemname = problems.problemname WHERE componentid=%Q;",
       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;

  problem_list = (gs_problem_t **) CALLOC(nrows, sizeof(gs_problem_t *));
  if(problem_list == NULL) {
    ERRPRINTF("malloc error in gs_get_problem_list\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    problem_list[nrows - 1] = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
    gs_decode_problem(table[i], problem_list[nrows - 1]);
  }

  FREE_TABLE(table);

  *problems = problem_list;

  return *count;
}

Here is the call graph for this function:

int gs_get_server ( gs_agent_t *  gs_agent,
char *  name,
gs_server_t *  server 
)

Gets all the information about the specified server from the database.

Parameters:
gs_agent -- pointer to agent struct
name -- hostname of the server
server -- pointer to a server struct which will be filled in here
Returns:
0 on success, -1 on failure.

Definition at line 2158 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols, i;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE hostname=%Q LIMIT 1;",
      name);
  if ( sql == NULL )
  {
    return -1;
  }
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if ( err < 0 )
  {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("Error from database: %s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  if ( nrows == 0 )
  {
    return -1;
  }

  /* fill in structure */
  i = nrows * ncols;
  server->hostname = strdup(table[i]);
  proxy_str_to_ip(&(server->ipaddress), table[i + 1]);
  server->port = atoi(table[i + 2]);
  proxy_str_to_ip(&(server->proxyip), table[i + 3]);
  server->proxyport = atoi(table[i + 4]);
  proxy_str_to_cid(server->componentid, table[i + 5]);
  server->arch = strdup(table[i + 6]);
  server->data_format = atoi(table[i + 7]);
  server->kflops = atoi(table[i + 8]);
  server->workload = atoi(table[i + 9]);
  server->ncpu = atoi(table[i + 10]);
  server->status = atoi(table[i + 11]);
  server->availcpu = atof(table[i + 12]);
  server->availmem = atof(table[i + 13]);
  server->nproblems = atoi(table[i + 14]);
  server->agenthost = strdup(table[i + 15]);
  server->agentport = atoi(table[i + 16]);
  server->smart = atoi(table[i + 17]);
  server->last_update = atoi(table[i + 18]);

  /* 
   * fill in server attribuites
   */
  server->sa_list = NULL;
  gs_decode_infolist(table[i + 20], &(server->sa_list));

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

int gs_get_server_by_cid ( gs_agent_t *  gs_agent,
char *  cid,
gs_server_t *  server 
)

Gets information about the server with the specified component id.

Parameters:
gs_agent -- agent struct
cid -- the server's component id
server -- pointer to a server struct which will be filled in here
Returns:
0 on success, -1 on failure.

Definition at line 2364 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols, i;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE componentid=%Q LIMIT 1;",
      cid);
  if ( sql == NULL )
  {
    return -1;
  }
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if ( err < 0 )
  {
    if ( dbErrMsg != NULL )
    {
      DBGPRINTF("Error from database: %s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  if ( nrows == 0 )
  {
    return -1;
  }
  /* fill in structure */
  i = nrows * ncols;
  server->hostname = strdup(table[i]);
  proxy_str_to_ip(&(server->ipaddress), table[i + 1]);
  server->port = atoi(table[i + 2]);
  proxy_str_to_ip(&(server->proxyip), table[i + 3]);
  server->proxyport = atoi(table[i + 4]);
  proxy_str_to_cid(server->componentid, table[i + 5]);
  server->arch = strdup(table[i + 6]);
  server->data_format = atoi(table[i + 7]);
  server->kflops = atoi(table[i + 8]);
  server->workload = atoi(table[i + 9]);
  server->ncpu = atoi(table[i + 10]);
  server->status = atoi(table[i + 11]);
  server->availcpu = atof(table[i + 12]);
  server->availmem = atof(table[i + 13]);
  server->nproblems = atoi(table[i + 14]);
  server->agenthost = strdup(table[i + 15]);
  server->agentport = atoi(table[i + 16]);
  server->smart = atoi(table[i + 17]);
  server->last_update = atoi(table[i + 18]);

  /* 
   * fill in server attribuites
   */
  server->sa_list = NULL;
  gs_decode_infolist(table[i + 20], &(server->sa_list));

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

int gs_get_server_list ( gs_agent_t *  gs_agent,
gs_problem_t *  gs_problem,
char *  client_criteria,
gs_server_t ***  servers,
int *  count 
)

Returns a list of servers tha can solve a given problem.

Parameters:
gs_agent The agent structure.
gs_problem The problem structure. Just problemname is needed, the rest will be filled in.
client_criteria Cliet criteria to match. If NULL, it is ignored.
servers An array of server structures of servers that can solve the requested problem. This is allocated in the function.
count The number of servers in servers list.
Returns:
number of servers on success, -1 on error.

Definition at line 1376 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, table_els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_server_t **server_list;

  /* 
   * fill in remaining problem information.
   */
  sql = sqlite3_mprintf("SELECT encoding FROM problems WHERE problemname=%Q;",
                       gs_problem->name);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  if(nrows > 0) {
    free(gs_problem->name);
    gs_problem->name = NULL;
    err = gs_decode_problem(table[1], gs_problem);
  }
  FREE_TABLE(table);

  if(client_criteria == NULL) {
    /* 
     * get servers associated with this problem.
     */
    sql =
        sqlite3_mprintf
        ("SELECT servers.*,problem_server.perf_model_expr FROM problem_server JOIN servers ON problem_server.componentid = servers.componentid WHERE problemname=%Q;",
         gs_problem->name);
  }
  else {                        /* we need to consider server attributes */
    char *critq, *gs_parse_client_criteria(char *, int);

    critq = gs_parse_client_criteria(client_criteria, GS_CRIT_PARSE_SQLITE);
    sql = sqlite3_mprintf(critq, gs_problem->name);
    FREE(critq);
  }
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s %d\n", dbErrMsg, nrows);
      sqlite3_free(dbErrMsg);
    }
    (*servers) = NULL;
    return -1;
  }
  *count = nrows;
  server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
  if(server_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  table_els = (nrows + 1) * ncols - 1;

  for(; nrows > 0; nrows--) {
    /* fill in servers array */
    i = nrows * ncols;
    server_list[nrows-1] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
    server_list[nrows - 1]->hostname = strdup(table[i]);
    proxy_str_to_ip(&(server_list[nrows - 1]->ipaddress), table[i + 1]);
    server_list[nrows - 1]->port = atoi(table[i + 2]);
    proxy_str_to_ip(&(server_list[nrows - 1]->proxyip), table[i + 3]);
    server_list[nrows - 1]->proxyport = atoi(table[i + 4]);
    proxy_str_to_cid(server_list[nrows - 1]->componentid, table[i + 5]);
    server_list[nrows - 1]->arch = strdup(table[i + 6]);
    server_list[nrows - 1]->data_format = atoi(table[i + 7]);
    server_list[nrows - 1]->kflops = atoi(table[i + 8]);
    server_list[nrows - 1]->workload = atoi(table[i + 9]);
    server_list[nrows - 1]->ncpu = atoi(table[i + 10]);
    server_list[nrows - 1]->status = atoi(table[i + 11]);
    server_list[nrows - 1]->availcpu = atof(table[i + 12]);
    server_list[nrows - 1]->availmem = atof(table[i + 13]);
    server_list[nrows - 1]->nproblems = atoi(table[i + 14]);
    server_list[nrows - 1]->agenthost = strdup(table[i + 15]);
    server_list[nrows - 1]->agentport = atoi(table[i + 16]);
    server_list[nrows - 1]->smart = atoi(table[i + 17]);
    server_list[nrows - 1]->last_update = atoi(table[i + 18]);

    /* skip 19 for addedat */

    /* 
     * fill in server attribuites
     */
    server_list[nrows - 1]->sa_list = NULL;

    gs_decode_infolist(table[i + 20], &(server_list[nrows - 1]->sa_list));

    server_list[nrows - 1]->my_ping_str = strdup(table[i+21]);
 
    server_list[nrows - 1]->perf_expr = strdup(table[i+22]);
  }

  FREE_TABLE(table);

  *servers = server_list;
  return *count;
}

Here is the call graph for this function:

int gs_get_server_ping_list ( gs_agent_t *  gs_agent,
gs_server_t ***  servers,
char *  cid,
int *  count 
)

Returns a list of servers to be pinged. This is currently going to be all servers with componentIDs less than the requesting server and with SmartGridSolve enabled.

Parameters:
gs_agent The agent structure.
servers A list of all server structures, allocated by the function.
cid The component ID of the requesting server
count The number of servers in servers list.
Returns:
number of servers or -1 on error.

Definition at line 1709 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_server_t **server_list;

  sql = sqlite3_mprintf("SELECT * FROM servers WHERE componentid<%Q AND smart=\"1\";", cid);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);
  *count = nrows;
  server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));

  if(server_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;
    server_list[nrows-1] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
    if(!server_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    server_list[nrows - 1]->hostname = strdup(table[i]);
    proxy_str_to_ip(&(server_list[nrows - 1]->ipaddress), table[i + 1]);
    server_list[nrows - 1]->port = atoi(table[i + 2]);
    proxy_str_to_ip(&(server_list[nrows - 1]->proxyip), table[i + 3]);
    server_list[nrows - 1]->proxyport = atoi(table[i + 4]);
    proxy_str_to_cid(server_list[nrows - 1]->componentid, table[i + 5]);
    server_list[nrows - 1]->arch = strdup(table[i + 6]);
    server_list[nrows - 1]->data_format = atoi(table[i + 7]);
    server_list[nrows - 1]->kflops = atoi(table[i + 8]);
    server_list[nrows - 1]->workload = atoi(table[i + 9]);
    server_list[nrows - 1]->ncpu = atoi(table[i + 10]);
    server_list[nrows - 1]->status = atoi(table[i + 11]);
    server_list[nrows - 1]->availcpu = atof(table[i + 12]);
    server_list[nrows - 1]->availmem = atof(table[i + 13]);
    server_list[nrows - 1]->nproblems = atoi(table[i + 14]);
    server_list[nrows - 1]->agenthost = strdup(table[i + 15]);
    server_list[nrows - 1]->agentport = atoi(table[i + 16]);
    server_list[nrows - 1]->smart = atoi(table[i + 17]);
    server_list[nrows - 1]->last_update = atoi(table[i + 18]);
  }

  FREE_TABLE(table);

  *servers = server_list;
  return *count;
}

Here is the call graph for this function:

int gs_get_task_by_agent_taskid ( int  agent_taskid,
gs_htm_task *  task 
)

Finds a task with the specified agent-generated task id.

Parameters:
agent_taskid -- the task id of the job to find.
task -- pointer to a task structure which will be filled in here
Returns:
0 on success, -1 on failure.

Definition at line 2309 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols, i;

  sql = sqlite3_mprintf("SELECT * FROM tasks WHERE t_agent_taskid=\"%d\" LIMIT 1;", 
    agent_taskid);

  if ( sql == NULL ) {
    return -1;
  }

  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if ( err < 0 ) {
    if ( dbErrMsg != NULL ) {
      ERRPRINTF("Error from database: %s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  if ( nrows == 0 ) {
    return -1;
  }

  /* fill in structure */
  i = nrows * ncols;

  strcpy(task->id, table[i+1]);
  task->agent_taskid = atof(table[i+2]);
  task->start = atof(table[i+3]);
  task->duration = atof(table[i+4]);
  task->remaining = atof(table[i+5]);
  task->end = atof(table[i+6]);
  task->active = atoi(table[i+7]);
  task->finished = atoi(table[i+8]);
  task->next = NULL;

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

int gs_get_tasks_for_server ( char *  cid_string,
gs_htm_task ***  tasks,
int *  count,
int  sync 
)

Gets all the tasks (jobs) that are currently running or have recently run on the specified server.

Parameters:
cid_string -- the server's component id
tasks -- upon return, this contains an array of pointers to task structures. memory is allocted here.
count -- upon return, this is set to the number of entries in the tasks array.
sync -- whether to get synchronized task durations (1=synchronized, 0=unsynchronized i.e. prediction only)
Returns:
0 on success, -1 on failure.

Definition at line 1521 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_htm_task **task_list;

  *count = -1;

  sql = sqlite3_mprintf("select * from (select * from tasks,completed_tasks where tasks.t_taskid=completed_tasks.c_taskid and tasks.t_componentid=completed_tasks.c_componentid union select * from tasks,completed_tasks where completed_tasks.c_taskid='-1' and tasks.t_taskid not in (select tasks.t_taskid from tasks,completed_tasks where tasks.t_taskid=completed_tasks.c_taskid and tasks.t_componentid=completed_tasks.c_componentid) union select * from tasks,completed_tasks where tasks.t_taskid='-1' and completed_tasks.c_taskid not in (select tasks.t_taskid from tasks,completed_tasks where tasks.t_taskid=completed_tasks.c_taskid and tasks.t_componentid=completed_tasks.c_componentid)) as foo where t_componentid=%Q or c_componentid=%Q;", cid_string, cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  } 

  sqlite3_free(sql);
  *count = nrows;
  task_list = (gs_htm_task **) CALLOC(nrows, sizeof(gs_htm_task *));

  if(task_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;

    task_list[nrows - 1] = (gs_htm_task *) CALLOC(1, sizeof(gs_htm_task));

    if(!task_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    if(table[i+1] && table[i+10] && strcmp(table[i+1], "-1") && strcmp(table[i+10], "-1")) {
      /* entry exists in both tasks and completed_tasks */

      /* skip table[i] which is component_id */
      strcpy(task_list[nrows - 1]->id, table[i+1]);
      /* skip table[i+2] which is agent_taskid */
      if(sync) {
        task_list[nrows - 1]->start = MIN(atof(table[i+3]), atof(table[i+12]));
        task_list[nrows - 1]->end = MAX(atof(table[i+6]), atof(table[i+15]));
        task_list[nrows - 1]->duration = task_list[nrows - 1]->end - task_list[nrows - 1]->start;
      }
      else {
        task_list[nrows - 1]->start = atof(table[i+3]);
        task_list[nrows - 1]->end = atof(table[i+6]);
        task_list[nrows - 1]->duration = atof(table[i+4]);
      }
      task_list[nrows - 1]->remaining = atof(table[i+14]);
      task_list[nrows - 1]->active = atoi(table[i+7]);
      task_list[nrows - 1]->finished = atoi(table[i+17]);
      task_list[nrows - 1]->next = NULL;
    }
    else if(table[i+1] && strcmp(table[i+1], "-1")) {
      /* entry exists in only in tasks */

      /* skip table[i] which is component_id */
      strcpy(task_list[nrows - 1]->id, table[i+1]);
      /* skip table[i+2] which is agent_taskid */
      task_list[nrows - 1]->start = atof(table[i+3]);
      task_list[nrows - 1]->duration = atof(table[i+4]);
      task_list[nrows - 1]->remaining = atof(table[i+5]);
      task_list[nrows - 1]->end = atof(table[i+6]);
      task_list[nrows - 1]->active = atoi(table[i+7]);
      task_list[nrows - 1]->finished = atoi(table[i+8]);
      task_list[nrows - 1]->next = NULL;
    }
    else if(table[i+10] && strcmp(table[i+10], "-1")) {
      /* entry exists in only in completed_tasks */

      /* skip table[i+9] which is component_id */
      strcpy(task_list[nrows - 1]->id, table[i+10]);
      /* skip table[i+11] which is agent_taskid */
      task_list[nrows - 1]->start = atof(table[i+12]);
      task_list[nrows - 1]->duration = atof(table[i+13]);
      task_list[nrows - 1]->remaining = atof(table[i+14]);
      task_list[nrows - 1]->end = atof(table[i+15]);
      task_list[nrows - 1]->active = atoi(table[i+16]);
      task_list[nrows - 1]->finished = atoi(table[i+17]);
      task_list[nrows - 1]->next = NULL;
    }
    else {
      /* should not hit this case */
      ERRPRINTF("Unexpected result from query.\n");
      return -1;
    }

    /* make sure duration isn't some weird value */
    if(task_list[nrows - 1]->duration <= 0.0)
      task_list[nrows - 1]->duration = 0.001;
  }

  FREE_TABLE(table);

  qsort(task_list, nrows, sizeof(gs_htm_task *), task_start_compare_function);

  *tasks = task_list;
  return 0;
}

Here is the call graph for this function:

int gs_init_db ( sqlite3 **  db  ) 

Definition at line 92 of file gs_storage_sqlite.c.

{
  int err;

  unlink(GRIDSOLVE_SQLITE_DB);

  /*
   * open database
   */
  err = sqlite3_open(GRIDSOLVE_SQLITE_DB, db);
  if( err != SQLITE_OK ) {
    ERRPRINTF("Error connecting to database: %s\n", sqlite3_errmsg(*db));
    return -1;
  }

  if(gs_init_tables(*db) < 0) {
    ERRPRINTF("Error initializing database tables\n");
    return -1;
  }
  
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_init_tables ( sqlite3 *  db  ) 

Definition at line 58 of file gs_storage_sqlite.c.

{
  char **table, *dbErrMsg;
  int i, err, nr, nc;
  char *cmds[] = {
    GS_SQL_SERVER_TABLE,
    GS_SQL_PROBLEM_TABLE,
    GS_SQL_PROBLEM_SERVER_MAPPING_TABLE,
    GS_SQL_CRITERIA_TABLE,
    GS_SQL_TASKS_TABLE,
    GS_SQL_INIT_TASKS_TABLE,
    GS_SQL_COMPLETED_TASKS_TABLE,
    GS_SQL_INIT_COMPLETED_TASKS_TABLE,
    GS_SQL_EXTRA_OPTIONS,
    NULL};

  for(i=0; cmds[i]; i++) {
    /*
     * Initialize the database.  Ingnore failure that could result
     * from attempting to re-initialize the database
     */
    err = sqlite3_get_table(db, cmds[i], &table, &nr, &nc, &dbErrMsg);
    if(err != SQLITE_OK && err != SQLITE_CONSTRAINT && err != SQLITE_ERROR) {
      ERRPRINTF("Error initializing database: %d: %s\n", err, dbErrMsg);
      return -1;
    }

    FREE_TABLE(table);
  }

  return 0;
}

Here is the caller graph for this function:

int gs_insert_completed_task ( char *  cid_string,
char *  taskid,
int  agent_taskid,
double  start,
double  duration,
double  remaining,
double  end,
int  active,
int  finished 
)

This inserts a new task completion record into the database.

Parameters:
cid_string -- the component id of the server that the task is running on
taskid -- the request id generated by the server.
agent_taskid -- the agent-generated task id.
start -- the task's start time.
duration -- the task's execution time.
remaining -- number of seconds remaining in the task's execution.
end -- the task's completion time.
active -- currently for internal use. pass 0 for this param.
finished -- pass TRUE if the task has completed, FALSE otherwise.
Returns:
0 on success, -1 on failure.

Definition at line 695 of file gs_storage_sqlite.c.

{
  return gs_insert_task(cid_string, taskid, agent_taskid, start,
    duration, remaining, end, active, finished, "completed_tasks", 1);
}

Here is the call graph for this function:

int gs_insert_problem ( gs_problem_t *  gs_problem  ) 

Inserts a problem encoding into the database.

Parameters:
gs_problem -- pointer to the problem struct to insert
Returns:
0 on success, -1 on failure.

Definition at line 819 of file gs_storage_sqlite.c.

{
  int err = 0, nrows = 0, ncols = 0;
  char *sql = 0, *dbErrMsg = 0, **table = 0, *penc = 0;

  if(gs_encode_problem(&penc, gs_problem) < 0)
    return -1;

  sql = sqlite3_mprintf("INSERT INTO problems (problemname,encoding) VALUES (%Q,%Q);",
         gs_problem->name, penc);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    free(penc);
    gs_sqlite_commit_transaction();
    return -1;
  }

  sqlite3_free(sql);
  free(penc);

  return 0;
}

Here is the call graph for this function:

int gs_insert_submitted_task ( char *  cid_string,
char *  taskid,
int  agent_taskid,
double  start,
double  duration,
double  remaining,
double  end,
int  active,
int  finished 
)

Inserts a task into the database. This inserts a new task submission record into the database.

Parameters:
cid_string -- the component id of the server that the task is running on
taskid -- the request id generated by the server.
agent_taskid -- the agent-generated task id.
start -- the task's start time.
duration -- the task's execution time.
remaining -- number of seconds remaining in the task's execution.
end -- the task's completion time.
active -- currently for internal use. pass 0 for this param.
finished -- pass TRUE if the task has completed, FALSE otherwise.
Returns:
0 on success, -1 on failure.

Definition at line 639 of file gs_storage_sqlite.c.

{
  return gs_insert_task(cid_string, taskid, agent_taskid, start,
    duration, remaining, end, active, finished, "tasks", 1);
}

Here is the call graph for this function:

int gs_insert_submitted_task_guess ( char *  cid_string,
char *  taskid,
int  agent_taskid,
double  start,
double  duration,
double  remaining,
double  end,
int  active,
int  finished 
)

This inserts a new task submission record into the database. This is basically the same as gs_insert_submitted_task() except that we use this one when the taskid string has not been obtained from the server yet. In that case, we don't overwrite any previous DB entries.

Parameters:
cid_string -- the component id of the server that the task is running on
taskid -- the request id generated by the server.
agent_taskid -- the agent-generated task id.
start -- the task's start time.
duration -- the task's execution time.
remaining -- number of seconds remaining in the task's execution.
end -- the task's completion time.
active -- currently for internal use. pass 0 for this param.
finished -- pass TRUE if the task has completed, FALSE otherwise.
Returns:
0 on success, -1 on failure.

Definition at line 669 of file gs_storage_sqlite.c.

{
  return gs_insert_task(cid_string, taskid, agent_taskid, start,
    duration, remaining, end, active, finished, "tasks", 0);
}

Here is the call graph for this function:

static int gs_insert_task ( char *  cid_string,
char *  taskid,
int  agent_taskid,
double  start,
double  duration,
double  remaining,
double  end,
int  active,
int  finished,
char *  tname,
int  clobber 
) [static]

This is common code used by gs_insert_completed_task() and gs_insert_submitted_task() to insert a new task record into the database.

Parameters:
cid_string -- the component id of the server that the task is running on
taskid -- the request id generated by the server.
agent_taskid -- the agent-generated task id.
start -- the task's start time.
duration -- the task's execution time.
remaining -- number of seconds remaining in the task's execution.
end -- the task's completion time.
active -- currently for internal use. pass 0 for this param.
finished -- pass TRUE if the task has completed, FALSE otherwise.
tname -- the name of the table to insert this record into. currently this should be "tasks" or "completed_tasks".
clobber -- overwrite previous row? (1=yes, 0=no)
Returns:
0 on success, -1 on failure.

Definition at line 725 of file gs_storage_sqlite.c.

{
  int err = 0, nrows = 0, ncols = 0;
  char *sql = 0, *dbErrMsg = 0, **table = 0, *conflict_res;

  switch(clobber) {
    case 0:
      conflict_res = "IGNORE";
      break;
    case 1:
      conflict_res = "REPLACE";
      break;
    default:
      ERRPRINTF("Bad arg value for clobber: %d\n", clobber);
      return -1;
      break;
  }

  sql = sqlite3_mprintf("INSERT OR %s INTO %s VALUES (%Q,%Q,\"%d\",\"%lf\",\"%lf\",\"%lf\",\"%lf\",\"%d\",\"%d\");",
           conflict_res, tname, cid_string, taskid, agent_taskid, start, duration, remaining, end, active, finished);

  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  sqlite3_free(sql);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_random_sleep ( long  lo_usec,
long  hi_usec 
)

Definition at line 116 of file gs_storage_sqlite.c.

{
  struct timeval tv;

  gettimeofday(&tv, NULL);

  srand48(tv.tv_usec);

  tv.tv_sec = 0;
  tv.tv_usec = lo_usec + (lrand48() % hi_usec);

  return select(0, NULL, NULL, NULL, &tv);
}

Here is the caller graph for this function:

int gs_register_problem_changes ( gs_agent_t *  gs_agent,
gs_problem_t **  gs_problem,
int  num_services,
char **  models,
char **  rm_prob,
int  num_removed,
char *  cid_string 
)

Adds all the problems in the given array.

Parameters:
gs_problem array of complete problem structures.
num_services number of elements in gs_problem
models array of performance models
rm_prob array of problem names to be removed
num_removed number of elements in rm_prob
Returns:
0 on success, -1 on error.

Definition at line 858 of file gs_storage_sqlite.c.

{
  int i;

  if(gs_sqlite_begin_transaction() < 0)
    ERRPRINTF("Warning: table lock failed\n");

  for(i=0;i<num_services;i++) {
    if(gs_add_single_problem(gs_agent, gs_problem[i], cid_string) < 0) {
      ERRPRINTF("Add problem failed.\n");
      gs_sqlite_commit_transaction();
      return -1;
    }

    if(gs_update_perf_expr(cid_string, gs_problem[i]->name, models[i]) < 0)
      ERRPRINTF("Warning: failed to update perf model expression\n");
  }

  gs_sqlite_commit_transaction();

  for(i=0;i<num_removed;i++) {
    if(gs_delete_problem(gs_agent, rm_prob[i], cid_string) < 0)
      ERRPRINTF("Failed to delete problem: %s\n", rm_prob[i]);
    else
      LOGPRINTF("Unregistered problem %s\n", rm_prob[i]);
  }

  return 0;
}

Here is the call graph for this function:

int gs_server_exists ( gs_agent_t *  gs_agent,
gs_server_t *  gs_server 
)

Checks whether a server is registered.

Parameters:
gs_agent The agent structure.
gs_server The server structure. At least componentid must be filled in.
Returns:
0 if server is not registered, 1 if it is, -1 on error.

Definition at line 1221 of file gs_storage_sqlite.c.

{
  int err, nrows, ncols;
  char *sql, *dbErrMsg = NULL, **table = NULL, cid_string[2 * CID_LEN + 1];

  proxy_cid_to_str(cid_string, gs_server->componentid);

  sql = sqlite3_mprintf("SELECT 1 FROM servers WHERE componentid=%Q;",
                       cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }

  if(nrows > 0) {
    FREE_TABLE(table);
    return 1;
  }
  else {
    return 0;
  }
}

Here is the call graph for this function:

void gs_server_expiration ( void **  args  ) 

Called periodically by mfork to expire servers.

This function should be spawned as a thread at agent start-up. It periodically checks the database and removes servers that haven't contacted us recently.

Parameters:
args This is the arg list supplied when mfork was called. args[0] should be a pointer to the gs_agent structure. args[1] should be a pointer to the (integer) timeout value.

Definition at line 1261 of file gs_storage_sqlite.c.

{
  gs_agent_t *agent;
  int timeout;

  agent = (gs_agent_t *) args[0];
  timeout = *((int *) args[1]);

  gs_server_expire(agent, timeout);
}

Here is the call graph for this function:

void gs_server_expiration_post ( void **  args  ) 

This is called by mfork one time when closing out the server expiration process.

Parameters:
args This is the arg list supplied when mfork was called. args[0] should be a pointer to the gs_agent structure. args[1] should be a pointer to the (integer) timeout value.

Definition at line 1303 of file gs_storage_sqlite.c.

{
  gs_agent_t *agent;
  agent = (gs_agent_t *) args[0];
  DBGPRINTF("Closing connection to db manager.\n");
  gs_storage_finalize(agent);
}

Here is the call graph for this function:

void gs_server_expiration_pre ( void **  args  ) 

This is called by mfork one time before it begins looping on gs_server_expiration.

Parameters:
args This is the arg list supplied when mfork was called. args[0] should be a pointer to the gs_agent structure. args[1] should be a pointer to the (integer) timeout value.

Definition at line 1279 of file gs_storage_sqlite.c.

{
  gs_agent_t *agent;
  int timeout;

  agent = (gs_agent_t *) args[0];
  timeout = *((int *) args[1]);
  if ( gs_storage_init(agent) < 0 )
  {
    ERRPRINTF("Error connecting to database manager.\n");
    return;
  }
  DBGPRINTF("Connected to db manager.\n");
  gs_server_expire(agent, timeout);
}

Here is the call graph for this function:

int gs_server_expire ( gs_agent_t *  gs_agent,
int  timeout 
)

Expires all servers that have not updated recently.

Removes all servers and their associated problems if they haven't sent a workload report in more than timeout seconds.

Parameters:
gs_agent The agent structure.
timeout The number of seconds for the timeout value.
Returns:
0 on success, -1 on error.

Definition at line 1321 of file gs_storage_sqlite.c.

{
  int i, err, now, nrows, ncols;
  char *sql, *dbErrMsg = NULL, **table = NULL;

  now = time(0);
  sql = sqlite3_mprintf("SELECT componentid FROM servers WHERE lastupdate < \"%ld\";",
                        now - timeout);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);

  if(table != NULL) {
    gs_server_t tmpsrv;

    /* just in case */
    memset(&tmpsrv, 0, sizeof(tmpsrv));

    for(i = 1; i < (nrows + 1) * ncols; i++)
    {
      ERRPRINTF("expiring %s\n", table[i]);

      proxy_str_to_cid(tmpsrv.componentid, table[i]);
      if(gs_delete_server(gs_agent, &tmpsrv) < 0)
        ERRPRINTF("Failed to delete server '%s'\n", table[i]);
    }

    FREE_TABLE(table);
  }

  return 0;
}

Here is the call graph for this function:

int gs_sqlite_begin_transaction (  ) 

Definition at line 256 of file gs_storage_sqlite.c.

{
  char *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols;

  err = gs_sqlite_submit_query("begin transaction;", &table, 
    &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    ERRPRINTF("Error beginning transaction\n");
    return -1;
  }

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_sqlite_commit_transaction (  ) 

Definition at line 274 of file gs_storage_sqlite.c.

{
  char *dbErrMsg = NULL, **table = NULL;
  int err, nrows, ncols;

  err = gs_sqlite_submit_query("commit transaction;", &table,
    &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    ERRPRINTF("Error beginning transaction\n");
    return -1;
  }

  FREE_TABLE(table);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int gs_sqlite_submit_query ( char *  sql,
char ***  table,
int *  nrows,
int *  ncols,
char **  dbErrMsg 
)

Submits a query to the database manager over unix domain socket.

Parameters:
sql The SQL query
table Pointer to a char** table that will be allocated and returned containing the results. See the SQLite documentation about how this table is formatted.
nrows The number of rows returned.
ncols The number of cols returned.
dbErrMsg If an error is returned from SQLite, this will contain the error string.
Returns:
The number of changes (>= 0) or -1 if an error occurred (if the error came from SQLite, dbErrMsg will contain the error string.)

Definition at line 213 of file gs_storage_sqlite.c.

{
  int sz[3];

  *nrows = 0;
  *ncols = 0;
  *table = NULL;

  if(!sql)
    return -1;

  if(gs_db_mgr_run_query(global_db, sql, sz, table, dbErrMsg) < 0) {
    ERRPRINTF("Query failed\n");
    return -1;
  }

  *nrows = sz[0];
  *ncols = sz[1];

  return sz[2];
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gs_storage_finalize ( gs_agent_t *  gs_agent  ) 

Finalizes the database.

Since the database manager was added, this function does nothing, but may do something in the future.

Parameters:
gs_agent The agent structure.

Definition at line 299 of file gs_storage_sqlite.c.

{
  sqlite3_close(global_db);

  return;
}

int gs_storage_init ( gs_agent_t *  gs_agent  ) 

Initializes the connection to the database manager.

Parameters:
gs_agent The agent structure.
Returns:
0 on success, -1 on error.

Definition at line 241 of file gs_storage_sqlite.c.

{
  int err;

  err = sqlite3_open(GRIDSOLVE_SQLITE_DB, &global_db);
  if( err != SQLITE_OK ) {
    ERRPRINTF("Error opening to database: %s\n",
        sqlite3_errmsg(global_db));
    return -1;
  }

  return 0;
}

int gs_update_perf_expr ( char *  srv_cid,
char *  probname,
char *  expr 
)

Updates the performance expression, which is used to compute the estimated execution time of a particular instance of a problem on a specific server.

Parameters:
srv_cid -- the component id of the server
probname -- the name of the problem
expr -- the new performance expression
Returns:
0 on success, -1 on failure.

Definition at line 1113 of file gs_storage_sqlite.c.

{
  char *sql, *dbErrMsg = NULL, **table = NULL;
  int err, ncols, nrows;

  sql = sqlite3_mprintf("UPDATE problem_server SET perf_model_expr=%Q WHERE componentid=%Q AND problemname=%Q;",
       expr, srv_cid, probname);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);

  if(err == 0) {
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

int gs_update_ping_list ( gs_agent_t *  gs_agent,
char *  cid,
char *  pings 
)

Update a server ping list.

Parameters:
gs_agent The agent structure.
cid The server component ID
pings The ping list (string)
Returns:
0 on success, -1 on error.

Definition at line 1146 of file gs_storage_sqlite.c.

{
  int now, err, ncols, nrows;
  char *sql, *dbErrMsg = NULL, **table = NULL;

  now = time(0);
  sql =
      sqlite3_mprintf("UPDATE servers SET server_pings=%Q WHERE componentid=%Q;",
        pings, cid);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);

  if(err == 0) {
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

int gs_update_task ( char *  cid_string,
char *  old_taskid,
char *  new_taskid,
int  agent_taskid,
double  start,
double  duration,
double  remaining,
double  end,
int  active,
int  finished 
)

This updates the task corresponding to "old_taskid" with all the specified parameters.

Parameters:
cid_string -- the component id of the server that the task is running on
old_taskid -- the temporary request id generated by the agent.
new_taskid -- the real request id generated by the server.
agent_taskid -- the agent-generated task id.
start -- the task's start time.
duration -- the task's execution time.
remaining -- number of seconds remaining in the task's execution.
end -- the task's completion time.
active -- currently for internal use. pass 0 for this param.
finished -- pass TRUE if the task has completed, FALSE otherwise.
Returns:
0 on success, -1 on failure.

Definition at line 782 of file gs_storage_sqlite.c.

{
  int err, ncols, nrows;
  char *sql, *dbErrMsg = NULL, **table = NULL;

  sql = sqlite3_mprintf("UPDATE tasks SET t_componentid=%Q, t_taskid=%Q, t_agent_taskid=\"%d\", t_start=\"%lf\", t_duration=\"%lf\", t_remaining=\"%lf\", t_end=\"%lf\", t_active=\"%d\", t_finished=\"%d\" WHERE t_taskid=%Q;",
           cid_string, new_taskid, agent_taskid, start, duration, remaining, end, active, finished, old_taskid);

  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);

  if(err == 0) {
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

int gs_update_workload ( gs_agent_t *  gs_agent,
gs_server_t *  gs_server 
)

Update a server workload.

Parameters:
gs_agent The agent structure.
gs_server The server structure. At least componentid and workload must be filled in.
Returns:
0 on success, -1 on error.

Definition at line 1181 of file gs_storage_sqlite.c.

{
  int now, err, ncols, nrows;
  char *sql, *dbErrMsg = NULL, cid_string[2 * CID_LEN + 1], **table = NULL;

  proxy_cid_to_str(cid_string, gs_server->componentid);

  now = time(0);
  sql =
      sqlite3_mprintf
      ("UPDATE servers SET workload=\"%d\", nproblems=\"%d\", lastupdate=\"%ld\" WHERE componentid=%Q;",
       gs_server->workload, gs_server->nproblems, now, cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  }
  sqlite3_free(sql);

  SENSORPRINTF("WORK %s %d\n", cid_string, gs_server->workload);

  if(err == 0) {
    return -1;
  }

  return 0;
}

Here is the call graph for this function:

int OLD_gs_get_tasks_for_server ( char *  cid_string,
gs_htm_task ***  tasks,
int *  count 
)

Definition at line 1634 of file gs_storage_sqlite.c.

{
  int err, i, nrows, ncols, els;
  char *sql, *dbErrMsg = NULL, **table = NULL;
  gs_htm_task **task_list;

  *count = -1;

  sql = sqlite3_mprintf("SELECT * FROM taskviewjoin WHERE componentid=%Q;",
    cid_string);
  err = gs_sqlite_submit_query(sql, &table, &nrows, &ncols, &dbErrMsg);
  if(err < 0) {
    if ( dbErrMsg != NULL )
    {
      ERRPRINTF("%s\n", dbErrMsg);
      sqlite3_free(dbErrMsg);
    }
    return -1;
  } 

  sqlite3_free(sql);
  *count = nrows;
  task_list = (gs_htm_task **) CALLOC(nrows, sizeof(gs_htm_task *));

  if(task_list == NULL) {
    ERRPRINTF("malloc error\n");
    FREE_TABLE(table);
    return -1;
  }

  /* save number of table elements before nrows gets clobbered */
  els = (nrows+1)*ncols;

  for(; nrows > 0; nrows--) {
    i = nrows * ncols;

    task_list[nrows - 1] = (gs_htm_task *) CALLOC(1, sizeof(gs_htm_task));

    if(!task_list[nrows-1]) {
      ERRPRINTF("malloc error\n");
      FREE_TABLE(table);
      return -1;
    }

    /* skip table[i] which is component_id */
    strcpy(task_list[nrows - 1]->id, table[i+1]);
    /* skip table[i+2] which is agent_taskid */
    task_list[nrows - 1]->start = atof(table[i+3]);
    task_list[nrows - 1]->duration = atof(table[i+4]);
    task_list[nrows - 1]->remaining = atof(table[i+5]);
    task_list[nrows - 1]->end = atof(table[i+6]);
    task_list[nrows - 1]->active = atoi(table[i+7]);
    task_list[nrows - 1]->finished = atoi(table[i+8]);
    task_list[nrows - 1]->next = NULL;
  }

  FREE_TABLE(table);

  *tasks = task_list;
  return 0;
}

Here is the call graph for this function:

int sqliteIsNumber ( char *   ) 

Here is the caller graph for this function:

int task_start_compare_function ( const void *  p1,
const void *  p2 
)

Definition at line 1488 of file gs_storage_sqlite.c.

{
  gs_htm_task *s1, *s2;

  if(!p1 || !p2) return 0;

  s1 = *((gs_htm_task **) p1);
  s2 = *((gs_htm_task **) p2);

  if(s1->start > s2->start)
    return 1;
  if(s1->start < s2->start)
    return -1;

  return 0;
}


Variable Documentation

sqlite3* global_db

global pointer to the SQLite database

Definition at line 72 of file agent.c.

struct sockaddr_un GS_SQL_SOCKADDR

Definition at line 53 of file gs_storage_sqlite.c.