diff --git a/checkin_notes b/checkin_notes index b27b559309..0bfc02c59c 100755 --- a/checkin_notes +++ b/checkin_notes @@ -9136,3 +9136,49 @@ Karl 2004-01-12 Karl 2004-01-12 - source release 2.18 (no client-visible changes) + +David Jan 12 2004 + - change team account so that team gets (and keeps) credit + for results of users while they belong to team: + - add team_id field to result + - add expavg_time field to team + - validator increments team credit + - scheduler fills in result.teamid + - don't delete empty teams + - rename result.client_version_num to result.app_version_num + populate this field based on field of stderr_out + - change update_stats so that it doesn't compute team credit fields, + and so that it updates expavg fields only if the entity + has been idle for 4 days or more + - add DB_BASE::update_field() (to update one or more fields, + not whole record) + - add lookup_team() to db.inc + SHOULD ALWAYS USE FUNCTIONS LIKE THIS INSTEAD OF AD-HOC QUERIES + - factor out mysql_query() into DB_BASE::do_query() + + db/ + db_boinc.C,h + db_base.C,h + schema.sql + html_user/ + db.inc + team.inc + team_join_action.php + team_quit_action.php + sched/ + handle_request.C + update_stats.C + validate.C + +David Jan 14 2004 + - typo in boincxml.py + (caused "start" script to always set enabled=0 + in run_state file, with various bad consequences) + - two indentation problems in "start": + line 499 + line 516 + + py/Boinc/ + boincxml.py + sched/ + start diff --git a/db/boinc_db.C b/db/boinc_db.C index e2090c27c8..f257e531af 100644 --- a/db/boinc_db.C +++ b/db/boinc_db.C @@ -263,7 +263,8 @@ void DB_TEAM::db_print(char* buf){ "id=%d, create_time=%d, userid=%d, name='%s', " "name_lc='%s', url='%s', " "type=%d, name_html='%s', description='%s', nusers=%d, " - "country='%s', total_credit=%.15e, expavg_credit=%.15e, " + "country='%s', " + "total_credit=%.15e, expavg_credit=%.15e, expavg_time=%.15e, " "seti_id=%d", id, create_time, @@ -278,6 +279,7 @@ void DB_TEAM::db_print(char* buf){ country, total_credit, expavg_credit, + expavg_time, seti_id ); unescape_string(name); @@ -303,6 +305,7 @@ void DB_TEAM::db_parse(MYSQL_ROW &r) { strcpy2(country, r[i++]); total_credit = atof(r[i++]); expavg_credit = atof(r[i++]); + expavg_time = atof(r[i++]); seti_id = safe_atoi(r[i++]); } @@ -472,7 +475,7 @@ void DB_RESULT::db_print(char* buf){ "xml_doc_in='%s', xml_doc_out='%s', stderr_out='%s', " "batch=%d, file_delete_state=%d, validate_state=%d, " "claimed_credit=%.15e, granted_credit=%.15e, opaque=%f, random=%d, " - "client_version_num=%d, appid=%d, exit_status=%d", + "app_version_num=%d, appid=%d, exit_status=%d, teamid=%d", id, create_time, workunitid, server_state, outcome, client_state, hostid, userid, @@ -481,7 +484,7 @@ void DB_RESULT::db_print(char* buf){ xml_doc_in, xml_doc_out, stderr_out, batch, file_delete_state, validate_state, claimed_credit, granted_credit, opaque, random, - client_version_num, appid, exit_status + app_version_num, appid, exit_status, teamid ); unescape_string(xml_doc_out); unescape_string(stderr_out); @@ -513,9 +516,10 @@ void DB_RESULT::db_parse(MYSQL_ROW &r) { granted_credit = atof(r[i++]); opaque = atof(r[i++]); random = atoi(r[i++]); - client_version_num = atoi(r[i++]); + app_version_num = atoi(r[i++]); appid = atoi(r[i++]); exit_status = atoi(r[i++]); + teamid = atoi(r[i++]); } int DB_RESULT::insert() { diff --git a/db/boinc_db.h b/db/boinc_db.h index aae5b642c5..9577c7c1f3 100755 --- a/db/boinc_db.h +++ b/db/boinc_db.h @@ -199,8 +199,9 @@ struct TEAM { char description[LARGE_BLOB_SIZE]; int nusers; // UNDEFINED BY DEFAULT char country[256]; - double total_credit; // UNDEFINED BY DEFAULT - double expavg_credit; // UNDEFINED BY DEFAULT + double total_credit; + double expavg_credit; + double expavg_time; // The following is specific to SETI@home int seti_id; // ID in old DB @@ -406,9 +407,10 @@ struct RESULT { double granted_credit; // == canonical credit of WU double opaque; // project-specific; usually external ID int random; // determines send order - int client_version_num; + int app_version_num; // version# of app (not core client) int appid; // copy of WU's appid int exit_status; // application exit status, if any + int teamid; // the following not used in the DB char wu_name[256]; diff --git a/db/db_base.C b/db/db_base.C index 93f272fc47..226d274206 100644 --- a/db/db_base.C +++ b/db/db_base.C @@ -24,12 +24,16 @@ void DB_CONN::close() { if (mysql) mysql_close(mysql); } +int DB_CONN::do_query(char* p) { + return mysql_query(mysql, p); +} + int DB_CONN::insert_id() { int retval; MYSQL_ROW row; MYSQL_RES* rp; - retval = mysql_query(mysql, "select LAST_INSERT_ID()"); + retval = do_query("select LAST_INSERT_ID()"); if (retval) return retval; rp = mysql_store_result(mysql); row = mysql_fetch_row(rp); @@ -61,14 +65,25 @@ int DB_BASE::insert() { char vals[MAX_QUERY_LEN], query[MAX_QUERY_LEN]; db_print(vals); sprintf(query, "insert into %s set %s", table_name, vals); - return mysql_query(db->mysql, query); + return db->do_query(query); } +// update an entire record +// int DB_BASE::update() { char vals[MAX_QUERY_LEN], query[MAX_QUERY_LEN]; db_print(vals); sprintf(query, "update %s set %s where id=%d", table_name, vals, get_id()); - return mysql_query(db->mysql, query); + return db->do_query(query); +} + +// update one or more fields +// "clause" is something like "foo=5, blah='xxx'" or "foo=foo+5" +// +int DB_BASE::update_field(char* clause) { + char query[MAX_QUERY_LEN]; + sprintf(query, "update %s set %s where id=%d", table_name, clause, get_id()); + return db->do_query(query); } int DB_BASE::lookup(char* clause) { @@ -78,7 +93,7 @@ int DB_BASE::lookup(char* clause) { MYSQL_RES* rp; sprintf(query, "select * from %s %s", table_name, clause); - retval = mysql_query(db->mysql, query); + retval = db->do_query(query); if (retval) return retval; rp = mysql_store_result(db->mysql); if (!rp) return -1; @@ -101,7 +116,7 @@ int DB_BASE::lookup_id(int id) { MYSQL_RES* rp; sprintf(query, "select * from %s where id=%d", table_name, id); - retval = mysql_query(db->mysql, query); + retval = db->do_query(query); if (retval) return retval; rp = mysql_store_result(db->mysql); if (!rp) return -1; @@ -122,7 +137,7 @@ int DB_BASE::enumerate(char* clause) { if (!cursor.active) { cursor.active = true; sprintf(query, "select * from %s %s", table_name, clause); - x = mysql_query(db->mysql, query); + 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); @@ -143,7 +158,7 @@ int DB_BASE::get_integer(char* query, int& n) { MYSQL_ROW row; MYSQL_RES* resp; - retval = mysql_query(db->mysql, query); + retval = db->do_query(query); if (retval) return retval; resp = mysql_store_result(db->mysql); if (!resp) return ERR_DB_NOT_FOUND; @@ -160,7 +175,7 @@ int DB_BASE::get_double(char* query, double& x) { MYSQL_ROW row; MYSQL_RES* resp; - retval = mysql_query(db->mysql, query); + retval = db->do_query(query); if (retval) return retval; resp = mysql_store_result(db->mysql); if (!resp) return ERR_DB_NOT_FOUND; diff --git a/db/db_base.h b/db/db_base.h index baa0b043d9..70ab02cfe5 100644 --- a/db/db_base.h +++ b/db/db_base.h @@ -33,6 +33,7 @@ class DB_CONN { public: DB_CONN(); int open(char* name, char* host, char* passwd); + int do_query(char*); void close(); int insert_id(); void print_error(char*); @@ -49,6 +50,7 @@ public: DB_BASE(DB_CONN&, char *table_name); int insert(); int update(); + int update_field(char*); int lookup_id(int id); int lookup(char*); int enumerate(char* clause=""); diff --git a/db/schema.sql b/db/schema.sql index db1e93d3d1..57b59126d0 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -103,6 +103,7 @@ create table team ( country varchar(254), total_credit double not null, /* temp */ expavg_credit double not null, /* temp */ + expavg_time double not null, seti_id integer not null, primary key (id) ); @@ -217,7 +218,7 @@ create table result ( granted_credit double not null, opaque double not null, random integer not null, - client_version_num integer not null, + app_version_num integer not null, appid integer not null, exit_status integer not null, primary key (id) diff --git a/html/user/db.inc b/html/user/db.inc index 07ea4147eb..a8c5236ef0 100644 --- a/html/user/db.inc +++ b/html/user/db.inc @@ -54,6 +54,16 @@ function lookup_host($id) { return null; } +function lookup_team($id) { + $result = mysql_query("select * from team where id='$id'"); + if ($result) { + $team = mysql_fetch_object($result); + mysql_free_result($result); + return $team; + } + return null; +} + function lookup_wu($id) { $result = mysql_query("select * from workunit where id='$id'"); if ($result) { diff --git a/html/user/team.inc b/html/user/team.inc index faa9046c5e..37715c0fe7 100644 --- a/html/user/team.inc +++ b/html/user/team.inc @@ -46,16 +46,9 @@ function display_team_page($team, $user) { } row2("Members", $team->nusers); - $result = mysql_query("select * from user where teamid=$team->id"); - $total_credit = 0; - for ($i = 0; $i < $team->nusers; $i++) { - $user = mysql_fetch_object($result); - $total_credit = $total_credit + $user->total_credit; - } - - row2("Total credit", format_credit($total_credit)); - $result = mysql_query("select * from user where id=$team->userid"); - $user = mysql_fetch_object($result); + row2("Total credit", format_credit($team->total_credit)); + row2("Recent average credit", format_credit($team->expavg_credit)); + $user = lookup_user_id($team->userid); row2("Founder", user_links($user)); row2("Country", $team->country); echo ""; @@ -73,9 +66,7 @@ function display_team_page($team, $user) { $result = mysql_query("select * from user where teamid=$team->id order by expavg_credit desc"); $j = 1; - while (true) { - $user = mysql_fetch_object($result); - if (!$user) break; + while ($user = mysql_fetch_object($result)) { $user_total_credit = format_credit($user->total_credit); $user_expavg_credit = format_credit($user->expavg_credit); $x = user_links($user); @@ -171,14 +162,7 @@ function user_join_team($team, $user) { $user->id ); $result_user_table = mysql_query($query_user_table); - $nusers = $team->nusers; - $new_nusers = $nusers + 1; - $query_team_table = sprintf( - "update team set nusers = %d where id = %d", - $new_nusers, - $team->id - ); - $result_team_table = mysql_query($query_team_table); + $result_team_table = mysql_query("update team set nusers=nusers+1 where id = $team->id"); if ($result_user_table && $result_team_table) return true; else return false; } diff --git a/html/user/team_join_action.php b/html/user/team_join_action.php index b73b510f40..9aa3b8cb5b 100644 --- a/html/user/team_join_action.php +++ b/html/user/team_join_action.php @@ -8,9 +8,7 @@ $user = get_logged_in_user(); $teamid = $_POST["teamid"]; - $result = mysql_query("select * from team where id = $teamid"); - $team = mysql_fetch_object($result); - mysql_free_result($result); + team = lookup_team($teamid); require_team($team); if ($user->teamid == $team->id) { page_head("Unable to add $user->name"); diff --git a/html/user/team_quit_action.php b/html/user/team_quit_action.php index c51ff1e25a..b8c3d2f9ce 100644 --- a/html/user/team_quit_action.php +++ b/html/user/team_quit_action.php @@ -5,44 +5,19 @@ db_init(); $user = get_logged_in_user(); + $teamid = $_POST["id"] - $query = sprintf( - "select * from team where id = %d", - $_POST["id"] - ); - $result = mysql_query($query); - $team = mysql_fetch_object($result); - mysql_free_result($result); + $team = lookup_team($teamid); if ($user->teamid == $team->id) { - $query_user_table = sprintf( - "update user set teamid = %d where id = %d", - 0, - $user->id - ); + $query_user_table = "update user set teamid = 0 where id = $user->id"; $result_user_table = mysql_query($query_user_table); - $nusers = $team->nusers; - $new_nusers = $nusers - 1; - if ($new_nusers > 0) { - $query_team_table = sprintf( - "update team set nusers = %d where id = %d", - $new_nusers, - $team->id - ); - } else { - $query_team_table = sprintf( - "delete from team where id = %d", - $team->id - ); - } + $query_team_table = "update team set nusers=nusers-1 where id=$team->id"; $result_team_table = mysql_query($query_team_table); if ($result_user_table && $result_team_table) { $team_name = $team->name; page_head("Quit $team_name"); echo "

Removed from team

"; echo "You have been removed from id>$team_name"; - if ($new_nusers <= 0) { - echo "

Since you were the last member of the team, it has been disbanded."; - } } else { page_head("Error"); echo "Couldn't quit team - please try later.\n"; diff --git a/py/Boinc/boincxml.py b/py/Boinc/boincxml.py index 1627041bb5..29e56f8c25 100644 --- a/py/Boinc/boincxml.py +++ b/py/Boinc/boincxml.py @@ -39,7 +39,7 @@ def get_element_data(node): def get_element_int(node, default=0): try: - return int(_get_element_data(node)) + return int(get_element_data(node)) except: return default diff --git a/sched/handle_request.C b/sched/handle_request.C index c674b636fb..3ad59d8fce 100644 --- a/sched/handle_request.C +++ b/sched/handle_request.C @@ -600,8 +600,8 @@ int handle_results( } strncpy(result.stderr_out, rp->stderr_out, sizeof(result.stderr_out)); strncpy(result.xml_doc_out, rp->xml_doc_out, sizeof(result.xml_doc_out)); - result.client_version_num = - sreq.core_client_major_version*100 + sreq.core_client_minor_version; + parse_int(result.stderr_out, "", result.app_version_num); + result.teamid = reply.user.teamid; retval = result.update(); if (retval) { log_messages.printf( diff --git a/sched/start b/sched/start index b316acbda0..57a5f946d1 100755 --- a/sched/start +++ b/sched/start @@ -496,7 +496,7 @@ def command_enable_start(): print "Staying in ENABLED mode" else: print "Entering ENABLED mode" - run_state.enabled = True + run_state.enabled = True run_daemons() def command_cron_start(): @@ -513,7 +513,6 @@ def command_disable_stop(): print "Entering DISABLED mode" else: print "Staying in DISABLED mode" - run_state.enabled = True run_state.enabled = False stop_daemons() diff --git a/sched/update_stats.C b/sched/update_stats.C index b734884296..ed787884ab 100644 --- a/sched/update_stats.C +++ b/sched/update_stats.C @@ -16,10 +16,14 @@ // // Contributor(s): // - -// update_stats -// update average credit for users and hosts, -// and calculate total users/credit for teams +// update_stats: +// Update average credit for idle users, hosts and teams. +// These fields are updates as new credit is granted; +// the purpose of this program is to decay credit of entities +// that are inactive for long periods. +// Hence it should be run about once a day at most. +// +// Also updates the nusers field of teams // // usage: update_stats [-update_teams] [-update_users] [-update_hosts] [-asynch] @@ -36,11 +40,16 @@ #define LOCKFILE "update_stats.out" #define PIDFILE "update_stats.pid" +#define UPDATE_INTERVAL 3600*24*4; + +double update_time_cutoff; + int update_users() { DB_USER user; int retval; while (!user.enumerate()) { + if (user.expavg_time > update_time_cutoff) continue; update_average(0, 0, user.expavg_credit, user.expavg_time); retval = user.update(); if (retval) { @@ -57,6 +66,7 @@ int update_hosts() { int retval; while (!host.enumerate()) { + if (host.expavg_time > update_time_cutoff) continue; update_average(0, 0, host.expavg_credit, host.expavg_time); retval = host.update(); if (retval) { @@ -68,9 +78,8 @@ int update_hosts() { return 0; } -int get_team_credit(TEAM& team) { +int get_team_totals(TEAM& team) { int nusers; - double expavg_credit, total_credit; int retval; DB_USER user; char buf[256]; @@ -81,23 +90,7 @@ int get_team_credit(TEAM& team) { retval = user.count(nusers, buf); if (retval) return retval; - // get the summed credit values for a team - // - sprintf(buf, "where teamid=%d", team.id); - retval = user.sum(expavg_credit, "expavg_credit", buf); - // we'll get error if nusers == 0 - // - if (retval) { - expavg_credit = 0; - } - retval = user.sum(total_credit, "total_credit", buf); - if (retval) { - total_credit = 0; - } - team.nusers = nusers; - team.total_credit = total_credit; - team.expavg_credit = expavg_credit; return 0; } @@ -111,17 +104,19 @@ int update_teams() { int retval; while (!team.enumerate()) { - retval = get_team_credit(team); + retval = get_team_totals(team); if (retval) { log_messages.printf( SchedMessages::CRITICAL, "update_teams: get_team_credit([TEAM#%d]) failed: %d\n", team.id, - retval); - //return retval; + retval + ); continue; } - + if (team.expavg_time < update_time_cutoff) { + update_average(0, 0, team.expavg_credit, team.expavg_time); + } retval = team.update(); if (retval) { log_messages.printf(SchedMessages::CRITICAL, "Can't update team %d\n", team.id); @@ -137,6 +132,8 @@ int main(int argc, char** argv) { bool do_update_teams = false, do_update_users = false; bool do_update_hosts = false, asynch = false; + update_time_cutoff = time(0) - UPDATE_INTERVAL; + check_stop_trigger(); for (i=1; i