Client spamming server hotfix

svn path=/trunk/boinc/; revision=3734
This commit is contained in:
Rom Walton 2004-07-01 18:43:36 +00:00
parent b564dfa89d
commit d609e2bc48
7 changed files with 305 additions and 31 deletions

View File

@ -14411,3 +14411,12 @@ Brian 1 July 2004
client/
gui_rpc_client.h
Rom 1 July 2004
- Introduce skeleton of new transitioner queue class that uses a specialized
query for its job. NOTE: I don't know if it will even compile, but need another
set of eyes looking over it as well.
db/
db_base.C, .h
boinc_db.C, .h

View File

@ -8,6 +8,7 @@
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "win_config.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -30,12 +31,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
1 TEXTINCLUDE
BEGIN
"boinc_gui.h\0"
"win_config.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""win_config.h""\r\n"
"\0"
END
@ -298,8 +299,8 @@ IDI_ICONWARNING ICON "res\\iconwarning.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,19,0,0
PRODUCTVERSION 3,19,0,0
FILEVERSION MAJOR_VERSION,MINOR_VERSION,0,0
PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -316,12 +317,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Space Sciences Laboratory"
VALUE "FileDescription", "boinc_gui"
VALUE "FileVersion", "3.19"
VALUE "FileVersion", VERSION "\0"
VALUE "InternalName", "boinc_gui"
VALUE "LegalCopyright", "Copyright © 2004 University of California"
VALUE "OriginalFilename", "boinc_gui.exe"
VALUE "ProductName", "BOINC Core Client"
VALUE "ProductVersion", "3.19"
VALUE "ProductVersion", PACKAGE_VERSION "\0"
END
END
BLOCK "VarFileInfo"

View File

@ -1,7 +1,6 @@
// Microsoft Visual C++ generated resource script.
//
#include "boinc_ss.h"
#include "win_config.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
@ -9,6 +8,7 @@
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "win_config.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@ -31,12 +31,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
1 TEXTINCLUDE
BEGIN
"boinc_ss.h\0"
"win_config.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""win_config.h""\r\n"
"\0"
END

View File

@ -34,19 +34,6 @@ static struct random_init {
}
} random_init;
// 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);
}
inline float safe_atof(const char* s) {
if (!s) return 0;
return atof(s);
}
#define ESCAPE(x) escape_string(x, sizeof(x))
#define UNESCAPE(x) unescape_string(x, sizeof(x))
@ -72,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_MSG_TO_HOST::DB_MSG_TO_HOST() : DB_BASE(boinc_db, "msg_to_host"){}
DB_TRANSITIONER_QUEUE::DB_TRANSITIONER_QUEUE() : DB_BASE(boinc_db), current_entry_start_position(0), current_entry_workunit_id(0){}
int DB_PLATFORM::get_id() {return id;}
int DB_CORE_VERSION::get_id() {return id;}
@ -583,3 +570,150 @@ void DB_MSG_TO_HOST::db_parse(MYSQL_ROW& r) {
handled = atol(r[i++]);
strcpy2(xml, r[i++]);
}
int DB_TRANSITIONER_QUEUE::enumerate_queue_entries(int transition_time, int ntotal_transitioners, int ntransitioner, int nresult_limit) {
int x;
char query[MAX_QUERY_LEN];
char priority[16];
char mod[64];
MYSQL_ROW row;
int temp_workunit_id;
MYSQL_ROW_OFFSET temp_entry_position;
if (!cursor.active) {
cursor.active = true;
memset(priority, '\0', sizeof(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); }
sprintf(query,
"SELECT %s "
" wu.id, "
" wu.name, "
" wu.appid, "
" wu.min_quorum, "
" wu.need_validate, "
" wu.canonical_resultid, "
" wu.transition_time, "
" wu.delay_bound, "
" wu.error_mask, "
" wu.max_error_results, "
" wu.max_total_results, "
" wu.file_delete_state, "
" wu.assimilate_state, "
" wu.target_nresults, "
" wu.result_template, "
" res.id AS res_id, "
" res.report_deadline AS res_report_deadline, "
" res.server_state AS res_server_state, "
" res.outcome AS res_outcome, "
" res.validate_state AS res_validate_state, "
" res.file_delete_state AS res_file_delete_state, "
" res.sent_time AS res_sent_time "
"FROM "
" workunit AS wu "
" LEFT JOIN result AS res ON wu.id = res.workunitid "
"WHERE "
" wu.transition_time < %d AND "
" %s "
"LIMIT "
" %d ",
priority, transition_time, mod, nresult_limit);
x = db->do_query(query);
if (x) return mysql_errno(db->mysql);
cursor.rp = mysql_store_result(db->mysql);
if (!cursor.rp) return mysql_errno(db->mysql);
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);
}
}
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;
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);
parse_result(result, row);
}
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;
MYSQL_ROW row;
row = mysql_fetch_row(cursor.rp);
if (!row) {
retval = seek_first_result();
} else {
parse_result(cursor.rp, row);
retval = 0;
}
return retval;
}

View File

@ -427,6 +427,31 @@ struct MSG_TO_HOST {
void clear();
};
struct TRANSITIONER_QUEUE {
int id;
char name[256];
int appid;
int min_quorum;
bool need_validate;
int canonical_resultid;
int transition_time;
int delay_bound;
int error_mask;
int max_error_results;
int max_total_results;
int file_delete_state;
int assimilate_state;
int target_nresults;
int res_id;
int res_report_deadline;
int res_server_state;
int res_outcome;
int res_validate_state;
int res_file_delete_state;
int res_sent_time;
void clear();
};
#if 0
#define WORKSEQ_STATE_UNASSIGNED 0
#define WORKSEQ_STATE_ASSIGNED 1
@ -537,6 +562,22 @@ public:
void db_parse(MYSQL_ROW &row);
};
class DB_TRANSITIONER_QUEUE : public DB_BASE, public TRANSITIONER_QUEUE {
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();
};
#if 0
class DB_WORKSEQ : public DB_BASE, public WORKSEQ {
public:

View File

@ -253,6 +253,67 @@ int DB_BASE::sum(double& x, char* field, char* clause) {
return get_double(query, x);
}
DB_BASE_PERF::DB_BASE_PERF(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 \\

View File

@ -22,6 +22,29 @@
#include "mysql.h"
// 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);
}
inline float safe_atof(const char* s) {
if (!s) return 0;
return atof(s);
}
#define strcpy2(x, y) \
{ \
char* z = y; \
if (!z) { \
x[0]=0; \
} else { \
strlcpy(x, z, sizeof(x)); \
} \
}
struct CURSOR {
bool active;
MYSQL_RES *rp;
@ -38,7 +61,6 @@ public:
int insert_id();
void print_error(char*);
const char* error_string();
bool is_high_priority;
MYSQL* mysql;
};
@ -70,15 +92,21 @@ public:
virtual void db_parse(MYSQL_ROW&);
};
#define strcpy2(x, y) \
{ \
char* z = y; \
if (!z) { \
x[0]=0; \
} else { \
strlcpy(x, z, sizeof(x)); \
} \
}
// Base for derived classes that can access the DB
// Defines various generic operations on DB tables
// for specially designed queries
//
class DB_BASE_PERF {
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_CONN* db;
CURSOR cursor;
};
void escape_string(char* field, int len);
void unescape_string(char* p, int len);