From fccf8d83ab373a89b82e9f054012516bb787c574 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 1 Jul 2004 20:24:00 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=3736 --- db/boinc_db.C | 159 ++++++++++++++++++++------------------------------ db/boinc_db.h | 29 ++++----- db/db_base.C | 61 +------------------ db/db_base.h | 25 ++++---- 4 files changed, 91 insertions(+), 183 deletions(-) diff --git a/db/boinc_db.C b/db/boinc_db.C index 8f7193bf51..9879bcb7d1 100644 --- a/db/boinc_db.C +++ b/db/boinc_db.C @@ -59,7 +59,7 @@ DB_HOST::DB_HOST() : DB_BASE(boinc_db, "host"){} DB_WORKUNIT::DB_WORKUNIT() : DB_BASE(boinc_db, "workunit"){} DB_RESULT::DB_RESULT() : DB_BASE(boinc_db, "result"){} DB_MSG_FROM_HOST::DB_MSG_FROM_HOST() : DB_BASE(boinc_db, "msg_from_host"){} -DB_TRANSITIONER_QUEUE::DB_TRANSITIONER_QUEUE() : DB_BASE(boinc_db), current_entry_start_position(0), current_entry_workunit_id(0){} +DB_TRANSITIONER_ITEM_SET::DB_TRANSITIONER_ITEM_SET() : DB_BASE_SPECIAL(boinc_db){} int DB_PLATFORM::get_id() {return id;} int DB_CORE_VERSION::get_id() {return id;} @@ -571,23 +571,29 @@ void DB_MSG_TO_HOST::db_parse(MYSQL_ROW& r) { strcpy2(xml, r[i++]); } -int DB_TRANSITIONER_QUEUE::enumerate_queue_entries(int transition_time, int ntotal_transitioners, int ntransitioner, int nresult_limit) { +int DB_TRANSITIONER_ITEM_SET::enumerate( + int transition_time, int ntotal_transitioners, int ntransitioner, + int nresult_limit, + std::vector& items +) { int x; char query[MAX_QUERY_LEN]; - char priority[16]; - char mod[64]; + char priority[256]; + char mod[256]; MYSQL_ROW row; - int temp_workunit_id; - MYSQL_ROW_OFFSET temp_entry_position; + TRANSITIONER_ITEM new_item; if (!cursor.active) { - cursor.active = true; - memset(priority, '\0', sizeof(priority)); - if (db->mysql) { strcpy(priority, "HIGH_PRIORITY"); } + strcpy(priority, ""); + if (db->mysql) strcpy(priority, "HIGH_PRIORITY"); - memset(mod, '\0', sizeof(mod)); - if (0 < ntotal_transitioners) { sprintf(mod, "MOD(wu.id, %d) = %d", ntotal_transitioners, ntransitioner); } + strcpy(mod, ""); + if (ntotal_transitioners > 1) { + sprintf(mod, "MOD(wu.id, %d) = %d", + ntotal_transitioners, ntransitioner + ); + } sprintf(query, "SELECT %s " @@ -625,104 +631,63 @@ int DB_TRANSITIONER_QUEUE::enumerate_queue_entries(int transition_time, int ntot x = db->do_query(query); if (x) return mysql_errno(db->mysql); + + // the following stores the entire result set in memory cursor.rp = mysql_store_result(db->mysql); if (!cursor.rp) return mysql_errno(db->mysql); + cursor.active = true; + //nrows = mysql_num_rows(cursor.rp); + //current_row = 0; - current_entry_start_position = mysql_row_tell(cursor.rp); - } - - mysql_row_seek(current_entry_start_position); - - do - { - temp_entry_position = mysql_row_tell(cursor.rp); row = mysql_fetch_row(cursor.rp); if (!row) { - mysql_free_result(cursor.rp); cursor.active = false; return -1; - } else { - fetch_field_value(cursor.rp, row, "id", temp_workunit_id); } + last_item.parse(row); } - while ( row && ( temp_workunit_id == current_entry_workunit_id )); - // New Workunit Detected - current_entry_workunit_id = temp_workunit_id; - current_entry_start_position = temp_entry_position; + items.clear(); + while (true) { + items.push_back(last_item); + row = mysql_fetch_row(cursor.rp); + if (!row) { + cursor.active = false; + return -1; + } + new_item.parse(row); + if (new_item.id != last_item.id) { + last_item = new_item; + return 0; + } + last_item = new_item; + } - parse_entry(cursor.rp, row); - return 0; } -void DB_TRANSITIONER_QUEUE::parse_entry(MYSQL_RES *result, MYSQL_ROW& row) { - int temp_need_validate = 0; - fetch_field_value(result, row, "id", id); - fetch_field_value(result, row, "name", name, sizeof(name)); - fetch_field_value(result, row, "appid", appid); - fetch_field_value(result, row, "min_quorum", min_quorum); - fetch_field_value(result, row, "need_validate", temp_need_validate); - if (temp_need_validate) { need_validate = true; } else { need_validate = false; } - fetch_field_value(result, row, "canonical_resultid", canonical_resultid); - fetch_field_value(result, row, "transition_time", transition_time); - fetch_field_value(result, row, "delay_bound", delay_bound); - fetch_field_value(result, row, "error_mask", error_mask); - fetch_field_value(result, row, "max_error_results", max_error_results); - fetch_field_value(result, row, "max_total_results", max_total_results); - fetch_field_value(result, row, "file_delete_state", file_delete_state); - fetch_field_value(result, row, "assimilate_state", assimilate_state); - fetch_field_value(result, row, "target_nresults", target_nresults); - fetch_field_value(result, row, "result_template_file", result_template_file, sizeof(result_template_file)); - parse_result(result, row); +void TRANSITIONER_ITEM::parse(MYSQL_ROW& r) { + int i=0; + memset(this, 0, sizeof(TRANSITIONER_ITEM)); + id = atoi(r[i++]); + strcpy2(name, r[i++]); + appid = atoi(r[i++]); + min_quorum = atoi(r[i++]); + canonical_resultid = atoi(r[i++]); + transition_time = atoi(r[i++]); + delay_bound = atoi(r[i++]); + error_mask = atoi(r[i++]); + max_error_results = atoi(r[i++]); + max_total_results = atoi(r[i++]); + file_delete_state = atoi(r[i++]); + assimilate_state = atoi(r[i++]); + target_nresults = atoi(r[i++]); + strcpy2(result_template_file, r[i++]); + res_id = atoi(r[i++]); + res_report_deadline = atoi(r[i++]); + res_server_state = atoi(r[i++]); + res_outcome = atoi(r[i++]); + res_validate_state = atoi(r[i++]); + res_file_delete_state = atoi(r[i++]); + res_sent_time = atoi(r[i++]); } - -void DB_TRANSITIONER_QUEUE::parse_result(MYSQL_RES *result, MYSQL_ROW& row) { - fetch_field_value(result, row, "res_id", res_id); - fetch_field_value(result, row, "res_report_deadline", res_report_deadline); - fetch_field_value(result, row, "res_server_state", res_server_state); - fetch_field_value(result, row, "res_outcome", res_outcome); - fetch_field_value(result, row, "res_validate_state", res_validate_state); - fetch_field_value(result, row, "res_file_delete_state", res_file_delete_state); - fetch_field_value(result, row, "res_sent_time", res_sent_time); -} - -int DB_TRANSITIONER_QUEUE::seek_first_result() { - int retval; - MYSQL_ROW row; - - mysql_row_seek(current_entry_start_position); - row = mysql_fetch_row(cursor.rp); - if (!row) { - retval = -1; - } else { - parse_result(cursor.rp, row); - retval = 0; - } - - return retval; -} - -int DB_TRANSITIONER_QUEUE::seek_next_result() { - int retval; - int temp_workunit_id; - MYSQL_ROW row; - - row = mysql_fetch_row(cursor.rp); - if (!row) { - seek_first_result(); - retval = -1; - } else { - fetch_field_value(result, row, "id", temp_workunit_id); - if ( temp_workunit_id != current_entry_workunit_id ) { - seek_first_result(); - retval = -1; - } else { - parse_result(cursor.rp, row); - retval = 0; - } - } - - return retval; -} - diff --git a/db/boinc_db.h b/db/boinc_db.h index bdf7e9b27e..5e38e80f2d 100755 --- a/db/boinc_db.h +++ b/db/boinc_db.h @@ -28,6 +28,7 @@ // They don't necessarily serialize the entire records. #include +#include #include "db_base.h" @@ -427,7 +428,7 @@ struct MSG_TO_HOST { void clear(); }; -struct TRANSITIONER_QUEUE { +struct TRANSITIONER_ITEM { int id; char name[256]; int appid; @@ -451,6 +452,7 @@ struct TRANSITIONER_QUEUE { int res_file_delete_state; int res_sent_time; void clear(); + void parse(MYSQL_ROW&); }; #if 0 @@ -563,20 +565,21 @@ public: void db_parse(MYSQL_ROW &row); }; -class DB_TRANSITIONER_QUEUE : public DB_BASE, public TRANSITIONER_QUEUE { +// The transitioner uses this to get (WU, result) pairs efficiently. +// Each call to enumerate() returns a list of the pairs for a single WU +// +class DB_TRANSITIONER_ITEM_SET : public DB_BASE_SPECIAL { public: - DB_TRANSITIONER_QUEUE(); - - MYSQL_ROW_OFFSET current_entry_start_position; - int current_entry_workunit_id; - - int enumerate_entries(int transition_time, int ntotal_transitioners, int ntransitioner, int nresult_limit); - void parse_entry(MYSQL_RES *result, MYSQL_ROW& row); - void parse_result(MYSQL_RES *result, MYSQL_ROW& row); - - int seek_first_result(); - int seek_next_result(); + DB_TRANSITIONER_ITEM_SET(); + TRANSITIONER_ITEM last_item; + int enumerate( + int transition_time, + int ntotal_transitioners, + int ntransitioner, + int nresult_limit, + std::vector& items + ); }; #if 0 diff --git a/db/db_base.C b/db/db_base.C index 2efd5e4796..1670c4f4ab 100644 --- a/db/db_base.C +++ b/db/db_base.C @@ -10,9 +10,6 @@ #include "fcgi_stdio.h" #endif -#define MAX_QUERY_LEN 256000 - // TODO: use "string" instead of char[] - DB_CONN::DB_CONN() { mysql = 0; } @@ -254,66 +251,10 @@ int DB_BASE::sum(double& x, char* field, char* clause) { } -DB_BASE_PERF::DB_BASE_PERF(DB_CONN& p) : db(&p) { +DB_BASE_SPECIAL::DB_BASE_SPECIAL(DB_CONN& p) : db(&p) { cursor.active = false; } -int DB_BASE_PERF::fetch_field_value(MYSQL_RES *result, MYSQL_ROW& row, const char* field_name, int& field_value) -{ - unsigned int num_fields; - unsigned int i; - MYSQL_FIELD* fields; - - num_fields = mysql_num_fields(result); - fields = mysql_fetch_fields(result); - for(i = 0; i < num_fields; i++) - { - if (0 == strncmp(field_name, fields[i].name, strlen(field_name))) { - field_value = safe_atoi(row[i]); - } - } - - return 0; -} - -int DB_BASE_PERF::fetch_field_value(MYSQL_RES *result, MYSQL_ROW& row, const char* field_name, float& field_value) -{ - unsigned int num_fields; - unsigned int i; - MYSQL_FIELD* fields; - - num_fields = mysql_num_fields(result); - fields = mysql_fetch_fields(result); - for(i = 0; i < num_fields; i++) - { - if (0 == strncmp(field_name, fields[i].name, strlen(field_name))) { - field_value = safe_atof(row[i]); - } - } - - return 0; -} - -int DB_BASE_PERF::fetch_field_value(MYSQL_RES *result, MYSQL_ROW& row, const char* field_name, char* field_value, int field_size) -{ - unsigned int num_fields; - unsigned int i; - MYSQL_FIELD* fields; - - num_fields = mysql_num_fields(result); - fields = mysql_fetch_fields(result); - for(i = 0; i < num_fields; i++) - { - if (0 == strncmp(field_name, fields[i].name, strlen(field_name))) { - memset(field_value, '\0', field_size); - strlcpy(field_value, row[i], field_size); - } - } - - return 0; -} - - // convert a string into a form that allows it to be used // in SQL queries delimited by single quotes: // replace ' with \', \ with \\ diff --git a/db/db_base.h b/db/db_base.h index 716f08c7b9..c675317d42 100644 --- a/db/db_base.h +++ b/db/db_base.h @@ -25,14 +25,15 @@ // if SQL columns are not 'not null', you must use these safe_atoi, safe_atof // instead of atoi, atof, since the strings returned by MySQL may be NULL. // + inline int safe_atoi(const char* s) { - if (!s) return 0; - return atoi(s); + if (!s) return 0; + return atoi(s); } inline float safe_atof(const char* s) { - if (!s) return 0; - return atof(s); + if (!s) return 0; + return atof(s); } #define strcpy2(x, y) \ @@ -45,6 +46,9 @@ inline float safe_atof(const char* s) { } \ } +#define MAX_QUERY_LEN 256000 + // TODO: use string for queries, get rid of this + struct CURSOR { bool active; MYSQL_RES *rp; @@ -92,17 +96,12 @@ public: virtual void db_parse(MYSQL_ROW&); }; -// Base for derived classes that can access the DB -// Defines various generic operations on DB tables -// for specially designed queries +// Base for derived classes that can get special-purpose data, +// perhaps spanning multiple tables // -class DB_BASE_PERF { +class DB_BASE_SPECIAL { public: - DB_BASE_PERF(DB_CONN&); - - int fetch_field_value(MYSQL_RES* result, MYSQL_ROW& row, const char* field_name, int& field_value); - int fetch_field_value(MYSQL_RES* result, MYSQL_ROW& row, const char* field_name, float& field_value); - int fetch_field_value(MYSQL_RES* result, MYSQL_ROW& row, const char* field_name, char* field_value, int field_size); + DB_BASE_SPECIAL(DB_CONN&); DB_CONN* db; CURSOR cursor;