Version 1 (modified by davea, 11 years ago) (diff)


Simple validator framework

To create a validator using the simple framework, you must supply four functions:

extern int init_result(RESULT& result, void*& data);

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:

  • Zero on success,
  • 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.
  • 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.
    extern int compare_results(
        RESULT& r1, void* data1, RESULT& r2, void* data2, bool& match

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).

extern int cleanup_result(RESULT& r, void* data);

This frees the structure pointed to by data, if it's non-NULL.

extern double compute_granted_credit(WORKUNIT&, vector<RESULT>& results);

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 credit is specified in the workunit, call get_credit_from_wu().

You must link these functions with the files validator.C, validate_util.C, and validate_util2.C. The result is your custom validator. Example 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.

This example uses utility functions get_output_file_path() and try_fopen().

#include <string>
#include <vector>
#include <math.h>
#include "error_numbers.h"
#include "boinc_db.h"
#include "sched_util.h"
#include "validate_util.h"
using std::string;
using std::vector;

struct DATA {
    int i;
    double x;

int init_result(RESULT const & result, void*& data) {
    FILE* f;
    string path;
    int i, n, retval;
    double x;

    retval = get_output_file_path(result, path);
    if (retval) return retval;
    retval = try_fopen(path.c_str(), f, "r");
    if (retval) return retval;
    n = fscanf(f, "%d %f", &i, &x);
    if (n != 2) return ERR_XML_PARSE;
    DATA* dp = new DATA;
    dp->i = i;
    dp->x = x;
    data = (void*) dp;
    return 0;

int compare_results(
    RESULT& r1, void* _data1, RESULT const& r2, void* _data2, bool& match
) {
    DATA* data1 = (DATA*)_data1;
    DATA* data2 = (DATA*)_data2;
    match = true;
    if (data1->i != data2->i) match = false;
    if (fabs(data1->x - data2->x) > 0.01) match = false;
    return 0;

int cleanup_result(RESULT const& r, void* data) {
    if (data) delete (DATA*) data;
    return 0;

double compute_granted_credit(WORKUNIT& wu, vector<RESULT>& results) {
    return median_mean_credit(wu, results);