| | 1 | = Simple validator framework = |
| | 2 | |
| | 3 | To create a validator using the simple framework, you must supply four functions: |
| | 4 | {{{ |
| | 5 | extern int init_result(RESULT& result, void*& data); |
| | 6 | }}} |
| | 7 | This takes a result, reads its output file(s), parses them into a memory structure, and returns (via the 'data' argument) a pointer to this structure. It returns: |
| | 8 | |
| | 9 | * Zero on success, |
| | 10 | * ERR_OPENDIR if there was a transient error, e.g. the output file is on a network volume that is not available. The validator will try this result again later. |
| | 11 | * Any other return value indicates a permanent error. Example: an output file is missing, or has a syntax error. The result will be marked as invalid. |
| | 12 | {{{ |
| | 13 | extern int compare_results( |
| | 14 | RESULT& r1, void* data1, RESULT& r2, void* data2, bool& match |
| | 15 | ); |
| | 16 | }}} |
| | 17 | This takes two results and their associated memory structures. It returns (via the 'match' argument) true if the two results are equivalent (within the tolerances of the application). |
| | 18 | {{{ |
| | 19 | extern int cleanup_result(RESULT& r, void* data); |
| | 20 | }}} |
| | 21 | This frees the structure pointed to by data, if it's non-NULL. |
| | 22 | {{{ |
| | 23 | extern double compute_granted_credit(WORKUNIT&, vector<RESULT>& results); |
| | 24 | }}} |
| | 25 | Given a set of results (at least one of which is valid) compute the credit to be granted to all of them. Normally this function simply returns median_mean_credit(results). If [http://boinc.berkeley.edu/tools_work.php credit is specified in the workunit], call get_credit_from_wu(). |
| | 26 | |
| | 27 | You must link these functions with the files validator.C, validate_util.C, and validate_util2.C. The result is your custom validator. |
| | 28 | Example |
| | 29 | Here's an example in which the output file contains an integer and a double. Two results are considered equivalent if the integer is equal and the doubles differ by no more than 0.01. |
| | 30 | |
| | 31 | This example uses [http://boinc.berkeley.edu/backend_util.php utility functions] get_output_file_path() and try_fopen(). |
| | 32 | {{{ |
| | 33 | #include <string> |
| | 34 | #include <vector> |
| | 35 | #include <math.h> |
| | 36 | #include "error_numbers.h" |
| | 37 | #include "boinc_db.h" |
| | 38 | #include "sched_util.h" |
| | 39 | #include "validate_util.h" |
| | 40 | using std::string; |
| | 41 | using std::vector; |
| | 42 | |
| | 43 | struct DATA { |
| | 44 | int i; |
| | 45 | double x; |
| | 46 | }; |
| | 47 | |
| | 48 | int init_result(RESULT const & result, void*& data) { |
| | 49 | FILE* f; |
| | 50 | string path; |
| | 51 | int i, n, retval; |
| | 52 | double x; |
| | 53 | |
| | 54 | retval = get_output_file_path(result, path); |
| | 55 | if (retval) return retval; |
| | 56 | retval = try_fopen(path.c_str(), f, "r"); |
| | 57 | if (retval) return retval; |
| | 58 | n = fscanf(f, "%d %f", &i, &x); |
| | 59 | if (n != 2) return ERR_XML_PARSE; |
| | 60 | DATA* dp = new DATA; |
| | 61 | dp->i = i; |
| | 62 | dp->x = x; |
| | 63 | data = (void*) dp; |
| | 64 | return 0; |
| | 65 | } |
| | 66 | |
| | 67 | int compare_results( |
| | 68 | RESULT& r1, void* _data1, RESULT const& r2, void* _data2, bool& match |
| | 69 | ) { |
| | 70 | DATA* data1 = (DATA*)_data1; |
| | 71 | DATA* data2 = (DATA*)_data2; |
| | 72 | match = true; |
| | 73 | if (data1->i != data2->i) match = false; |
| | 74 | if (fabs(data1->x - data2->x) > 0.01) match = false; |
| | 75 | return 0; |
| | 76 | } |
| | 77 | |
| | 78 | int cleanup_result(RESULT const& r, void* data) { |
| | 79 | if (data) delete (DATA*) data; |
| | 80 | return 0; |
| | 81 | } |
| | 82 | |
| | 83 | double compute_granted_credit(WORKUNIT& wu, vector<RESULT>& results) { |
| | 84 | return median_mean_credit(wu, results); |
| | 85 | } |
| | 86 | |
| | 87 | }}} |