// result_retry - create new results to make up for lost ones // // result_retry // -app appname // [ -nerror n ] if get this many errors, bail on WU // [ -ndet n ] if get this results w/o consensus, bail // [ -nredundancy n ] try to get at least this many done results // [ -asynch ] be asynchronous using namespace std; #include #include #include #include "db.h" #include "backend_lib.h" #include "config.h" int max_errors = 999; int max_done = 999; int nredundancy = 0; int startup_time; CONFIG config; R_RSA_PRIVATE_KEY key; char app_name[256]; // The scheme for generating unique output filenames is as follows. // If the original filename is of the form x__y, // then y is replaced with a string of the form time_seqno, // where "time" is when this program started up. // NOTE: if you ever need to start up multiple copies of this, // you'll need to add a PID in there somewhere. // // If the original filename doesn't have __, add a string // of the form __time_seqno void make_unique_name(char* name) { char buf[256], *p; static int seqno; sprintf(buf, "%d_%d", startup_time, seqno++); p = strstr(name, "__"); if (p) { strcpy(p+2, buf); } else { strcat(name, "__"); strcat(name, buf); } } // convert a result's XML document to generate new output filenames. // The input has the form // // xxx // ... // // ... // // // xxx // ... // // ... // // // Look for ... elements within // and make a unique name based on it; // apply the same conversion to the element later on. // // TODO: this is ad-hoc. Would be nice to use some generic // XML parsing routines, or XSLT or something. // int assign_new_names(char* in) { char *p = in, *n1, *n2, *r; char name[256], newname[256], element[256], buf[MAX_BLOB_SIZE]; int len; // notice where the is so we don't try to convert // the result name // r = strstr(in, ""); while (1) { n1 = strstr(p, ""); if (!n1) break; if (n1 > r) break; // don't go past n1 += strlen(""); n2 = strstr(p, ""); if (!n2) { fprintf(stderr, "assign_new_names(): malformed XML:\n%s", in); return 1; } len = n2 - n1; memcpy(name, n1, len); name[len] = 0; strcpy(newname, name); make_unique_name(newname); strcpy(buf, n2); strcpy(n1, newname); strcat(n1, buf); // replace the name in the element // sprintf(element, "%s", name); n2 = strstr(n1, element); if (!n2) { fprintf(stderr, "assign_new_names(): no :\n%s", in); return 1; } strcpy(buf, n2+strlen(element)); sprintf(element, "%s", newname); strcpy(n2, element); strcat(n2, buf); p = n1; } return 0; } bool do_pass(APP& app) { WORKUNIT wu; RESULT result; int nerrors, ndone, retval; unsigned int i, n; bool did_something = false; wu.retry_check_time = time(0); wu.appid = app.id; // loop over WUs that are due to be checked // while (!db_workunit_enum_retry_check_time(wu)) { vector results; did_something = true; // if this WU has a canonical result, we're done // (this normally doesn't happen since the retry check time // is zeroed when canonical result found, but just in case). // if (wu.canonical_resultid) { wu.retry_check_time = 0; goto update_wu; } // enumerate all the results for the WU // result.workunitid = wu.id; while (!db_result_enum_wuid(result)) { results.push_back(result); } nerrors = 0; ndone = 0; for (i=0; i max_errors) { fprintf(stderr, "WU %s has too many errors\n", wu.name); wu.state = WU_STATE_TOO_MANY_ERRORS; wu.retry_check_time = 0; goto update_wu; } if (ndone > max_done) { fprintf(stderr, "WU %s has too many answers\n", wu.name); wu.state = WU_STATE_TOO_MANY_DONE; wu.retry_check_time = 0; goto update_wu; } // Generate new results if needed. // Munge the XML of an existing result // to create unique new output filenames. // if (nredundancy > ndone) { n = nredundancy - ndone; for (i=0; i