// The contents of this file are subject to the Mozilla Public License // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.mozilla.org/MPL/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations // under the License. // // The Original Code is the Berkeley Open Infrastructure for Network Computing. // // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 // University of California at Berkeley. All Rights Reserved. // // Contributor(s): // // timeout_check - do various time-based tasks // - time out results // - create new results to make up for lost ones // - check for WU error conditions // // timeout_check // -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 "util.h" #include "backend_lib.h" #include "config.h" #define TRIGGER_FILENAME "stop_server" #define LOCKFILE "result_retry.out" 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]; void check_trigger() { FILE* f = fopen(TRIGGER_FILENAME, "r"); if (!f) return; exit(0); } void write_log(char* p) { time_t now = time(0); char* timestr = ctime(&now); *(strchr(timestr, '\n')) = 0; fprintf(stderr, "%s: %s", timestr, p); } // 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) { sprintf(buf, "assign_new_names(): malformed XML:\n%s", in); write_log(buf); 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) { sprintf(buf, "assign_new_names(): no :\n%s", in); write_log(buf); return 1; } strcpy(buf, n2+strlen(element)); sprintf(element, "%s", newname); strcpy(n2, element); strcat(n2, buf); p = n1; } return 0; } void handle_wu(WORKUNIT& wu) { vector results; RESULT result; int nerrors, ndone, retval; unsigned int i, n; char buf[256]; unsigned int now = time(0); bool wu_error = false, all_over; // scan 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) { sprintf(buf, "WU %s has too many errors\n", wu.name); write_log(buf); wu.error_mask |= WU_ERROR_TOO_MANY_ERROR_RESULTS; wu_error = true; } if (ndone > max_done) { sprintf(buf, "WU %s has too many answers\n", wu.name); write_log(buf); wu.error_mask |= WU_ERROR_TOO_MANY_RESULTS; wu_error = true; } // if this WU had an error, don't send any unsent results // if (wu_error) { for (i=0; i ndone) { n = nredundancy - ndone; for (i=0; i