// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . // Simple validator framework: // Lets you create a custom validator by supplying three functions. // See http://boinc.berkeley.edu/trac/wiki/ValidationSimple // #include "config.h" #include #include #include #include "boinc_db.h" #include "error_numbers.h" #include "sched_config.h" #include "sched_msgs.h" #include "validator.h" #include "validate_util.h" #include "validate_util2.h" using std::vector; // Given a set of results, check for a canonical result, // i.e. a set of at least min_quorum/2+1 results for which // that are equivalent according to check_pair(). // // invariants: // results.size() >= wu.min_quorum // for each result: // result.outcome == SUCCESS // result.validate_state == INIT // int check_set( DB_APP& app, vector& app_versions, vector& results, WORKUNIT& wu, int& canonicalid, double&, bool& retry ) { vector data; vector had_error; int i, j, neq = 0, n, retval; int min_valid = wu.min_quorum/2+1; retry = false; n = results.size(); data.resize(n); had_error.resize(n); // Initialize results for (i=0; i matches; matches.resize(n); neq = 0; for (j=0; j!=n; j++) { if (had_error[j]) continue; bool match = false; if (i == j) { ++neq; matches[j] = true; } else if (compare_results(results[i], data[i], results[j], data[j], match)) { log_messages.printf(MSG_CRITICAL, "generic_check_set: check_pair_with_data([RESULT#%d %s], [RESULT#%d %s]) failed\n", results[i].id, results[i].name, results[j].id, results[j].name ); } else if (match) { ++neq; matches[j] = true; } } if (neq >= min_valid) { // set validate state for each result // for (j=0; j!=n; j++) { if (had_error[j]) continue; if (max_claimed_credit && results[j].claimed_credit > max_claimed_credit) { results[j].validate_state = VALIDATE_STATE_INVALID; } else { results[j].validate_state = matches[j] ? VALIDATE_STATE_VALID : VALIDATE_STATE_INVALID; } } canonicalid = results[i].id; break; } } cleanup: for (i=0; i max_claimed_credit) { r1.validate_state = VALIDATE_STATE_INVALID; } else { r1.validate_state = match?VALIDATE_STATE_VALID:VALIDATE_STATE_INVALID; } cleanup_result(r1, data1); cleanup_result(r2, data2); }