| 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 | }}} |