*** empty log message ***

svn path=/trunk/boinc/; revision=4840
This commit is contained in:
David Anderson 2004-12-14 00:57:03 +00:00
parent 2beff6f74c
commit c0c47595ac
9 changed files with 153 additions and 82 deletions

View File

@ -21191,3 +21191,40 @@ Karl 2004-12-13
test/
testbase.py
David 13 Dec 2004
- Fix a bug where a result could potentially bounce back
and forth between the transitioner and the validator.
This could happen if there are min_quorum success results,
and there's no consensus.
The fix:
- added new value for result.validate_state:
VALIDATE_STATE_INCONCLUSIVE means that check_set()
was called for the result and it didn't find a canonical result.
- The transitioner sets workunit.need_validate
if there are min_quorum success results,
and at least one is VALIDATE_STATE_INIT
(no change - this is how it currently is)
- validator:
consider results that are both INIT and INCONCLUSIVE
If check_set() doesn't find a quorum,
set all result states to INCONCLUSIVE
Thanks to Kjell Nedrelid (Rattledagger) for finding this.
- added logic to admin HTML to show INCONCLUSIVE state
- Took boinc_real_escape_string() stuff out of HTML ops code.
If prevented SQL queries from working on isaac
db/
boinc_db.h
html/
inc/
db_ops.inc
result.inc
user.inc
ops/
db_action.php
sched/
assimilator.C
transitioner.C
validator.C

View File

@ -371,7 +371,8 @@ struct WORKUNIT {
// got a quorum
#define RESULT_OUTCOME_VALIDATE_ERROR 6
// The outcome was initially SUCCESS, but the validator
// had a permanent error reading a result file
// had a permanent error reading a result file,
// or the result file had a syntax error
#define VALIDATE_STATE_INIT 0
#define VALIDATE_STATE_VALID 1
@ -379,6 +380,9 @@ struct WORKUNIT {
#define VALIDATE_STATE_NO_CHECK 3
// WU had error, so we'll never get around to validating its results
// This lets us avoid showing the claimed credit as "pending"
#define VALIDATE_STATE_INCONCLUSIVE 4
// the validator looked this result (as part of a check_set() call)
// but didn't find a canonical result.
struct RESULT {
int id;

View File

@ -1,21 +1,27 @@
<?php
echo "<!--\$Id$ -->\n";
define("NVALIDATE_STATES", 5);
// Function prints a description of $table
//
function print_describe_table_onecol($table, $which, $columns) {
$result=mysql_query("SELECT * from $table LIMIT 1");
$fields=mysql_num_fields($result);
$avgnum=(int)($fields/$columns);
if ($avgnum*$columns<$fields)
if ($avgnum*$columns<$fields) {
$avgnum++;
}
$actualcolumns=0;
while ($avgnum*$actualcolumns<$fields)
while ($avgnum*$actualcolumns<$fields) {
$actualcolumns++;
}
if ($which>$actualcolumns)
if ($which>$actualcolumns) {
return 0;
}
$bot=($which-1)*$avgnum;
$top=$which*$avgnum;
@ -30,8 +36,7 @@ function print_describe_table_onecol($table, $which, $columns) {
$name= mysql_field_name($result, $count);
$type= mysql_field_type($result, $count);
$length=mysql_field_len($result, $count);
}
else {
} else {
$name="<br/> ";
$type="<br/>";
$length="<br/>";
@ -46,8 +51,9 @@ function print_describe_table($table, $how_many_columns) {
// Number of columns for showing table description
echo "<h2>Description of <b>$table</b> table fields:</h2>\n";
echo "<table border='0' width='100%'>\n\t<tr>";
for ($i=1; $i<=$how_many_columns; $i++)
for ($i=1; $i<=$how_many_columns; $i++) {
print_describe_table_onecol($table, $i, $how_many_columns);
}
echo "\t</tr>\n</table>\n";
return 0;
}
@ -103,11 +109,11 @@ class SqlQueryString {
$this->urlquery = "";
}
function add($clause) {
$cleaned=boinc_real_escape_string($clause);
if (!$this->query) {
$this->query .= "where $cleaned";
//$clause=boinc_real_escape_string($clause);
if (!$this->query) {
$this->query .= "where $clause";
} else {
$this->query .= " and $cleaned";
$this->query .= " and $clause";
}
}
function addclause($clause) {
@ -183,7 +189,7 @@ class SqlQueryString {
$this->addeq('userid');
$this->addeq('teamid');
$this->addeq('exit_status');
if ($_GET['nsecs']) {
if ($_GET['nsecs']) {
$_GET['received_time'] = time() - $_GET['nsecs'];
}
$this->addgt('received_time');
@ -222,10 +228,11 @@ function exit_status_string($result) {
$x = (int)$y;
}
}
if (0<=$x && $x<=9)
if (0<=$x && $x<=9) {
return "$x";
else
} else {
return sprintf("%d (0x%x)", $x, $x);
}
}
function show_result_summary() {
@ -251,16 +258,17 @@ function show_result_summary() {
for ($fds=0; $fds<3; $fds++) {
$delete_state[$fds] = 0;
}
for ($vs=0; $vs<4; $vs++) {
$validate_state[$vs]=0;
for ($vs=0; $vs<NVALIDATE_STATES; $vs++) {
$validate_state[$vs]=0;
}
$_GET['table'] = 'result';
$_GET['sort_by'] = ''; // ignore sort
$query_appid = $_GET['appid'];
if ($_GET['nsecs'])
$query_received_time = time() - $_GET['nsecs'];
if ($_GET['nsecs']) {
$query_received_time = time() - $_GET['nsecs'];
}
$query_wuid = $_GET['workunitid'];
$q = new SqlQueryString();
@ -285,6 +293,7 @@ SELECT COUNT(id) AS nTotal,
SUM(case when server_state = '5' and outcome = '1' and validate_state = '1' then 1 else 0 end) AS validate_valid,
SUM(case when server_state = '5' and outcome = '1' and validate_state = '2' then 1 else 0 end) AS validate_invalid,
SUM(case when server_state = '5' and outcome = '1' and validate_state = '3' then 1 else 0 end) AS validate_nocheck,
SUM(case when server_state = '5' and outcome = '1' and validate_state = '4' then 1 else 0 end) AS validate_inconclusive,
SUM(case when server_state = '5' and outcome = '1' and file_delete_state = '0' then 1 else 0 end) AS filedeletestate_init,
SUM(case when server_state = '5' and outcome = '1' and file_delete_state = '1' then 1 else 0 end) AS filedeletestate_ready,
SUM(case when server_state = '5' and outcome = '1' and file_delete_state = '2' then 1 else 0 end) AS filedeletestate_done,
@ -295,16 +304,19 @@ SELECT COUNT(id) AS nTotal,
SUM(case when server_state = '5' and outcome = '3' and client_state = '4' then 1 else 0 end) AS clientstate_uploading,
SUM(case when server_state = '5' and outcome = '3' and client_state = '5' then 1 else 0 end) AS clientstate_uploaded
FROM result WHERE
";
";
if ($query_appid)
$main_query .= "appid=$query_appid and ";
if ($query_wuid)
$main_query .= "workunitid=$query_wuid and ";
if ($query_received_time)
$main_query .= "received_time > $query_received_time and ";
if ($query_appid) {
$main_query .= "appid=$query_appid and ";
}
if ($query_wuid) {
$main_query .= "workunitid=$query_wuid and ";
}
if ($query_received_time) {
$main_query .= "received_time > $query_received_time and ";
}
$main_query .= "1=1";
$main_query .= "1=1";
$urlquery = $q->urlquery;
$result = mysql_query($main_query);
@ -328,7 +340,7 @@ if ($query_received_time)
$outcome[3] = $res->outcome_failure;
$outcome[4] = $res->outcome_noreply;
$outcome[5] = $res->outcome_didntneed;
$outcome[6] = $res->outcome_validateerror;
$outcome[6] = $res->outcome_validateerror;
$client_state[1] = $res->clientstate_downloading;
$client_state[2] = $res->clientstate_downloaded;
@ -339,7 +351,8 @@ if ($query_received_time)
$validate_state[0] = $res->validate_init;
$validate_state[1] = $res->validate_valid;
$validate_state[2] = $res->validate_invalid;
$validate_state[3] = $res->validate_skipped;
$validate_state[3] = $res->validate_nocheck;
$validate_state[4] = $res->validate_inconclusive;
$file_delete[0] = $res->filedeletestate_init;
$file_delete[1] = $res->filedeletestate_ready;
@ -378,20 +391,20 @@ if ($query_received_time)
echo "<td><table border=2 cellpadding=4\n";
echo "<tr><th>Validate state</th><th># results</th></tr>\n";
for ($vs=0; $vs<4; $vs++) {
c_row2($validate_state[$vs]?validate_color($vs):'', validate_state_str($vs),
link_results("$validate_state[$vs]", $urlquery, "validate_state=$vs", "outcome=1"));
for ($vs=0; $vs<NVALIDATE_STATES; $vs++) {
c_row2($validate_state[$vs]?validate_color($vs):'', validate_state_str($vs),
link_results("$validate_state[$vs]", $urlquery, "validate_state=$vs", "outcome=1"));
}
echo "</table>";
echo "<table border=2 cellpadding=4\n";
echo "<tr><th>File Delete state</th><th># results</th></tr>\n";
for ($fds=0; $fds<3; $fds++) {
row2(file_delete_state_str($fds),
link_results("$file_delete[$fds]", $urlquery, "outcome=1", "file_delete_state=$fds"));
row2(file_delete_state_str($fds),
link_results("$file_delete[$fds]", $urlquery, "outcome=1", "file_delete_state=$fds"));
}
row2("Total files deleted",
link_results("$nfile_deleted", $urlquery, "outcome=1", "(file_delete_state=1 or file_delete_state=2)"));
link_results("$nfile_deleted", $urlquery, "outcome=1", "(file_delete_state=1 or file_delete_state=2)"));
echo "</table></td>";
echo "<td><table border=2 cellpadding=4\n";
@ -433,7 +446,7 @@ function validate_state_select() {
<select name=validate_state>
<option value='CHOOSE_ALL' selected> Any
";
for($i=0; $i<4; $i++) {
for($i=0; $i<NVALIDATE_STATES; $i++) {
echo "<option value=$i> "."[$i]&nbsp;&nbsp;".' '.validate_state_str($i)."</option>\n";
}
echo "</select>\n";
@ -642,10 +655,11 @@ function wu_error_mask_str($s) {
if ($s) {
$x = $x."Unrecognized Error: $s<br>";
}
if (strlen($x))
if (strlen($x)) {
$x="<font color='ff3333'>".$x."</font>";
else
$x="<br>";
} else {
$x="<br>";
}
return $x;
}
@ -785,6 +799,7 @@ function validate_state_str($s) {
case 1: return "Valid";
case 2: return "Invalid";
case 3: return "Skipped";
case 4: return "Inconclusive";
}
echo "<b>THIS IS AN INTERNAL BUG IN BOINC: PLEASE CONTACT BOINC DEVELOPERS</b><br/>";
return "Unknown";
@ -900,11 +915,12 @@ function show_result_short($result) {
else {
// result has not been received yet, so show report deadline either
// in green if in the future or in red if in the past.
$timenow=time();
if ($result->report_deadline>=$timenow)
$timenow=time();
if ($result->report_deadline>=$timenow) {
$colortag="<font color='33cc33'>";
else
} else {
$colortag="<font color='ff3333'>";
}
$received = $colortag . time_str($result->report_deadline) . "</font>";
}
$version = $result->app_version_num;
@ -924,7 +940,7 @@ function show_result_short($result) {
<td bgcolor=$outcome_color>$oc</td>
<td bgcolor=$validate_color>$vs</td>
<td>$delete_state</td>
<td>", exit_status_string($result), "</td>
<td>", exit_status_string($result), "</td>
<td>$host_user</td>
<td>$version</td>
<td>$received</td>

View File

@ -17,11 +17,12 @@ function result_granted_credit_string($result, $string_to_show) {
if ($result->server_state <> 5) return "---";
switch($result->outcome) {
case 1: //Success
if ($result->validate_state == 0) {
return "pending";
} else {
return $string_to_show;
switch ($result->validate_state) {
case 0:
case 4:
return "pending";
}
return $string_to_show;
case 2: return "---"; //Couldn't send
case 3: return "---"; //Client error
case 4: return "---"; //No reply
@ -70,7 +71,8 @@ function validate_state_str($s) {
case 0: return "Initial";
case 1: return "Valid";
case 2: return "Invalid";
case 3: return "Check skipped";
case 3: return "WU error - check skipped";
case 4: return "Checked, but no consensus yet";
}
return "Unknown";
}
@ -118,10 +120,11 @@ function show_result_row(
$r = time_str($result->received_time);
else {
$timenow=time();
if ($result->report_deadline>$timenow)
if ($result->report_deadline>$timenow) {
$r = "<font color='33cc33'>" . time_str($result->report_deadline) . "</font>";
else
} else {
$r = "<font color='ff3333'>" . time_str($result->report_deadline) . "</font>";
}
}
$ss = result_server_state_string($result->server_state);
$out = result_outcome_string($result->outcome);

View File

@ -4,7 +4,7 @@ require_once("../inc/credit.inc");
require_once("../inc/email.inc");
function pending_credit($user) {
$result = mysql_query("select sum(claimed_credit) as total from result where userid=$user->id and validate_state=0");
$result = mysql_query("select sum(claimed_credit) as total from result where userid=$user->id and (validate_state=0 or validate_state=4)");
$foobar = mysql_fetch_object($result);
if (!$foobar) return 0;
mysql_free_result($result);

View File

@ -116,7 +116,7 @@
}
}
$result = mysql_query(boinc_real_escape_string($main_query));
$result = mysql_query($main_query);
if ($result) {
if ($detail == "low") {
start_table();

View File

@ -47,7 +47,7 @@ bool update_db = true;
bool noinsert = false;
#define SLEEP_INTERVAL 1
#define SLEEP_INTERVAL 10
// assimilate all WUs that need it
// return nonzero if did anything
@ -108,9 +108,11 @@ bool do_pass(APP& app) {
boinc_db.commit_transaction();
}
log_messages.printf(SCHED_MSG_LOG::NORMAL,
if (num_assimilated) {
log_messages.printf(SCHED_MSG_LOG::NORMAL,
"Assimilated %d workunits.\n", num_assimilated
);
);
}
return did_something;
}
@ -133,16 +135,16 @@ int main(int argc, char** argv) {
} else if (!strcmp(argv[i], "-app")) {
strcpy(app.name, argv[++i]);
} else if (!strcmp(argv[i], "-dont_update_db")) {
// This option is for testing your assimilator. When set,
// it ensures that the assimilator does not actually modify
// the assimilate_state of the workunits, so you can run
// your assimilator over and over again without affecting
// your project.
// This option is for testing your assimilator. When set,
// it ensures that the assimilator does not actually modify
// the assimilate_state of the workunits, so you can run
// your assimilator over and over again without affecting
// your project.
update_db = false;
} else if (!strcmp(argv[i], "-noinsert")) {
// This option is also for testing and is used to
// prevent the inserting of results into the *backend*
// (as opposed to the boinc) DB.
// This option is also for testing and is used to
// prevent the inserting of results into the *backend*
// (as opposed to the boinc) DB.
noinsert = true;
} else {
log_messages.printf(SCHED_MSG_LOG::CRITICAL, "Unrecognized arg: %s\n", argv[i]);

View File

@ -71,7 +71,7 @@ int handle_wu(
int canonical_result_index, j;
char suffix[256];
time_t now = time(0), x;
bool all_over_and_validated, have_result_to_validate, do_delete;
bool all_over_and_validated, have_new_result_to_validate, do_delete;
unsigned int i;
// count up the number of results in various states,
@ -86,7 +86,7 @@ int handle_wu(
ncouldnt_send = 0;
nno_reply = 0;
ndidnt_need = 0;
have_result_to_validate = false;
have_new_result_to_validate = false;
int rs, max_result_suffix = -1;
TRANSITIONER_ITEM& wu_item = items[0];
@ -139,7 +139,7 @@ int handle_wu(
break;
case RESULT_OUTCOME_SUCCESS:
if (res_item.res_validate_state == VALIDATE_STATE_INIT) {
have_result_to_validate = true;
have_new_result_to_validate = true;
}
nsuccess++;
break;
@ -168,7 +168,7 @@ int handle_wu(
// trigger validation if we have a quorum
// and some result hasn't been validated
//
if (nsuccess >= wu_item.min_quorum && have_result_to_validate) {
if (nsuccess >= wu_item.min_quorum && have_new_result_to_validate) {
wu_item.need_validate = true;
log_messages.printf(
SCHED_MSG_LOG::NORMAL,

View File

@ -200,10 +200,13 @@ void handle_wu(
for (i=0; i<items.size(); i++) {
RESULT& result = items[i].res;
if (!((result.validate_state == VALIDATE_STATE_INIT) &&
(result.server_state == RESULT_SERVER_STATE_OVER) &&
(result.outcome == RESULT_OUTCOME_SUCCESS))
) {
if (result.server_state != RESULT_SERVER_STATE_OVER) continue;
if (result.outcome != RESULT_OUTCOME_SUCCESS) continue;
switch (result.validate_state) {
case VALIDATE_STATE_INIT:
case VALIDATE_STATE_INCONCLUSIVE:
break;
default:
continue;
}
@ -223,7 +226,8 @@ void handle_wu(
update_result = true;
}
// ?? do we need this here?
// this might be last result, so let validator
// trigger file delete etc. if needed
//
need_immediate_transition = true;
@ -335,9 +339,10 @@ void handle_wu(
nsuccess_results++;
}
// grant credit for valid results
//
if (result.validate_state == VALIDATE_STATE_VALID) {
switch (result.validate_state) {
case VALIDATE_STATE_VALID:
// grant credit for valid results
//
update_result = true;
retval = grant_credit(result, credit);
if (retval) {
@ -353,9 +358,14 @@ void handle_wu(
"[RESULT#%d %s] Granted %f credit to valid result [HOST#%d]\n",
result.id, result.name, result.granted_credit, result.hostid
);
}
if (result.validate_state == VALIDATE_STATE_INVALID) {
update_result = true;
break;
case VALIDATE_STATE_INVALID:
update_result = true;
break;
case VALIDATE_STATE_INIT:
result.validate_state = VALIDATE_STATE_INCONCLUSIVE;
update_result = true;
break;
}
if (update_result) {
@ -403,14 +413,12 @@ void handle_wu(
}
} else {
// here if no consensus.
// Trigger a transition to make more results if needed
//
need_immediate_transition = true;
// check if #success results is too large
//
if (nsuccess_results > wu.max_success_results) {
wu.error_mask |= WU_ERROR_TOO_MANY_SUCCESS_RESULTS;
need_immediate_transition = true;
}
// if #success results == than target_nresults,
@ -420,6 +428,7 @@ void handle_wu(
//
if (nsuccess_results >= wu.target_nresults) {
wu.target_nresults = nsuccess_results+1;
need_immediate_transition = true;
}
}
}
@ -512,11 +521,11 @@ int main(int argc, char** argv) {
} else if (!strcmp(argv[i], "-app")) {
strcpy(app_name, argv[++i]);
} else if (!strcmp(argv[i], "-d")) {
boinc_validator_debuglevel=atoi(argv[++i]);
boinc_validator_debuglevel=atoi(argv[++i]);
log_messages.set_debug_level(boinc_validator_debuglevel);
} else {
log_messages.printf(SCHED_MSG_LOG::CRITICAL, "unrecognized arg: %s\n", argv[i]);
exit(1);
exit(1);
}
}