gs_storage_mysql.c

Go to the documentation of this file.
00001 /* 
00002  * @file
00003  *
00004  * This implements the interface defined in gs_storage.h for
00005  * the MySQL client library.
00006  */
00007 /* $Id: gs_storage_mysql.c,v 1.10 2008/12/15 21:00:59 seymour Exp $ */
00008 /* $UTK_Copyright: $ */
00009 
00010 #include <ctype.h>
00011 #include <stdlib.h>
00012 #include <stdio.h>
00013 #include <string.h>
00014 #include <time.h>
00015 #include <sys/types.h>
00016 #include <sys/socket.h>
00017 #include <sys/un.h>
00018 #include <unistd.h>
00019 
00020 #include "gs_storage.h"
00021 #include "gs_storage_sql_tables.h"
00022 #include "utility.h"
00023 #include "server.h"
00024 #include "problem.h"
00025 #include "agent.h"
00026 #include "comm_basics.h"
00027 #include "comm_encode.h"
00028 #include "mysql.h"
00029 
00030 
00031 static int
00032   gs_insert_task(char *, char *, int, double, double, double, double, int, int,
00033     char *, int);
00034 
00035 int
00036   gs_create_criteria_table(char *name, char *description, char *firstValue),
00037   gs_mysql_create_clean_db(MYSQL *, const char *, const char *, 
00038       const char *, const char *, unsigned int, const char *),
00039   gs_add_single_problem(gs_agent_t * gs_agent, gs_problem_t * gs_problem,
00040       char *cid_string);
00041 
00042 MYSQL mysql_conn;
00043 
00053 int
00054 gs_mysql_lock_tables(char *tables[], int n)
00055 {
00056   char *sql, *tmp;
00057   int i;
00058 
00059   sql = dstring_sprintf("LOCK TABLES ");
00060   if(!sql) {
00061     ERRPRINTF("failed to create string\n");
00062     return -1;
00063   }
00064 
00065   for(i=0;i<n;i++) {
00066     tmp = dstring_sprintf("%s WRITE%c", tables[i], (i==(n-1)) ? ';' : ',');
00067     if(!tmp) {
00068       ERRPRINTF("failed to create tmp string\n");
00069       free(sql);
00070       return -1;
00071     }
00072 
00073     sql = dstring_append(sql, tmp);
00074     if(!sql) {
00075       ERRPRINTF("failed to create string\n");
00076       if(tmp) free(tmp);
00077       return -1;
00078     }
00079     free(tmp);
00080   }
00081 
00082   if(mysql_query(&mysql_conn, sql)) { 
00083     ERRPRINTF("Failed to lock tables: Error: %s (%d)\n", mysql_error(&mysql_conn), 
00084        mysql_errno(&mysql_conn));
00085     ERRPRINTF("The query was: %s\n", sql);
00086     free(sql);
00087     return -1;
00088   }
00089   free(sql);
00090 
00091   return 0;
00092 }
00093 
00100 int
00101 gs_mysql_unlock_tables()
00102 {
00103   char *sql;
00104 
00105   sql = dstring_sprintf("UNLOCK TABLES;");
00106   if(!sql) {
00107     ERRPRINTF("failed to create string\n");
00108     return -1;
00109   }
00110 
00111   if(mysql_query(&mysql_conn, sql)) {
00112     ERRPRINTF("Failed to unlock tables: Error: %s (%d)\n", mysql_error(&mysql_conn),
00113        mysql_errno(&mysql_conn));
00114     free(sql);
00115     return -1;
00116   }
00117   free(sql);
00118 
00119   return 0;
00120 }
00121 
00130 int
00131 gs_mysql_init_tables(MYSQL *mysql)
00132 {
00133   char *cmds[] = {
00134     GS_SQL_SERVER_TABLE,
00135     GS_SQL_PROBLEM_TABLE,
00136     GS_SQL_PROBLEM_SERVER_MAPPING_TABLE,
00137     GS_SQL_CRITERIA_TABLE,
00138     GS_SQL_TASKS_TABLE,
00139     GS_SQL_INIT_TASKS_TABLE,
00140     GS_SQL_COMPLETED_TASKS_TABLE,
00141     GS_SQL_INIT_COMPLETED_TASKS_TABLE,
00142     GS_SQL_EXTRA_OPTIONS,
00143     NULL};
00144   int i;
00145 
00146   for(i=0; cmds[i]; i++) {
00147     if(!strcmp(cmds[i], ""))
00148       continue;
00149 
00150     if(mysql_query(mysql, cmds[i])) {
00151       ERRPRINTF("Query failed: Error: %s (%d)\n", mysql_error(mysql), mysql_errno(mysql));
00152       return -1;
00153     }
00154   }
00155 
00156   return 0;
00157 }
00158 
00167 int
00168 gs_mysql_init_db(gs_agent_t *gs_agent)
00169 {
00170   MYSQL mysql;
00171 
00172   if(mysql_init(&mysql) == NULL) {
00173     ERRPRINTF("\nFailed to initate MySQL connection");
00174     return -1;
00175   }
00176 
00177   if(gs_mysql_create_clean_db(&mysql, gs_agent->mysql.host, gs_agent->mysql.user,
00178        gs_agent->mysql.passwd, gs_agent->mysql.db_name, gs_agent->mysql.port,
00179        gs_agent->mysql.unix_socket) < 0)
00180   {
00181     ERRPRINTF("\nFailed to create db.");
00182     mysql_close(&mysql);
00183     return -1;
00184   }
00185 
00186   if(gs_mysql_init_tables(&mysql) < 0) {
00187     ERRPRINTF("\nFailed to init tables.");
00188     mysql_close(&mysql);
00189     return -1;
00190   }
00191 
00192   mysql_close(&mysql);
00193 
00194   return 0;
00195 }
00196 
00211 int
00212 gs_mysql_create_clean_db(MYSQL *mysql, const char *host, const char *user, 
00213   const char *passwd, const char *db, unsigned int port, const char *unix_socket)
00214 {
00215   char *sql;
00216 
00217   if(!mysql_real_connect(mysql, host, user, passwd, db, port, unix_socket, 0)) {
00218     if(!mysql_real_connect(mysql, host, user, passwd, 0, port, unix_socket, 0)) {
00219       ERRPRINTF("Failed to connect to MySQL: Error: %s\n", mysql_error (mysql));
00220       return -1;
00221     }
00222   }
00223   else {
00224     sql = dstring_sprintf("DROP DATABASE %s;", db);
00225 
00226     if(mysql_query(mysql, sql)) { 
00227       ERRPRINTF("Failed to drop db: Error: %s (%d)\n", mysql_error(mysql), mysql_errno(mysql));
00228       free(sql);
00229       return -1;
00230     }
00231     free(sql);
00232   }
00233 
00234   sql = dstring_sprintf("CREATE DATABASE %s;", db);
00235 
00236   if(mysql_query(mysql, sql)) {
00237     ERRPRINTF("Failed to create db: Error: %s (%d)\n", mysql_error(mysql), mysql_errno(mysql));
00238     free(sql);
00239     return -1;
00240   }
00241   free(sql);
00242 
00243   if(mysql_select_db(mysql, db)) {
00244     ERRPRINTF("Failed to select db: Error: %s (%d)\n", mysql_error(mysql), mysql_errno(mysql));
00245     return -1;
00246   }
00247 
00248   return 0;
00249 }
00250 
00255 int
00256 gs_storage_init(gs_agent_t * gs_agent)
00257 {
00258   if(mysql_init(&mysql_conn) == NULL) {
00259     ERRPRINTF("Failed to initiate MySQL connection\n");
00260     return -1;
00261   }
00262 
00263   if(!mysql_real_connect(&mysql_conn, gs_agent->mysql.host, gs_agent->mysql.user, gs_agent->mysql.passwd,
00264        gs_agent->mysql.db_name, gs_agent->mysql.port, gs_agent->mysql.unix_socket, 0)) {
00265     ERRPRINTF("Failed to connect to database: %s\n", mysql_error(&mysql_conn));
00266     return -1;
00267   }
00268 
00269   if(mysql_select_db(&mysql_conn, gs_agent->mysql.db_name)) {
00270     printf("Failed to select db: Error: %s (%d)\n", mysql_error(&mysql_conn),
00271          mysql_errno(&mysql_conn));
00272     return -1;
00273   }
00274 
00275   return 0;
00276 }
00277 
00285 void
00286 gs_storage_finalize(gs_agent_t * gs_agent)
00287 {
00288   mysql_close(&mysql_conn);
00289   return;
00290 }
00291 
00302 int
00303 gs_add_server(gs_agent_t * gs_agent, gs_server_t * gs_server)
00304 {
00305   int now, i;
00306   char *sql, cid_string[2 * CID_LEN + 1],
00307       server_dottedIP[20], proxy_dottedIP[20], *sa_str,
00308       *escaped_sa_str, *sp_str;
00309   gs_info_t *attrs;
00310 
00311   DBGPRINTF("Adding Server.\n");
00312 
00313   proxy_cid_to_str(cid_string, gs_server->componentid);
00314   proxy_ip_to_str(gs_server->ipaddress, server_dottedIP);
00315   proxy_ip_to_str(gs_server->proxyip, proxy_dottedIP);
00316   sa_str = strdup("");
00317   sp_str = strdup(GS_NO_SERVER_PING_UPDATE);
00318   gs_encode_infolist(&sa_str, gs_server->sa_list);
00319 
00320   escaped_sa_str = (char *)malloc(2 * strlen(sa_str) + 1);
00321   if(!escaped_sa_str) {
00322     ERRPRINTF("malloc failed\n");
00323     free(sa_str);
00324     return -1;
00325   }
00326 
00327   mysql_real_escape_string(&mysql_conn, escaped_sa_str, sa_str, strlen(sa_str));
00328 
00329   now = time(0);
00330   sql = dstring_sprintf("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 ('%s','%s','%d','%s','%d','%s','%s','%d','%d','%d','%d','%d','%lf','%lf','%d','%s','%d','%d','%ld','%ld','%s','%s');",
00331        gs_server->hostname, server_dottedIP, gs_server->port, proxy_dottedIP,
00332        gs_server->proxyport, cid_string, gs_server->arch,
00333        gs_server->data_format, gs_server->kflops, gs_server->workload,
00334        gs_server->ncpu, gs_server->status, gs_server->availcpu,
00335        gs_server->availmem, gs_server->nproblems, gs_server->agenthost,
00336        gs_server->agentport, gs_server->smart, now, now, escaped_sa_str, sp_str);
00337 
00338   /* free sa_str, but don't free escaped_sa_str yet, we'll reuse it below */
00339   free(sa_str);
00340   free(sp_str);
00341 
00342   if(mysql_query(&mysql_conn, sql)) {
00343     ERRPRINTF("SQL ERROR inserting server: %s\n", mysql_error(&mysql_conn));
00344     ERRPRINTF("The query was: %s\n", sql);
00345     free(escaped_sa_str);
00346     free(sql);
00347     return -1;
00348   }
00349 
00350   free(sql);
00351 
00352   SENSORPRINTF("SRV_UP %s %s\n", gs_server->hostname, cid_string);
00353   DBGPRINTF("Added Server, now adding attributes.\n");
00354 
00355   /* 
00356    * Add attributes
00357    */
00358   attrs = gs_server->sa_list;
00359   while(attrs != NULL) {
00360     i=0;
00361     while ( !isspace((int)attrs->type[i]) && attrs->type[i] != '\0') i++;
00362     attrs->type[i] = '\0';
00363     i=0;
00364     while ( !isspace((int)attrs->value[i]) && attrs->value[i] != '\0') i++;
00365     attrs->value[i] = '\0';
00366     if(gs_create_criteria_table(attrs->type, "", attrs->value) < 0) {
00367       ERRPRINTF("Error adding criteria table.\n");
00368       free(escaped_sa_str);
00369       return -1;
00370     }
00371 
00372     /* attrs->type shouldn't have any characters that need escaping, 
00373      * but attrs->value might 
00374      */
00375     mysql_real_escape_string(&mysql_conn, escaped_sa_str, attrs->value,
00376       strlen(attrs->value));
00377     
00378     sql = dstring_sprintf("INSERT INTO %s (value,componentid) values ('%s','%s');",
00379          attrs->type, escaped_sa_str, cid_string);
00380     DBGPRINTF("Submitting Attribute Query.\n");
00381 
00382     if(mysql_query(&mysql_conn, sql)) {
00383       ERRPRINTF("SQL ERROR inserting attribute: %s\n", mysql_error(&mysql_conn));
00384       ERRPRINTF("The query was: %s\n", sql);
00385       free(escaped_sa_str);
00386       free(sql);
00387       return -1;
00388     }
00389 
00390     free(sql);
00391 
00392     DBGPRINTF("Attribute added: %s.\n", attrs->type);
00393     attrs = attrs->next;
00394   }
00395 
00396   free(escaped_sa_str);
00397 
00398   return 0;
00399 }
00400 
00409 int
00410 gs_delete_problem_if_last_mapping(char *problemname)
00411 {
00412   char *sql, *tables_to_lock[] = {"problem_server", "problems"};
00413   MYSQL_RES *res;
00414 
00415   if(gs_mysql_lock_tables(tables_to_lock, 
00416        sizeof(tables_to_lock)/sizeof(*tables_to_lock)) < 0)
00417     ERRPRINTF("Warning: table lock failed\n");
00418 
00419   sql = dstring_sprintf("SELECT 1 FROM problem_server WHERE problemname='%s';",
00420                        problemname);
00421   if(mysql_query(&mysql_conn, sql)) {
00422     ERRPRINTF("SQL ERROR selecting problem-server mappings: %s\n",
00423         mysql_error(&mysql_conn));
00424     ERRPRINTF("The query was: %s\n", sql);
00425     gs_mysql_unlock_tables();
00426     free(sql);
00427     return -1;
00428   }
00429   free(sql);
00430 
00431   res=mysql_store_result(&mysql_conn);
00432 
00433   if(mysql_affected_rows(&mysql_conn) == 1) {
00434     mysql_free_result(res);
00435     sql = dstring_sprintf("DELETE FROM problems WHERE problemname='%s';",
00436                        problemname);
00437     if(mysql_query(&mysql_conn, sql)) {
00438       ERRPRINTF("SQL ERROR deleting problem: %s\n",
00439         mysql_error(&mysql_conn));
00440       ERRPRINTF("The query was: %s\n", sql);
00441       gs_mysql_unlock_tables();
00442       free(sql);
00443       return -1;
00444     }
00445     res=mysql_store_result(&mysql_conn);
00446     free(sql);
00447   }
00448 
00449   mysql_free_result(res);
00450   gs_mysql_unlock_tables();
00451 
00452   return 0;
00453 }
00454 
00462 int
00463 gs_delete_server_problems(char *cid_string)
00464 {
00465   MYSQL_RES *res;
00466   MYSQL_ROW row;
00467   char *sql;
00468   int nrows;
00469 
00470   sql = dstring_sprintf("SELECT problemname FROM problem_server WHERE componentid='%s';",
00471                        cid_string);
00472   if(mysql_query(&mysql_conn, sql)) {
00473     ERRPRINTF("SQL ERROR deleting problem-server mappings: %s\n", mysql_error(&mysql_conn));
00474     ERRPRINTF("The query was: %s\n", sql);
00475     free(sql);
00476     return -1;
00477   }
00478   free(sql);
00479 
00480   res = mysql_store_result(&mysql_conn);
00481   nrows = mysql_affected_rows(&mysql_conn);
00482 
00483   if(nrows > 0) {
00484     char **pnames;
00485     int i;
00486 
00487     pnames = (char **)malloc(nrows * sizeof(char *));
00488     
00489     for(i=0;i<nrows;i++) {
00490       row = mysql_fetch_row(res);
00491       pnames[i] = strdup(row[0]);
00492     }
00493     
00494     mysql_free_result(res);
00495 
00496     for(i=0;i<nrows;i++) {
00497       if(gs_delete_problem_if_last_mapping(pnames[i]) < 0)
00498         ERRPRINTF("Warning: could not delete unreferenced problems (if needed)\n");
00499       free(pnames[i]);
00500     }
00501 
00502     free(pnames);
00503   }
00504   else
00505     mysql_free_result(res);
00506 
00507   sql = dstring_sprintf("DELETE FROM problem_server WHERE componentid='%s';",
00508                        cid_string);
00509   if(mysql_query(&mysql_conn, sql)) {
00510     ERRPRINTF("SQL ERROR deleting problem-server mappings: %s\n", mysql_error(&mysql_conn));
00511     ERRPRINTF("The query was: %s\n", sql);
00512     free(sql);
00513     return -1;
00514   }
00515   free(sql);
00516 
00517   return 0;
00518 }
00519 
00531 int
00532 gs_delete_server(gs_agent_t * gs_agent, gs_server_t * gs_server)
00533 {
00534   char *sql, cid_string[2 * CID_LEN + 1];
00535   gs_info_t *attrs, *tmp;
00536   MYSQL_RES *res;
00537   MYSQL_ROW row;
00538 
00539   proxy_cid_to_str(cid_string, gs_server->componentid);
00540 
00541   /* 
00542    * remove server attributes from their tables.
00543    */
00544 
00545   sql = dstring_sprintf("SELECT infolist FROM servers WHERE componentid='%s';",
00546                        cid_string);
00547   if(mysql_query(&mysql_conn, sql)) {
00548     ERRPRINTF("SQL ERROR selecting infolist: %s\n", mysql_error(&mysql_conn));
00549     ERRPRINTF("The query was: %s\n", sql);
00550     free(sql);
00551     return -1;
00552   }
00553   free(sql);
00554 
00555   res = mysql_store_result(&mysql_conn);
00556 
00557   row = mysql_fetch_row(res);
00558 
00559   attrs = NULL;
00560 
00561   if(row) {
00562     if(gs_decode_infolist(row[0], &attrs) < 0) {
00563       ERRPRINTF("Warning: failed to decode infolist\n");
00564       attrs = NULL;
00565     }
00566   }
00567 
00568   mysql_free_result(res);
00569 
00570   while(attrs != NULL) {
00571     sql = dstring_sprintf("DELETE FROM %s WHERE componentid='%s';",
00572                          attrs->type, cid_string);
00573     if(mysql_query(&mysql_conn, sql)) {
00574       ERRPRINTF("SQL ERROR deleting attribute: %s\n", mysql_error(&mysql_conn));
00575       ERRPRINTF("The query was: %s\n", sql);
00576     }
00577 
00578     free(sql);
00579 
00580     tmp = attrs;
00581     attrs = attrs->next;
00582 
00583     if(tmp) {
00584       if(tmp->type) free(tmp->type);
00585       if(tmp->value) free(tmp->value);
00586       free(tmp);
00587     }
00588   }
00589 
00590   /* DELETE SERVER */
00591   sql = dstring_sprintf("DELETE FROM servers WHERE componentid='%s';",
00592                        cid_string);
00593   if(mysql_query(&mysql_conn, sql)) {
00594     ERRPRINTF("SQL ERROR removing server: %s\n", mysql_error(&mysql_conn));
00595     ERRPRINTF("The query was: %s\n", sql);
00596     free(sql);
00597     return -1;
00598   }
00599 
00600   free(sql);
00601 
00602   if(gs_delete_server_problems(cid_string) < 0) {
00603     ERRPRINTF("Failed to delete server-problem mappings\n");
00604     return -1;
00605   }
00606 
00607   SENSORPRINTF("SRV_RM %s unknown\n", cid_string);
00608 
00609   return 0;
00610 }
00611 
00629 int
00630 gs_insert_submitted_task(char *cid_string, char *taskid, int agent_taskid, 
00631   double start, double duration, double remaining, double end, int active, 
00632   int finished)
00633 {
00634   return gs_insert_task(cid_string, taskid, agent_taskid, start,
00635     duration, remaining, end, active, finished, "tasks", 1);
00636 }
00637 
00659 int
00660 gs_insert_submitted_task_guess(char *cid_string, char *taskid, int agent_taskid,
00661   double start, double duration, double remaining, double end, int active,
00662   int finished)
00663 {
00664   return gs_insert_task(cid_string, taskid, agent_taskid, start,
00665     duration, remaining, end, active, finished, "tasks", 0);
00666 }
00667 
00685 int
00686 gs_insert_completed_task(char *cid_string, char *taskid, int agent_taskid, 
00687   double start, double duration, double remaining, double end, int active, 
00688   int finished)
00689 {
00690   return gs_insert_task(cid_string, taskid, agent_taskid, start,
00691     duration, remaining, end, active, finished, "completed_tasks", 1);
00692 }
00693 
00715 static int
00716 gs_insert_task(char *cid_string, char *taskid, int agent_taskid, double start,
00717   double duration, double remaining, double end, int active, int finished,
00718   char *tname, int clobber)
00719 {
00720   char *sql = 0, *conflict_res;
00721 
00722   switch(clobber) {
00723     case 0:
00724       conflict_res = "IGNORE";
00725       break;
00726     case 1:
00727       conflict_res = "REPLACE";
00728       break;
00729     default:
00730       ERRPRINTF("Bad arg value for clobber: %d\n", clobber);
00731       return -1;
00732       break;
00733   }
00734 
00735   sql = dstring_sprintf("INSERT OR %s INTO %s VALUES ('%s','%s','%d','%lf','%lf','%lf','%lf','%d','%d');",
00736            conflict_res, tname, cid_string, taskid, agent_taskid, start, duration, remaining, end, active, finished);
00737 
00738   if(mysql_query(&mysql_conn, sql)) {
00739     ERRPRINTF("SQL ERROR inserting task: %s\n", mysql_error(&mysql_conn));
00740     ERRPRINTF("The query was: %s\n", sql);
00741     free(sql);
00742     return -1;
00743   }
00744 
00745   free(sql);
00746 
00747   return 0;
00748 }
00749 
00769 int
00770 gs_update_task(char *cid_string, char *old_taskid, char *new_taskid,
00771   int agent_taskid, double start, double duration, double remaining, 
00772   double end, int active, int finished)
00773 {
00774   char *sql;
00775 
00776   sql = dstring_sprintf("UPDATE tasks SET t_componentid='%s', t_taskid='%s', 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='%s';",
00777            cid_string, new_taskid, agent_taskid, start, duration, remaining, end, active, finished, old_taskid);
00778 
00779   if(mysql_query(&mysql_conn, sql)) {
00780     ERRPRINTF("SQL ERROR updating task: %s\n", mysql_error(&mysql_conn));
00781     ERRPRINTF("The query was: %s\n", sql);
00782     free(sql);
00783     return -1;
00784   }
00785 
00786   free(sql);
00787 
00788   return 0;
00789 }
00790 
00799 int
00800 gs_insert_problem(gs_problem_t * gs_problem)
00801 {
00802   char *sql = 0, *penc = 0, *escaped_penc;
00803 
00804   if(gs_encode_problem(&penc, gs_problem) < 0)
00805     return -1;
00806 
00807   escaped_penc = (char *) malloc(2 * strlen(penc) + 1);
00808 
00809   if(!escaped_penc) {
00810     ERRPRINTF("malloc failed\n");
00811     free(penc);
00812     return -1;
00813   }
00814 
00815   mysql_real_escape_string(&mysql_conn, escaped_penc, penc, strlen(penc));
00816 
00817   sql = dstring_sprintf("INSERT INTO problems (problemname,encoding) VALUES ('%s','%s');",
00818          gs_problem->name, escaped_penc);
00819   if(mysql_query(&mysql_conn, sql)) {
00820     gs_mysql_unlock_tables();
00821     ERRPRINTF("SQL ERROR inserting problem encoding: %s\n", mysql_error(&mysql_conn));
00822     ERRPRINTF("The query was: %s\n", sql);
00823     free(sql);
00824     free(penc);
00825     free(escaped_penc);
00826     return -1;
00827   }
00828 
00829   free(sql);
00830   free(penc);
00831   free(escaped_penc);
00832 
00833   return 0;
00834 }
00835 
00855 int
00856 gs_register_problem_changes(gs_agent_t * gs_agent, 
00857   gs_problem_t ** gs_problem, int num_services, char **models,
00858   char **rm_prob, int num_removed, char *cid_string)
00859 {
00860   char *tables_to_lock[] = {"problems", "problem_server"};
00861   int i;
00862 
00863   if(gs_mysql_lock_tables(tables_to_lock, 
00864        sizeof(tables_to_lock)/sizeof(*tables_to_lock)) < 0)
00865     ERRPRINTF("Warning: table lock failed\n");
00866 
00867   for(i=0;i<num_services;i++) {
00868     if(gs_add_single_problem(gs_agent, gs_problem[i], cid_string) < 0) {
00869       gs_mysql_unlock_tables();
00870       ERRPRINTF("Add problem failed.\n");
00871       return -1;
00872     }
00873 
00874     if(gs_update_perf_expr(cid_string, gs_problem[i]->name, models[i]) < 0)
00875       ERRPRINTF("Warning: failed to update perf model expression\n");
00876   }
00877 
00878   gs_mysql_unlock_tables();
00879 
00880   for(i=0;i<num_removed;i++) {
00881     if(gs_delete_problem(gs_agent, rm_prob[i], cid_string) < 0)
00882       ERRPRINTF("Failed to delete problem: %s\n", rm_prob[i]);
00883     else
00884       LOGPRINTF("Unregistered problem %s\n", rm_prob[i]);
00885   }
00886 
00887   return 0;
00888 }
00889 
00890 int
00891 gs_add_single_problem(gs_agent_t * gs_agent, gs_problem_t * gs_problem,
00892               char *cid_string)
00893 {
00894   char *sql = 0;
00895   int pid = 0, nrows = 0;
00896   MYSQL_RES *res;
00897   MYSQL_ROW row;
00898 
00899   DBGPRINTF("ADDING %s to %s\n", gs_problem->name, cid_string);
00900 
00901   /* 
00902    * Check if problem already exists
00903    */
00904   sql = dstring_sprintf("SELECT encoding FROM problems WHERE problemname='%s';",
00905                        gs_problem->name);
00906   if(mysql_query(&mysql_conn, sql)) {
00907     ERRPRINTF("SQL ERROR checking for problem: %s\n", mysql_error(&mysql_conn));
00908     ERRPRINTF("The query was: %s\n", sql);
00909     free(sql);
00910     return -1;
00911   }
00912   free(sql);
00913 
00914   res = mysql_store_result(&mysql_conn);
00915   nrows = mysql_affected_rows(&mysql_conn);
00916 
00917   if(nrows == 1)
00918     pid = 1;
00919 
00920   /* 
00921    * If problem is not in db, insert it
00922    */
00923   if(!pid) {
00924     mysql_free_result(res);
00925 
00926     if(gs_insert_problem(gs_problem) < 0) {
00927       ERRPRINTF("Failed to insert new problem.\n");
00928       return -1;
00929     }
00930   }
00931   else {
00932     int comparison_result;
00933     char *new_prot, *db_prot;
00934 
00935     /* 
00936      * Check encoding for differences, looking only at the actual prototype
00937      */
00938     gs_problem_t *gs_problem_in_db  = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
00939     if(!gs_problem_in_db) {
00940       ERRPRINTF("couldn't malloc space for problem to compare\n");
00941       mysql_free_result(res);
00942       return -1;
00943     }
00944 
00945     row = mysql_fetch_row(res);
00946 
00947     if(gs_decode_problem(row[0], gs_problem_in_db) < 0) {
00948       mysql_free_result(res);
00949       ERRPRINTF("decoding problem from database failed\n");
00950       return -1;
00951     }
00952 
00953     mysql_free_result(res);
00954 
00955     new_prot = gs_problem_prototype(gs_problem);
00956     db_prot = gs_problem_prototype(gs_problem_in_db);
00957 
00958     comparison_result = strcmp(new_prot, db_prot);
00959 
00960     gs_free_problem(gs_problem_in_db);
00961     free(new_prot);
00962     free(db_prot);
00963 
00964     if(comparison_result != 0) {
00965       gs_server_t **server_list = NULL;
00966       int server_match, count, i;
00967 
00968       /* this problem exists, but is different than the problem being
00969        * registered.  if this is the only server that has the problem
00970        * then allow the new version to be registered.
00971        */
00972       count = gs_get_server_list(gs_agent, gs_problem, NULL, &server_list,
00973                  &count);
00974 
00975       server_match = 0;
00976 
00977       if(server_list) {
00978         char srv_cid[CID_LEN];
00979 
00980         proxy_str_to_cid(srv_cid, cid_string);
00981 
00982         for(i = 0; i < count; i++) {
00983           if(!memcmp(srv_cid, server_list[i]->componentid, CID_LEN))
00984             server_match = 1;
00985 
00986           gs_server_free(server_list[i]);
00987         }
00988         free(server_list);
00989       }
00990 
00991       /* if only one server has the problem and it matches the
00992        * current server name, then delete the old problem and
00993        * allow registration of the new version of the problem.
00994        */
00995       if((count == 1) && server_match &&
00996           (gs_delete_problem(gs_agent, gs_problem->name, cid_string) >= 0) &&
00997           (gs_insert_problem(gs_problem) >= 0))
00998       {
00999         LOGPRINTF("Successfully replaced old version of problem %s\n",
01000            gs_problem->name);
01001       }
01002       else {
01003         ERRPRINTF("Failed to replace old version of problem '%s'.\n",
01004           gs_problem->name);
01005         gs_delete_problem(gs_agent, gs_problem->name, cid_string);
01006         return -1;
01007       }
01008     }
01009   }
01010 
01011   /* 
01012    * Associate the problem with the server.
01013    */
01014   sql = dstring_sprintf("INSERT INTO problem_server (problemname,componentid,perf_model_expr) VALUES ('%s','%s','%s');",
01015        gs_problem->name, cid_string, "-1");
01016   if(mysql_query(&mysql_conn, sql)) {
01017     ERRPRINTF("SQL ERROR inserting problem association: %s\n", 
01018         mysql_error(&mysql_conn));
01019     ERRPRINTF("The query was: %s\n", sql);
01020     free(sql);
01021     return -1;
01022   }
01023 
01024   free(sql);
01025 
01026   return 0;
01027 }
01028 
01039 int
01040 gs_delete_problem(gs_agent_t * gs_agent, char * probname,
01041                   char *cid_string)
01042 {
01043   char *sql;
01044 
01045   if(gs_delete_problem_if_last_mapping(probname) < 0)
01046     ERRPRINTF("Warning: failed to delete last problem mapping (if needed)\n");
01047 
01048   /* 
01049    * delete association
01050    */
01051   sql = dstring_sprintf("DELETE FROM problem_server WHERE componentid='%s' AND problemname='%s';",
01052        cid_string, probname);
01053   if(mysql_query(&mysql_conn, sql)) {
01054     ERRPRINTF("SQL ERROR deleting problem association: %s\n", 
01055         mysql_error(&mysql_conn));
01056     ERRPRINTF("The query was: %s\n", sql);
01057     free(sql);
01058     return -1;
01059   }
01060 
01061   free(sql);
01062 
01063   return 0;
01064 }
01065 
01078 int
01079 gs_update_perf_expr(char *srv_cid, char *probname, char *expr)
01080 {
01081   char *sql;
01082 
01083   sql = dstring_sprintf("UPDATE problem_server SET perf_model_expr='%s' WHERE componentid='%s' AND problemname='%s';",
01084        expr, srv_cid, probname);
01085   if(mysql_query(&mysql_conn, sql)) {
01086     ERRPRINTF("SQL ERROR updating performance expression: %s\n", 
01087         mysql_error(&mysql_conn));
01088     ERRPRINTF("The query was: %s\n", sql);
01089     free(sql);
01090     return -1;
01091   }
01092 
01093   free(sql);
01094 
01095   return 0;
01096 }
01097 
01105 int
01106 gs_update_ping_list(gs_agent_t * gs_agent, char *cid, char *pings)
01107 {
01108   char *sql;
01109 
01110   sql = dstring_sprintf("UPDATE servers SET server_pings='%s' WHERE componentid='%s';",
01111         pings, cid);
01112   if(mysql_query(&mysql_conn, sql)) {
01113     ERRPRINTF("SQL ERROR updating server workload: %s\n", 
01114         mysql_error(&mysql_conn));
01115     ERRPRINTF("The query was: %s\n", sql);
01116     free(sql);
01117     return -1;
01118   }
01119   free(sql);
01120 
01121   return 0;
01122 }
01123 
01131 int
01132 gs_update_workload(gs_agent_t * gs_agent, gs_server_t * gs_server)
01133 {
01134   int now;
01135   char *sql, cid_string[2 * CID_LEN + 1];
01136 
01137   proxy_cid_to_str(cid_string, gs_server->componentid);
01138 
01139   now = time(0);
01140   sql = dstring_sprintf("UPDATE servers SET workload='%d', nproblems='%d', lastupdate='%ld' WHERE componentid='%s';",
01141        gs_server->workload, gs_server->nproblems, now, cid_string);
01142   if(mysql_query(&mysql_conn, sql)) {
01143     ERRPRINTF("SQL ERROR updating server workload: %s\n", 
01144         mysql_error(&mysql_conn));
01145     ERRPRINTF("The query was: %s\n", sql);
01146     free(sql);
01147     return -1;
01148   }
01149   free(sql);
01150 
01151   SENSORPRINTF("WORK %s %d\n", cid_string, gs_server->workload);
01152 
01153   return 0;
01154 }
01155 
01163 int
01164 gs_server_exists(gs_agent_t * gs_agent, gs_server_t * gs_server)
01165 {
01166   char *sql, cid_string[2 * CID_LEN + 1];
01167   int nrows = 0;
01168   MYSQL_RES *res;
01169 
01170   proxy_cid_to_str(cid_string, gs_server->componentid);
01171 
01172   sql = dstring_sprintf("SELECT 1 FROM servers WHERE componentid='%s';",
01173                        cid_string);
01174   if(mysql_query(&mysql_conn, sql)) {
01175     ERRPRINTF("SQL ERROR checking server existence: %s\n", 
01176         mysql_error(&mysql_conn));
01177     ERRPRINTF("The query was: %s\n", sql);
01178     free(sql);
01179     return -1;
01180   }
01181 
01182   res = mysql_store_result(&mysql_conn);
01183   nrows = mysql_affected_rows(&mysql_conn);
01184 
01185   mysql_free_result(res);
01186 
01187   if(nrows > 0)
01188     return 1;
01189 
01190   return 0;
01191 }
01192 
01204 void
01205 gs_server_expiration(void **args)
01206 {
01207   gs_agent_t *agent;
01208   int timeout;
01209 
01210   agent = (gs_agent_t *) args[0];
01211   timeout = *((int *) args[1]);
01212 
01213   gs_server_expire(agent, timeout);
01214 }
01215 
01222 void
01223 gs_server_expiration_pre(void **args)
01224 {
01225   gs_agent_t *agent;
01226   int timeout;
01227 
01228   agent = (gs_agent_t *) args[0];
01229   timeout = *((int *) args[1]);
01230   if(gs_storage_init(agent) < 0 ) {
01231     ERRPRINTF("Error connecting to database manager.\n");
01232     return;
01233   }
01234   gs_server_expire(agent, timeout);
01235 }
01236 
01244 void
01245 gs_server_expiration_post(void **args)
01246 {
01247   gs_agent_t *agent;
01248   agent = (gs_agent_t *) args[0];
01249   gs_storage_finalize(agent);
01250 }
01251 
01261 int
01262 gs_server_expire(gs_agent_t * gs_agent, int timeout)
01263 {
01264   int now, nrows;
01265   char *sql;
01266   MYSQL_RES *res;
01267   MYSQL_ROW row;
01268 
01269   now = time(0);
01270   sql = dstring_sprintf("SELECT componentid FROM servers WHERE lastupdate < '%ld';",
01271                         now - timeout);
01272   if(mysql_query(&mysql_conn, sql)) {
01273     ERRPRINTF("SQL ERROR selecting servers to expire: %s\n", 
01274         mysql_error(&mysql_conn));
01275     ERRPRINTF("The query was: %s\n", sql);
01276     free(sql);
01277     return -1;
01278   }
01279 
01280   free(sql);
01281 
01282   res = mysql_store_result(&mysql_conn);
01283   nrows = mysql_affected_rows(&mysql_conn);
01284   
01285   if(nrows > 0) {
01286     gs_server_t tmpsrv;
01287 
01288     /* just in case */
01289     memset(&tmpsrv, 0, sizeof(tmpsrv));
01290 
01291     while((row = mysql_fetch_row(res))) {
01292       ERRPRINTF("expiring %s\n", row[0]);
01293 
01294       proxy_str_to_cid(tmpsrv.componentid, row[0]);
01295       if(gs_delete_server(gs_agent, &tmpsrv) < 0)
01296         ERRPRINTF("Failed to delete server '%s'\n", row[0]);
01297     }
01298   }
01299 
01300   mysql_free_result(res);
01301 
01302   return 0;
01303 }
01304 
01319 int
01320 gs_get_server_list(gs_agent_t * gs_agent, gs_problem_t * gs_problem,
01321                    char *client_criteria, gs_server_t *** servers, int *count)
01322 {
01323   int i, nrows;
01324   char *sql;
01325   gs_server_t **server_list;
01326   MYSQL_RES *res;
01327   MYSQL_ROW row;
01328 
01329   /* 
01330    * fill in remaining problem information.
01331    */
01332   sql = dstring_sprintf("SELECT encoding FROM problems WHERE problemname='%s';",
01333                        gs_problem->name);
01334   if(mysql_query(&mysql_conn, sql)) {
01335     ERRPRINTF("SQL ERROR getting problem encodings: %s\n", 
01336         mysql_error(&mysql_conn));
01337     ERRPRINTF("The query was: %s\n", sql);
01338     free(sql);
01339     return -1;
01340   }
01341 
01342   free(sql);
01343 
01344   res = mysql_store_result(&mysql_conn);
01345   nrows = mysql_affected_rows(&mysql_conn);
01346 
01347   if(nrows > 0) {
01348     row = mysql_fetch_row(res);
01349 
01350     free(gs_problem->name);
01351     gs_problem->name = NULL;
01352 
01353     if(gs_decode_problem(row[0], gs_problem) < 0) {
01354       ERRPRINTF("decoding problem failed.\n");
01355       mysql_free_result(res);
01356       return -1;
01357     }
01358   }
01359 
01360   mysql_free_result(res);
01361 
01362   if(client_criteria == NULL) {
01363     /* 
01364      * get servers associated with this problem.
01365      */
01366     sql = dstring_sprintf("SELECT servers.*,problem_server.perf_model_expr FROM problem_server JOIN servers ON problem_server.componentid = servers.componentid WHERE problemname='%s';",
01367          gs_problem->name);
01368   }
01369   else {                        /* we need to consider server attributes */
01370     char *critq, *gs_parse_client_criteria(char *, int);
01371 
01372     critq = gs_parse_client_criteria(client_criteria, GS_CRIT_PARSE_MYSQL);
01373     sql = dstring_sprintf(critq, gs_problem->name);
01374     FREE(critq);
01375   }
01376   if(mysql_query(&mysql_conn, sql)) {
01377     ERRPRINTF("SQL ERROR getting servers associated with problem '%s': %s\n", 
01378         gs_problem->name, mysql_error(&mysql_conn));
01379     ERRPRINTF("The query was: %s\n", sql);
01380     free(sql);
01381     (*servers) = NULL;
01382     return -1;
01383   }
01384 
01385   free(sql);
01386 
01387   res = mysql_store_result(&mysql_conn);
01388   nrows = mysql_affected_rows(&mysql_conn);
01389 
01390   *count = nrows;
01391   server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
01392   if(server_list == NULL) {
01393     ERRPRINTF("malloc error\n");
01394     mysql_free_result(res);
01395     return -1;
01396   }
01397 
01398   for(i=0;i<nrows;i++) {
01399     row = mysql_fetch_row(res);
01400 
01401     server_list[i] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
01402 
01403     server_list[i]->hostname = strdup(row[0]);
01404     proxy_str_to_ip(&(server_list[i]->ipaddress), row[1]);
01405     server_list[i]->port = atoi(row[2]);
01406     proxy_str_to_ip(&(server_list[i]->proxyip), row[3]);
01407     server_list[i]->proxyport = atoi(row[4]);
01408     proxy_str_to_cid(server_list[i]->componentid, row[5]);
01409     server_list[i]->arch = strdup(row[6]);
01410     server_list[i]->data_format = atoi(row[7]);
01411     server_list[i]->kflops = atoi(row[8]);
01412     server_list[i]->workload = atoi(row[9]);
01413     server_list[i]->ncpu = atoi(row[10]);
01414     server_list[i]->status = atoi(row[11]);
01415     server_list[i]->availcpu = atof(row[12]);
01416     server_list[i]->availmem = atof(row[13]);
01417     server_list[i]->nproblems = atoi(row[14]);
01418     server_list[i]->agenthost = strdup(row[15]);
01419     server_list[i]->agentport = atoi(row[16]);
01420     server_list[i]->smart = atoi(row[17]);
01421     server_list[i]->last_update = atol(row[18]);
01422 
01423     /* 
01424      * fill in server attribuites
01425      */
01426     server_list[i]->sa_list = NULL;
01427     gs_decode_infolist(row[20], &(server_list[i]->sa_list));
01428     server_list[i]->server_pings = strdup(row[21]);
01429     server_list[i]->perf_expr = strdup(row[22]);
01430   }
01431 
01432   mysql_free_result(res);
01433 
01434   *servers = server_list;
01435   return *count;
01436 }
01437  
01438 int
01439 task_start_compare_function(const void *p1, const void *p2)
01440 {
01441   gs_htm_task *s1, *s2;
01442 
01443   if(!p1 || !p2) return 0;
01444 
01445   s1 = *((gs_htm_task **) p1);
01446   s2 = *((gs_htm_task **) p2);
01447 
01448   if(s1->start > s2->start)
01449     return 1;
01450   if(s1->start < s2->start)
01451     return -1;
01452 
01453   return 0;
01454 }
01455 
01471 int
01472 gs_get_tasks_for_server(char *cid_string, gs_htm_task ***tasks, 
01473   int *count, int sync)
01474 {
01475   int i, nrows;
01476   char *sql;
01477   gs_htm_task **task_list;
01478   MYSQL_RES *res;
01479   MYSQL_ROW row;
01480 
01481   *count = -1;
01482 
01483   sql = dstring_sprintf("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='%s' or c_componentid='%s';", cid_string, cid_string);
01484   if(mysql_query(&mysql_conn, sql)) {
01485     ERRPRINTF("SQL ERROR getting tasks: %s\n", 
01486         mysql_error(&mysql_conn));
01487     ERRPRINTF("The query was: %s\n", sql);
01488     free(sql);
01489     return -1;
01490   }
01491 
01492   free(sql);
01493 
01494   res = mysql_store_result(&mysql_conn);
01495   nrows = mysql_affected_rows(&mysql_conn);
01496 
01497   *count = nrows;
01498   task_list = (gs_htm_task **) CALLOC(nrows, sizeof(gs_htm_task *));
01499 
01500   if(task_list == NULL) {
01501     ERRPRINTF("malloc error\n");
01502     mysql_free_result(res);
01503     return -1;
01504   }
01505 
01506   for(i=0;i<nrows;i++) {
01507     row = mysql_fetch_row(res);
01508 
01509     task_list[i] = (gs_htm_task *) CALLOC(1, sizeof(gs_htm_task));
01510 
01511     if(!task_list[i]) {
01512       ERRPRINTF("malloc error\n");
01513       mysql_free_result(res);
01514       return -1;
01515     }
01516 
01517     if(row[1] && row[10] && strcmp(row[1], "-1") && strcmp(row[10], "-1")) {
01518       /* entry exists in both tasks and completed_tasks */
01519 
01520       strcpy(task_list[i]->id, row[1]);
01521       /* skip row[2] which is agent_taskid */
01522       if(sync) {
01523         task_list[i]->start = MIN(atof(row[3]), atof(row[12]));
01524         task_list[i]->end = MAX(atof(row[6]), atof(row[15]));
01525         task_list[i]->duration = task_list[i]->end - task_list[i]->start;
01526       }
01527       else {
01528         task_list[i]->start = atof(row[3]);
01529         task_list[i]->end = atof(row[6]);
01530         task_list[i]->duration = atof(row[4]);
01531       }
01532       task_list[i]->remaining = atof(row[14]);
01533       task_list[i]->active = atoi(row[7]);
01534       task_list[i]->finished = atoi(row[17]);
01535       task_list[i]->next = NULL;
01536     }
01537     else if(row[1] && strcmp(row[1], "-1")) {
01538       /* entry exists in only in tasks */
01539 
01540       strcpy(task_list[i]->id, row[1]);
01541       /* skip row[2] which is agent_taskid */
01542       task_list[i]->start = atof(row[3]);
01543       task_list[i]->duration = atof(row[4]);
01544       task_list[i]->remaining = atof(row[5]);
01545       task_list[i]->end = atof(row[6]);
01546       task_list[i]->active = atoi(row[7]);
01547       task_list[i]->finished = atoi(row[8]);
01548       task_list[i]->next = NULL;
01549     }
01550     else if(row[10] && strcmp(row[10], "-1")) {
01551       /* entry exists in only in completed_tasks */
01552 
01553       strcpy(task_list[i]->id, row[10]);
01554       /* skip row[11] which is agent_taskid */
01555       task_list[i]->start = atof(row[12]);
01556       task_list[i]->duration = atof(row[13]);
01557       task_list[i]->remaining = atof(row[14]);
01558       task_list[i]->end = atof(row[15]);
01559       task_list[i]->active = atoi(row[16]);
01560       task_list[i]->finished = atoi(row[17]);
01561       task_list[i]->next = NULL;
01562     }
01563     else {
01564       /* should not hit this case */
01565       ERRPRINTF("Unexpected result from query.\n");
01566       mysql_free_result(res);
01567       return -1;
01568     }
01569 
01570     /* make sure duration isn't some weird value */
01571     if(task_list[i]->duration <= 0.0)
01572       task_list[i]->duration = 0.001;
01573   }
01574 
01575   qsort(task_list, nrows, sizeof(gs_htm_task *), task_start_compare_function);
01576 
01577   mysql_free_result(res);
01578   *tasks = task_list;
01579   return 0;
01580 }
01581 
01593 int 
01594 gs_get_server_ping_list(gs_agent_t * gs_agent, gs_server_t *** servers, char *cid, int *count)
01595 {
01596   int i, nrows;
01597   char *sql;
01598   gs_server_t **server_list;
01599   MYSQL_RES *res;
01600   MYSQL_ROW row;
01601 
01602   sql = dstring_sprintf("SELECT * FROM servers WHERE componentid<'%s' AND smart='1';", cid);
01603   if(mysql_query(&mysql_conn, sql)) {
01604     ERRPRINTF("SQL ERROR getting servers ping list: %s\n",
01605         mysql_error(&mysql_conn));
01606     ERRPRINTF("The query was: %s\n", sql);
01607     free(sql);
01608     return -1;
01609   }
01610 
01611   free(sql);
01612 
01613   res = mysql_store_result(&mysql_conn);
01614   nrows = mysql_affected_rows(&mysql_conn);
01615 
01616   *count = nrows;
01617   server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
01618 
01619   if(server_list == NULL) {
01620     ERRPRINTF("malloc error\n");
01621     mysql_free_result(res);
01622     return -1;
01623   }
01624 
01625   for(i=0; i<nrows; i++) {
01626     row = mysql_fetch_row(res);
01627 
01628     server_list[i] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
01629     if(!server_list[i]) {
01630       ERRPRINTF("malloc error\n");
01631       mysql_free_result(res);
01632       return -1;
01633     }
01634 
01635     server_list[i]->hostname = strdup(row[0]);
01636     proxy_str_to_ip(&(server_list[i]->ipaddress), row[1]);
01637     server_list[i]->port = atoi(row[2]);
01638     proxy_str_to_ip(&(server_list[i]->proxyip), row[3]);
01639     server_list[i]->proxyport = atoi(row[4]);
01640     proxy_str_to_cid(server_list[i]->componentid, row[5]);
01641     server_list[i]->arch = strdup(row[6]);
01642     server_list[i]->data_format = atoi(row[7]);
01643     server_list[i]->kflops = atoi(row[8]);
01644     server_list[i]->workload = atoi(row[9]);
01645     server_list[i]->ncpu = atoi(row[10]);
01646     server_list[i]->status = atoi(row[11]);
01647     server_list[i]->availcpu = atof(row[12]);
01648     server_list[i]->availmem = atof(row[13]);
01649     server_list[i]->nproblems = atoi(row[14]);
01650     server_list[i]->agenthost = strdup(row[15]);
01651     server_list[i]->agentport = atoi(row[16]);
01652     server_list[i]->smart = atoi(row[17]);
01653     server_list[i]->last_update = atol(row[18]);
01654   }
01655 
01656   mysql_free_result(res);
01657   *servers = server_list;
01658 
01659   return *count;
01660 }
01661 
01669 int
01670 gs_get_all_smart_servers(gs_agent_t * gs_agent, gs_server_t *** servers, int *count)
01671 {
01672   int i, nrows;
01673   char *sql;
01674   gs_server_t **server_list;
01675   MYSQL_RES *res;
01676   MYSQL_ROW row;
01677 
01678   sql = dstring_sprintf("SELECT * FROM servers WHERE smart='1';");
01679   if(mysql_query(&mysql_conn, sql)) {
01680     ERRPRINTF("SQL ERROR getting all smart servers: %s\n",
01681         mysql_error(&mysql_conn));
01682     ERRPRINTF("The query was: %s\n", sql);
01683     free(sql);
01684     return -1;
01685   } 
01686 
01687   free(sql);
01688 
01689   res = mysql_store_result(&mysql_conn);
01690   nrows = mysql_affected_rows(&mysql_conn);
01691 
01692   *count = nrows;
01693   server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
01694 
01695   if(server_list == NULL) {
01696     ERRPRINTF("malloc error\n");
01697     mysql_free_result(res);
01698     return -1;
01699   }
01700 
01701   for(i=0; i<nrows; i++) {
01702     row = mysql_fetch_row(res);
01703 
01704     server_list[i] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
01705     if(!server_list[i]) {
01706       ERRPRINTF("malloc error\n");
01707       mysql_free_result(res);
01708       return -1;
01709     }
01710 
01711     server_list[i]->hostname = strdup(row[0]);
01712     proxy_str_to_ip(&(server_list[i]->ipaddress), row[1]);
01713     server_list[i]->port = atoi(row[2]);
01714     proxy_str_to_ip(&(server_list[i]->proxyip), row[3]);
01715     server_list[i]->proxyport = atoi(row[4]);
01716     proxy_str_to_cid(server_list[i]->componentid, row[5]);
01717     server_list[i]->arch = strdup(row[6]);
01718     server_list[i]->data_format = atoi(row[7]);
01719     server_list[i]->kflops = atoi(row[8]);
01720     server_list[i]->workload = atoi(row[9]);
01721     server_list[i]->ncpu = atoi(row[10]);
01722     server_list[i]->status = atoi(row[11]);
01723     server_list[i]->availcpu = atof(row[12]);
01724     server_list[i]->availmem = atof(row[13]);
01725     server_list[i]->nproblems = atoi(row[14]);
01726     server_list[i]->agenthost = strdup(row[15]);
01727     server_list[i]->agentport = atoi(row[16]);
01728     server_list[i]->smart = atoi(row[17]);
01729     server_list[i]->last_update = atol(row[18]);
01730     /* skip 19 - addedat */
01731     /* skip 20 - infolist */
01732     server_list[i]->server_pings = strdup(row[21]);
01733   }
01734 
01735   mysql_free_result(res);
01736   *servers = server_list;
01737 
01738   return *count;
01739 }
01740 
01748 int
01749 gs_get_all_servers(gs_agent_t * gs_agent, gs_server_t *** servers, int *count)
01750 {
01751   int i, nrows;
01752   char *sql;
01753   gs_server_t **server_list;
01754   MYSQL_RES *res;
01755   MYSQL_ROW row;
01756 
01757   sql = dstring_sprintf("SELECT * FROM servers WHERE 1;");
01758   if(mysql_query(&mysql_conn, sql)) {
01759     ERRPRINTF("SQL ERROR getting all known servers: %s\n", 
01760         mysql_error(&mysql_conn));
01761     ERRPRINTF("The query was: %s\n", sql);
01762     free(sql);
01763     return -1;
01764   }
01765 
01766   free(sql);
01767 
01768   res = mysql_store_result(&mysql_conn);
01769   nrows = mysql_affected_rows(&mysql_conn);
01770 
01771   *count = nrows;
01772   server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
01773 
01774   if(server_list == NULL) {
01775     ERRPRINTF("malloc error\n");
01776     mysql_free_result(res);
01777     return -1;
01778   }
01779 
01780   for(i=0; i<nrows; i++) {
01781     row = mysql_fetch_row(res);
01782 
01783     server_list[i] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
01784     if(!server_list[i]) {
01785       ERRPRINTF("malloc error\n");
01786       mysql_free_result(res);
01787       return -1;
01788     }
01789 
01790     server_list[i]->hostname = strdup(row[0]);
01791     proxy_str_to_ip(&(server_list[i]->ipaddress), row[1]);
01792     server_list[i]->port = atoi(row[2]);
01793     proxy_str_to_ip(&(server_list[i]->proxyip), row[3]);
01794     server_list[i]->proxyport = atoi(row[4]);
01795     proxy_str_to_cid(server_list[i]->componentid, row[5]);
01796     server_list[i]->arch = strdup(row[6]);
01797     server_list[i]->data_format = atoi(row[7]);
01798     server_list[i]->kflops = atoi(row[8]);
01799     server_list[i]->workload = atoi(row[9]);
01800     server_list[i]->ncpu = atoi(row[10]);
01801     server_list[i]->status = atoi(row[11]);
01802     server_list[i]->availcpu = atof(row[12]);
01803     server_list[i]->availmem = atof(row[13]);
01804     server_list[i]->nproblems = atoi(row[14]);
01805     server_list[i]->agenthost = strdup(row[15]);
01806     server_list[i]->agentport = atoi(row[16]);
01807     server_list[i]->smart = atoi(row[17]);
01808     server_list[i]->last_update = atol(row[18]);
01809   }
01810 
01811   mysql_free_result(res);
01812   *servers = server_list;
01813   return *count;
01814 }
01815 
01825 int
01826 gs_get_problem_list(gs_agent_t * gs_agent, gs_server_t * gs_server,
01827                     gs_problem_t *** problems, int *count)
01828 {
01829   int i, nrows;
01830   char *sql, cid_string[2 * CID_LEN + 1];
01831   gs_problem_t **problem_list;
01832   MYSQL_RES *res;
01833   MYSQL_ROW row;
01834 
01835   proxy_cid_to_str(cid_string, gs_server->componentid);
01836   sql = dstring_sprintf("SELECT problems.encoding FROM problem_server JOIN problems ON problem_server.problemname = problems.problemname WHERE componentid='%s';",
01837        cid_string);
01838   if(mysql_query(&mysql_conn, sql)) {
01839     ERRPRINTF("SQL ERROR getting all problems: %s\n", mysql_error(&mysql_conn));
01840     ERRPRINTF("The query was: %s\n", sql);
01841     free(sql);
01842     return -1;
01843   }
01844   free(sql);
01845 
01846   res = mysql_store_result(&mysql_conn);
01847   nrows = mysql_affected_rows(&mysql_conn);
01848 
01849   *count = nrows;
01850 
01851   problem_list = (gs_problem_t **) CALLOC(nrows, sizeof(gs_problem_t *));
01852   if(problem_list == NULL) {
01853     ERRPRINTF("malloc error in gs_get_problem_list\n");
01854     mysql_free_result(res);
01855     return -1;
01856   }
01857 
01858   for(i=0; i < nrows; i++) {
01859     row = mysql_fetch_row(res);
01860 
01861     problem_list[i] = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
01862     gs_decode_problem(row[0], problem_list[i]);
01863   }
01864 
01865   mysql_free_result(res);
01866 
01867   *problems = problem_list;
01868 
01869   return *count;
01870 }
01871 
01880 int
01881 gs_get_all_problems(gs_agent_t * gs_agent, gs_problem_t *** problems, int *count)
01882 {
01883   return gs_get_problem_info(gs_agent, problems, count, NULL);
01884 }
01885 
01896 int
01897 gs_get_problem_info(gs_agent_t * gs_agent, gs_problem_t *** problems, int *count,
01898   char *name)
01899 {
01900   int i, nrows;
01901   char *sql;
01902   gs_problem_t **problem_list;
01903   MYSQL_RES *res;
01904   MYSQL_ROW row;
01905 
01906   if(name)
01907     sql = dstring_sprintf("SELECT encoding FROM problems WHERE problemname='%s';", name);
01908   else
01909     sql = dstring_sprintf("SELECT encoding FROM problems WHERE 1;");
01910 
01911   if(mysql_query(&mysql_conn, sql)) {
01912     ERRPRINTF("SQL ERROR getting list of problems: %s\n", 
01913         mysql_error(&mysql_conn));
01914     ERRPRINTF("The query was: %s\n", sql);
01915     free(sql);
01916     return -1;
01917   }
01918 
01919   free(sql);
01920 
01921   res = mysql_store_result(&mysql_conn);
01922   nrows = mysql_affected_rows(&mysql_conn);
01923 
01924   *count = nrows;
01925   problem_list = (gs_problem_t **) CALLOC(nrows, sizeof(gs_problem_t *));
01926   if(problem_list == NULL) {
01927     ERRPRINTF("malloc error in gs_get_problem_list\n");
01928     mysql_free_result(res);
01929     return -1;
01930   }
01931 
01932   for(i=0; i < nrows; i++) {
01933     row = mysql_fetch_row(res);
01934 
01935     problem_list[i] = (gs_problem_t *) CALLOC(1, sizeof(gs_problem_t));
01936     gs_decode_problem(row[0], problem_list[i]);
01937   }
01938 
01939   mysql_free_result(res);
01940   *problems = problem_list;
01941 
01942   return *count;
01943 }
01944 
01955 int
01956 gs_create_criteria_table(char *name, char *description, char *firstValue)
01957 {
01958   char *sql, *tables_to_lock[] = {"criteria", "problems"};
01959   int nrows;
01960   MYSQL_RES *res;
01961 
01962   if(gs_mysql_lock_tables(tables_to_lock, 
01963        sizeof(tables_to_lock)/sizeof(*tables_to_lock)) < 0)
01964     ERRPRINTF("Warning: table lock failed\n");
01965 
01966   /* 
01967    * Check if criteria is already in db
01968    */
01969   sql = dstring_sprintf("SELECT 1 FROM criteria WHERE critname = '%s';", name);
01970   if(mysql_query(&mysql_conn, sql)) {
01971     gs_mysql_unlock_tables();
01972     ERRPRINTF("SQL ERROR getting criteria: %s\n", mysql_error(&mysql_conn));
01973     ERRPRINTF("The query was: %s\n", sql);
01974     free(sql);
01975     return -1;
01976   }
01977   free(sql);
01978 
01979   res = mysql_store_result(&mysql_conn);
01980   nrows = mysql_affected_rows(&mysql_conn);
01981 
01982   mysql_free_result(res);
01983 
01984   if(nrows > 0) {
01985     gs_mysql_unlock_tables();
01986     return 0;
01987   }
01988 
01989   sql = dstring_sprintf("CREATE TABLE %s (value VARCHAR(128) NOT NULL, componentid VARCHAR(128) NOT NULL, UNIQUE(componentid));",
01990        name);
01991   if(mysql_query(&mysql_conn, sql)) {
01992     gs_mysql_unlock_tables();
01993     ERRPRINTF("SQL ERROR creating criteria table: %s\n", mysql_error(&mysql_conn));
01994     ERRPRINTF("The query was: %s\n", sql);
01995     free(sql);
01996     return -1;
01997   }
01998   free(sql);
01999 
02000   sql = dstring_sprintf("INSERT INTO criteria (critname,description) VALUES ('%s','%s');", 
02001      name, description);
02002   if(mysql_query(&mysql_conn, sql)) {
02003     gs_mysql_unlock_tables();
02004     ERRPRINTF("SQL ERROR inserting criteria: %s\n", mysql_error(&mysql_conn));
02005     ERRPRINTF("The query was: %s\n", sql);
02006     free(sql);
02007     return -1;
02008   }
02009 
02010   gs_mysql_unlock_tables();
02011   free(sql);
02012 
02013   return 0;
02014 }
02015 
02026 int 
02027 gs_get_server(gs_agent_t *gs_agent, char *name, gs_server_t *server) 
02028 {
02029   char *sql;
02030   int nrows;
02031   MYSQL_RES *res;
02032   MYSQL_ROW row;
02033 
02034   sql = dstring_sprintf("SELECT * FROM servers WHERE hostname='%s' LIMIT 1;",
02035       name);
02036   if(mysql_query(&mysql_conn, sql)) {
02037     ERRPRINTF("SQL ERROR getting server info: %s\n", mysql_error(&mysql_conn));
02038     ERRPRINTF("The query was: %s\n", sql);
02039     free(sql);
02040     return -1;
02041   }
02042   free(sql);
02043 
02044   res = mysql_store_result(&mysql_conn);
02045   nrows = mysql_affected_rows(&mysql_conn);
02046 
02047   if(nrows == 0) {
02048     mysql_free_result(res);
02049     return -1;
02050   }
02051 
02052   row = mysql_fetch_row(res);
02053 
02054   /* fill in structure */
02055   server->hostname = strdup(row[0]);
02056   proxy_str_to_ip(&(server->ipaddress), row[1]);
02057   server->port = atoi(row[2]);
02058   proxy_str_to_ip(&(server->proxyip), row[3]);
02059   server->proxyport = atoi(row[4]);
02060   proxy_str_to_cid(server->componentid, row[5]);
02061   server->arch = strdup(row[6]);
02062   server->data_format = atoi(row[7]);
02063   server->kflops = atoi(row[8]);
02064   server->workload = atoi(row[9]);
02065   server->ncpu = atoi(row[10]);
02066   server->status = atoi(row[11]);
02067   server->availcpu = atof(row[12]);
02068   server->availmem = atof(row[13]);
02069   server->nproblems = atoi(row[14]);
02070   server->agenthost = strdup(row[15]);
02071   server->agentport = atoi(row[16]);
02072   server->smart = atol(row[17]);
02073   server->last_update = atol(row[18]);
02074 
02075   /* 
02076    * fill in server attribuites
02077    */
02078   server->sa_list = NULL;
02079   gs_decode_infolist(row[20], &(server->sa_list));
02080 
02081   mysql_free_result(res);
02082 
02083   return 0;
02084 }
02085 
02098 int
02099 gs_get_all_servers_by_hostname(gs_agent_t * gs_agent, char *hostname,
02100   gs_server_t *** servers, int *count)
02101 {
02102   int i, nrows;
02103   char *sql;
02104   gs_server_t **server_list;
02105   MYSQL_RES *res;
02106   MYSQL_ROW row;
02107 
02108   *count = -1;
02109 
02110   sql = dstring_sprintf("SELECT * FROM servers WHERE hostname='%s';", 
02111     hostname);
02112   if(mysql_query(&mysql_conn, sql)) {
02113     ERRPRINTF("SQL ERROR getting all servers by name: %s\n", 
02114       mysql_error(&mysql_conn));
02115     ERRPRINTF("The query was: %s\n", sql);
02116     free(sql);
02117     return -1;
02118   }
02119   free(sql);
02120 
02121   res = mysql_store_result(&mysql_conn);
02122   nrows = mysql_affected_rows(&mysql_conn);
02123 
02124   *count = nrows;
02125   server_list = (gs_server_t **) CALLOC(nrows, sizeof(gs_server_t *));
02126 
02127   if(server_list == NULL) {
02128     ERRPRINTF("malloc error\n");
02129     mysql_free_result(res);
02130     return -1;
02131   }
02132 
02133   for(i=0;i<nrows;i++) {
02134     row = mysql_fetch_row(res);
02135 
02136     server_list[i] = (gs_server_t *) CALLOC(1, sizeof(gs_server_t));
02137     if(!server_list[i]) {
02138       ERRPRINTF("malloc error\n");
02139       mysql_free_result(res);
02140       return -1;
02141     }
02142 
02143     server_list[i]->hostname = strdup(row[0]);
02144     proxy_str_to_ip(&(server_list[i]->ipaddress), row[1]);
02145     server_list[i]->port = atoi(row[2]);
02146     proxy_str_to_ip(&(server_list[i]->proxyip), row[3]);
02147     server_list[i]->proxyport = atoi(row[4]);
02148     proxy_str_to_cid(server_list[i]->componentid, row[5]);
02149     server_list[i]->arch = strdup(row[6]);
02150     server_list[i]->data_format = atoi(row[7]);
02151     server_list[i]->kflops = atoi(row[8]);
02152     server_list[i]->workload = atoi(row[9]);
02153     server_list[i]->ncpu = atoi(row[10]);
02154     server_list[i]->status = atoi(row[11]);
02155     server_list[i]->availcpu = atof(row[12]);
02156     server_list[i]->availmem = atof(row[13]);
02157     server_list[i]->nproblems = atoi(row[14]);
02158     server_list[i]->agenthost = strdup(row[15]);
02159     server_list[i]->agentport = atoi(row[16]);
02160     server_list[i]->last_update = atol(row[17]);
02161   }
02162 
02163   mysql_free_result(res);
02164   *servers = server_list;
02165   return *count;
02166 }
02167 
02177 int
02178 gs_get_task_by_agent_taskid(int agent_taskid, gs_htm_task *task)
02179 {
02180   char *sql;
02181   int nrows;
02182   MYSQL_RES *res;
02183   MYSQL_ROW row;
02184 
02185   sql = dstring_sprintf("SELECT * FROM tasks WHERE t_agent_taskid='%d' LIMIT 1;", 
02186     agent_taskid);
02187   if(mysql_query(&mysql_conn, sql)) {
02188     ERRPRINTF("SQL ERROR getting task by taskid: %s\n", 
02189       mysql_error(&mysql_conn));
02190     ERRPRINTF("The query was: %s\n", sql);
02191     free(sql);
02192     return -1;
02193   }
02194   free(sql);
02195 
02196   res = mysql_store_result(&mysql_conn);
02197   nrows = mysql_affected_rows(&mysql_conn);
02198 
02199   if(nrows == 0) {
02200     mysql_free_result(res);
02201     return -1;
02202   }
02203 
02204   row = mysql_fetch_row(res);
02205 
02206   /* skip row[0] -- component id */
02207   strcpy(task->id, row[1]);
02208   task->agent_taskid = atof(row[2]);
02209   task->start = atof(row[3]);
02210   task->duration = atof(row[4]);
02211   task->remaining = atof(row[5]);
02212   task->end = atof(row[6]);
02213   task->active = atoi(row[7]);
02214   task->finished = atoi(row[8]);
02215   task->next = NULL;
02216 
02217   mysql_free_result(res);
02218 
02219   return 0;
02220 }
02221 
02232 int 
02233 gs_get_server_by_cid(gs_agent_t * gs_agent, char *cid, gs_server_t *server) 
02234 {
02235   char *sql;
02236   int nrows;
02237   MYSQL_RES *res;
02238   MYSQL_ROW row;
02239 
02240   sql = dstring_sprintf("SELECT * FROM servers WHERE componentid='%s' LIMIT 1;",
02241       cid);
02242   if(mysql_query(&mysql_conn, sql)) {
02243     ERRPRINTF("SQL ERROR getting server by component id: %s\n", 
02244        mysql_error(&mysql_conn));
02245     ERRPRINTF("The query was: %s\n", sql);
02246     free(sql);
02247     return -1;
02248   }
02249   free(sql);
02250 
02251   res = mysql_store_result(&mysql_conn);
02252   nrows = mysql_affected_rows(&mysql_conn);
02253 
02254   if(nrows == 0) {
02255     mysql_free_result(res);
02256     return -1;
02257   }
02258 
02259   row = mysql_fetch_row(res);
02260 
02261   /* fill in structure */
02262 
02263   server->hostname = strdup(row[0]);
02264   proxy_str_to_ip(&(server->ipaddress), row[1]);
02265   server->port = atoi(row[2]);
02266   proxy_str_to_ip(&(server->proxyip), row[3]);
02267   server->proxyport = atoi(row[4]);
02268   proxy_str_to_cid(server->componentid, row[5]);
02269   server->arch = strdup(row[6]);
02270   server->data_format = atoi(row[7]);
02271   server->kflops = atoi(row[8]);
02272   server->workload = atoi(row[9]);
02273   server->ncpu = atoi(row[10]);
02274   server->status = atoi(row[11]);
02275   server->availcpu = atof(row[12]);
02276   server->availmem = atof(row[13]);
02277   server->nproblems = atoi(row[14]);
02278   server->agenthost = strdup(row[15]);
02279   server->agentport = atoi(row[16]);
02280   server->smart = atol(row[17]);
02281   server->last_update = atol(row[18]);
02282 
02283   /* 
02284    * fill in server attribuites
02285    */
02286   server->sa_list = NULL;
02287   gs_decode_infolist(row[20], &(server->sa_list));
02288 
02289   mysql_free_result(res);
02290 
02291   return 0;
02292 }