From 199abba0e27d40a55bf32b110c837a9747eca3ea Mon Sep 17 00:00:00 2001 From: gombasg Date: Mon, 10 Apr 2006 07:42:43 +0000 Subject: [PATCH] Make sure the work unit is marked as done when the DC_Result is destroyed Remember the database ID of WUs to prevent unneccessary database lookups Quote the client's command line arguments when creating the command line git-svn-id: svn+ssh://cvs.lpds.sztaki.hu/var/lib/svn/szdg/dcapi/trunk@429 a7169a2c-3604-0410-bc95-c702d8d87f7a --- dcapi/boinc/client.C | 3 +- dcapi/boinc/db.C | 49 ++++++++++++++++++++++++ dcapi/boinc/dc_boinc.h | 16 ++++++-- dcapi/boinc/events.C | 10 ++--- dcapi/boinc/result.c | 9 ++++- dcapi/boinc/wu.C | 84 ++++++++++++++++++++++++++++-------------- 6 files changed, 132 insertions(+), 39 deletions(-) diff --git a/dcapi/boinc/client.C b/dcapi/boinc/client.C index 0ef484ddbd..b8a8d48e18 100644 --- a/dcapi/boinc/client.C +++ b/dcapi/boinc/client.C @@ -138,8 +138,9 @@ char *DC_resolveFileName(DC_FileType type, const char *logicalFileName) } int DC_sendResult(const char *logicalFileName, const char *path, - DC_FileMode fileMode) + DC_FileMode mode) { + /* XXX */ return DC_ERR_NOTIMPL; } diff --git a/dcapi/boinc/db.C b/dcapi/boinc/db.C index 1e892e319c..ed374559b8 100644 --- a/dcapi/boinc/db.C +++ b/dcapi/boinc/db.C @@ -25,3 +25,52 @@ int _DC_initDB(void) } return 0; } + +static int lookup_db_id(DC_Workunit *wu) +{ + char *query, *name; + DB_WORKUNIT dbwu; + int ret; + + if (wu->db_id) + return 0; + + name = _DC_getWUName(wu); + query = g_strdup_printf("WHERE name = '%s'", name); + g_free(name); + ret = dbwu.lookup(query); + g_free(query); + + if (ret) + return DC_ERR_DATABASE; + wu->db_id = dbwu.get_id(); + return 0; +} + +void _DC_resultCompleted(DC_Result *result) +{ + char *query; + int ret; + + if (!result->wu->db_id) + { + ret = lookup_db_id(result->wu); + if (ret) + { + char *name = _DC_getWUName(result->wu); + + DC_log(LOG_ERR, "Failed to look up the ID of WU %s", + name); + return; + } + } + + /* We could use DB_WORKUNIT but that would require doing a SELECT + * before the UPDATE, which is unneccessary */ + query = g_strdup_printf("UPDATE workunit " + "SET assimilate_state = %d, transition_time = %d " + "WHERE id = %d", ASSIMILATE_DONE, (int)time(NULL), + result->wu->db_id); + boinc_db.do_query(query); + g_free(query); +} diff --git a/dcapi/boinc/dc_boinc.h b/dcapi/boinc/dc_boinc.h index 0ea103963d..3f65b67c0f 100644 --- a/dcapi/boinc/dc_boinc.h +++ b/dcapi/boinc/dc_boinc.h @@ -48,10 +48,14 @@ struct _DC_Workunit char *tag; int subresults; - /* State of the WU */ + /* The WU's UUID */ uuid_t uuid; + /* State of the WU */ DC_WUState state; + /* The WU's working directory */ char *workdir; + /* The WU's ID in the Boinc database */ + int db_id; /* Input file definitions. Elements are of type DC_LogicalFile */ GList *input_files; @@ -128,18 +132,24 @@ DC_PhysicalFile *_DC_createPhysicalFile(const char *label, void _DC_destroyPhysicalFile(DC_PhysicalFile *file) G_GNUC_INTERNAL; /* Creates a new DC_Result */ -DC_Result *_DC_createResult(const char *wu_name, const char *xml_doc_in) - G_GNUC_INTERNAL; +DC_Result *_DC_createResult(const char *wu_name, int db_id, + const char *xml_doc_in) G_GNUC_INTERNAL; /* Destroys a DC_Result */ void _DC_destroyResult(DC_Result *result) G_GNUC_INTERNAL; +/* Get the name of the WU used in the database */ +char *_DC_getWUName(DC_Workunit *wu) G_GNUC_INTERNAL; + /* Looks up a WU by name */ DC_Workunit *_DC_getWUByName(const char *name) G_GNUC_INTERNAL; /* Parses definitions in an XML document */ GList *_DC_parseFileRefs(const char *xml_doc, int *num_files) G_GNUC_INTERNAL; +/* Marks a work unit as completed in the database */ +void _DC_resultCompleted(DC_Result *result) G_GNUC_INTERNAL; + #ifdef __cplusplus } #endif diff --git a/dcapi/boinc/events.C b/dcapi/boinc/events.C index 97ae082ede..c68387523c 100644 --- a/dcapi/boinc/events.C +++ b/dcapi/boinc/events.C @@ -48,16 +48,11 @@ int DC_processEvents(int timeout) } /* Call the callback function */ - result = _DC_createResult(wu.name, canonical_result.xml_doc_in); + result = _DC_createResult(wu.name, wu.id, canonical_result.xml_doc_in); if (!result) continue; _dc_resultcb(result->wu, result); _DC_destroyResult(result); - - /* Mark the work unit as completed */ - wu.assimilate_state = ASSIMILATE_DONE; - wu.transition_time = time(0); - wu.update(); } g_free(query); @@ -102,12 +97,13 @@ static DC_Event *look_for_results(const char *wuFilter, const char *wuName, event = g_new(DC_Event, 1); event->type = DC_EVENT_RESULT; - event->result = _DC_createResult(wu.name, result.xml_doc_in); + event->result = _DC_createResult(wu.name, wu.id, result.xml_doc_in); if (!event->result) { g_free(event); return NULL; } + event->wu = event->result->wu; return event; } diff --git a/dcapi/boinc/result.c b/dcapi/boinc/result.c index 070c9487b6..c3cfb52dbe 100644 --- a/dcapi/boinc/result.c +++ b/dcapi/boinc/result.c @@ -12,7 +12,8 @@ * Functions */ -DC_Result *_DC_createResult(const char *wu_name, const char *xml_doc_in) +DC_Result *_DC_createResult(const char *wu_name, int db_id, + const char *xml_doc_in) { DC_Result *result; @@ -25,6 +26,9 @@ DC_Result *_DC_createResult(const char *wu_name, const char *xml_doc_in) return NULL; } + if (!result->wu->db_id) + result->wu->db_id = db_id; + result->wu->state = DC_WU_FINISHED; result->output_files = _DC_parseFileRefs(xml_doc_in, @@ -39,6 +43,9 @@ DC_Result *_DC_createResult(const char *wu_name, const char *xml_doc_in) void _DC_destroyResult(DC_Result *result) { + /* Mark the work unit as completed in the database */ + _DC_resultCompleted(result); + while (result->output_files) { _DC_destroyPhysicalFile(result->output_files->data); diff --git a/dcapi/boinc/wu.C b/dcapi/boinc/wu.C index b1bef177e8..545a62abf3 100644 --- a/dcapi/boinc/wu.C +++ b/dcapi/boinc/wu.C @@ -664,8 +664,8 @@ static int install_input_files(DC_Workunit *wu) static char *generate_wu_template(DC_Workunit *wu) { + GString *tmpl, *cmd; int i, num_inputs; - GString *tmpl; GList *l; char *p; @@ -705,11 +705,21 @@ static char *generate_wu_template(DC_Workunit *wu) g_string_append(tmpl, "\t\n"); } - /* XXX Should qoute the individual arguments */ - p = g_strjoinv(" ", wu->argv); + /* Concatenate the shell-quoted argv elements into a single string */ + cmd = g_string_new(""); + for (i = 0; i < wu->argc; i++) + { + char *quoted; + + if (i) + g_string_append_c(cmd, ' '); + quoted = g_shell_quote(wu->argv[i]); + g_string_append(cmd, quoted); + g_free(quoted); + } g_string_append_printf(tmpl, - "\t%s\n", p); - g_free(p); + "\t%s\n", cmd->str); + g_string_free(cmd, TRUE); g_string_append(tmpl, "\t1e13\n"); /* XXX Check */ @@ -828,37 +838,46 @@ static int lookup_appid(DC_Workunit *wu) return app.get_id(); } +char *_DC_getWUName(DC_Workunit *wu) +{ + char uuid_str[37]; + + uuid_unparse_lower(wu->uuid, uuid_str); + if (wu->tag) + return g_strdup_printf("%s_%s_%s", project_uuid_str, uuid_str, + wu->tag); + else + return g_strdup_printf("%s_%s", project_uuid_str, uuid_str); +} + int DC_submitWU(DC_Workunit *wu) { - char *wu_template, *result_template_file, **infiles, *result_path, - uuid_str[37]; + char *wu_template, *result_template_file, **infiles, *result_path, *name; int i, ret, ninputs; - DB_WORKUNIT bwu; + DB_WORKUNIT dbwu; GList *l; ret = install_input_files(wu); if (ret) return ret; - uuid_unparse_lower(wu->uuid, uuid_str); - if (wu->tag) - snprintf(bwu.name, sizeof(bwu.name), "%s_%s_%s", - project_uuid_str, uuid_str, wu->tag); - else - snprintf(bwu.name, sizeof(bwu.name), "%s_%s", - project_uuid_str, uuid_str); + dbwu.clear(); - bwu.appid = lookup_appid(wu); - if (bwu.appid == -1) + name = _DC_getWUName(wu); + snprintf(dbwu.name, sizeof(dbwu.name), "%s", name); + g_free(name); + + dbwu.appid = lookup_appid(wu); + if (dbwu.appid == -1) return DC_ERR_DATABASE; /* XXX Make these compatible with the template */ - bwu.batch = 1; - bwu.rsc_fpops_est = 200000 ; - bwu.rsc_fpops_bound = 2000000000 ; - bwu.rsc_memory_bound = 2000000; - bwu.rsc_disk_bound = 2000000; - bwu.delay_bound = 720000; + dbwu.batch = 1; + dbwu.rsc_fpops_est = 200000; + dbwu.rsc_fpops_bound = 2000000000; + dbwu.rsc_memory_bound = 2000000; + dbwu.rsc_disk_bound = 2000000; + dbwu.delay_bound = 720000; wu_template = generate_wu_template(wu); result_template_file = generate_result_template(wu); @@ -882,7 +901,7 @@ int DC_submitWU(DC_Workunit *wu) /* Terminator so we can use g_strfreev() later */ infiles[i] = NULL; - ret = create_work(bwu, wu_template, result_template_file, result_path, + ret = create_work(dbwu, wu_template, result_template_file, result_path, const_cast(infiles), wu->num_inputs, dc_boinc_config); g_free(result_path); @@ -1076,6 +1095,15 @@ DC_Workunit *_DC_getWUByName(const char *name) return load_from_disk(uuid); } +static void count_ready(void *key, void *value, void *ptr) +{ + DC_Workunit *wu = (DC_Workunit *)value; + int *count = (int *)ptr; + + if (wu->state == DC_WU_READY) + ++(*count); +} + int DC_getWUNumber(DC_WUState state) { DB_BASE db("", &boinc_db); @@ -1085,8 +1113,11 @@ int DC_getWUNumber(DC_WUState state) switch (state) { case DC_WU_READY: - /* XXX Should walk the wu_table */ - return -1; + val = 0; + if (wu_table) + g_hash_table_foreach(wu_table, count_ready, + &val); + return val; case DC_WU_RUNNING: query = g_strdup_printf("SELECT COUNT(*) " "FROM workunit wu, result res WHERE " @@ -1115,5 +1146,4 @@ int DC_getWUNumber(DC_WUState state) default: return -1; } - }