int main(int argc, char** argv) { DB_RESULT result; char clause[256]; int retval, n, nerr; for(int c = 1; c < argc; c++) { std::string option(argv[c]); if(option == "-h" || option == "--help") { usage(argv[0]); exit(0); } else if(option == "-v" || option == "--version") { printf("%s\n", SVN_VERSION); exit(0); } else if (option == "--repair") { repair = true; } else { fprintf(stderr, "unknown command line argument: %s\n\n", argv[c]); usage(argv[0]); exit(1); } } retval = config.parse_file(); if (retval) exit(1); retval = boinc_db.open( config.db_name, config.db_host, config.db_user, config.db_passwd ); if (retval) { printf("boinc_db.open: %s\n", boincerror(retval)); exit(1); } n = nerr = 0; printf("Unsent results:\n"); sprintf(clause, "where server_state=%d", RESULT_SERVER_STATE_UNSENT); while (!result.enumerate(clause)) { retval = handle_result(result); n++; if (retval) nerr++; } printf("%d out of %d errors\n", nerr, n); n = nerr = 0; printf("In progress results:\n"); sprintf(clause, "where server_state=%d", RESULT_SERVER_STATE_IN_PROGRESS); while (!result.enumerate(clause)) { retval = handle_result(result); n++; if (retval) nerr++; } printf("%d out of %d errors\n", nerr, n); }
// Called when there's evidence that the host has detached. // Mark in-progress results for the given host // as server state OVER, outcome CLIENT_DETACHED. // This serves two purposes: // 1) make sure we don't resend these results to the host // (they may be the reason the user detached) // 2) trigger the generation of new results for these WUs // static void mark_results_over(DB_HOST& host) { char buf[256], buf2[256]; DB_RESULT result; sprintf(buf, "where hostid=%d and server_state=%d", host.id, RESULT_SERVER_STATE_IN_PROGRESS ); while (!result.enumerate(buf)) { sprintf(buf2, "server_state=%d, outcome=%d, received_time = %ld", RESULT_SERVER_STATE_OVER, RESULT_OUTCOME_CLIENT_DETACHED, time(0) ); result.update_field(buf2); // and trigger WU transition // DB_WORKUNIT wu; wu.id = result.workunitid; sprintf(buf2, "transition_time=%d", (int)time(0)); wu.update_field(buf2); log_messages.printf(MSG_CRITICAL, "[HOST#%d] [RESULT#%u] [WU#%u] changed CPID: marking in-progress result %s as client error!\n", host.id, result.id, result.workunitid, result.name ); } }
int purge_and_archive_results(DB_WORKUNIT& wu, int& number_results) { int retval= 0; DB_RESULT result; char buf[256]; number_results=0; sprintf(buf, "where workunitid=%d", wu.id); while (!result.enumerate(buf)) { if (!no_archive) { retval = archive_result(result); if (retval) return retval; log_messages.printf(MSG_DEBUG, "Archived result [%d] to a file\n", result.id ); } if (!dont_delete) { retval = result.delete_from_db(); if (retval) return retval; } log_messages.printf(MSG_DEBUG, "Purged result [%d] from database\n", result.id ); number_results++; } return 0; }
int main() { if ( boinc_db.open("predictor", "boinc", NULL, NULL) ) { printf("Open failed\n"); return 0; } DB_WORKUNIT workunit; char buf[256]; while (!workunit.enumerate()) { printf("workunit %d wsn %d\n", workunit.id, workunit.workseq_next); DB_RESULT result; sprintf(buf, "where workunitid=%d", workunit.id); if ( !result.enumerate(buf) ) { DB_HOST host; sprintf(buf, "where id=%d", result.hostid); if ( !host.enumerate(buf) ) { workunit.workseq_next = OS(host) + CPU(host); if ( workunit.update() ) printf("Update failed!\n"); } } } };
// The workunit is targeted to the host (or user or team). // Decide if we should actually send an instance // bool need_targeted_instance(WORKUNIT& wu, int hostid) { // don't send if WU had error or was canceled // (db_purge will eventually delete WU and assignment records) // if (wu.error_mask) { return false; } // don't send if WU is validation pending or completed, // or has transition pending // if (wu.need_validate) return false; if (wu.canonical_resultid) return false; if (wu.transition_time < time(0)) return false; // See if this WU needs another instance. // This replicates logic in the transitioner // char buf[256]; DB_RESULT result; int nunsent=0, ninprogress=0, nsuccess=0; sprintf(buf, "where workunitid=%lu", wu.id); while (!result.enumerate(buf)) { // send at most 1 instance to a given host // if (result.hostid == hostid) { return false; } switch (result.server_state) { case RESULT_SERVER_STATE_INACTIVE: case RESULT_SERVER_STATE_UNSENT: nunsent++; break; case RESULT_SERVER_STATE_IN_PROGRESS: ninprogress++; break; case RESULT_SERVER_STATE_OVER: if (result.outcome == RESULT_OUTCOME_SUCCESS && result.validate_state != VALIDATE_STATE_INVALID ) { nsuccess++; } break; } } int needed = wu.target_nresults - nunsent - ninprogress - nsuccess; if (needed <= 0) return false; return true; }
// Arrange that further results for this workunit // will be sent only to hosts with the given user ID. // This could be used, for example, so that late workunits // are sent only to cloud or cluster resources // int restrict_wu_to_user(WORKUNIT& _wu, int userid) { DB_RESULT result; DB_ASSIGNMENT asg; DB_WORKUNIT wu; wu = _wu; char buf[256]; int retval; // mark unsent results as DIDNT_NEED // sprintf(buf, "where workunitid=%d and server_state=%d", wu.id, RESULT_SERVER_STATE_UNSENT ); while (!result.enumerate(buf)) { char buf2[256]; sprintf(buf2, "server_state=%d, outcome=%d", RESULT_SERVER_STATE_OVER, RESULT_OUTCOME_DIDNT_NEED ); result.update_field(buf2); } // mark the WU as TRANSITION_NO_NEW_RESULTS // sprintf(buf, "transitioner_flags=%d", TRANSITION_NO_NEW_RESULTS); retval = wu.update_field(buf); if (retval) return retval; // create an assignment record // asg.clear(); asg.create_time = time(0); asg.target_id = userid; asg.target_type = ASSIGN_USER; asg.multi = 0; asg.workunitid = wu.id; retval = asg.insert(); return retval; }
// return true if we changed the file_delete_state of a WU or a result // bool do_pass(bool retry_error) { DB_WORKUNIT wu; DB_RESULT result; bool did_something = false; char buf[256]; char clause[256]; int retval, new_state; check_stop_daemons(); strcpy(clause, ""); if (id_modulus) { sprintf(clause, " and id %% %d = %d ", id_modulus, id_remainder); } if (dont_delete_batches) { strcat(clause, " and batch <= 0 "); } if (appid) { sprintf(buf, " and appid = %d ", appid); strcat(clause, buf); } sprintf(buf, "where file_delete_state=%d %s limit %d", retry_error?FILE_DELETE_ERROR:FILE_DELETE_READY, clause, WUS_PER_ENUM ); while (do_input_files) { retval = wu.enumerate(buf); if (retval) { if (retval != ERR_DB_NOT_FOUND) { log_messages.printf(MSG_DEBUG, "DB connection lost, exiting\n"); exit(0); } break; } if (preserve_wu_files) { retval = 0; } else { retval = wu_delete_files(wu); } if (retval) { new_state = FILE_DELETE_ERROR; log_messages.printf(MSG_CRITICAL, "[WU#%d] file deletion failed: %s\n", wu.id, boincerror(retval) ); } else { new_state = FILE_DELETE_DONE; } if (new_state != wu.file_delete_state) { sprintf(buf, "file_delete_state=%d", new_state); retval = wu.update_field(buf); if (retval) { log_messages.printf(MSG_CRITICAL, "[WU#%d] update failed: %s\n", wu.id, boincerror(retval) ); } else { log_messages.printf(MSG_DEBUG, "[WU#%d] file_delete_state updated\n", wu.id ); did_something = true; } } } sprintf(buf, "where file_delete_state=%d %s limit %d", retry_error?FILE_DELETE_ERROR:FILE_DELETE_READY, clause, RESULTS_PER_ENUM ); while (do_output_files) { retval = result.enumerate(buf); if (retval) { if (retval != ERR_DB_NOT_FOUND) { log_messages.printf(MSG_DEBUG, "DB connection lost, exiting\n"); exit(0); } break; } if (preserve_result_files) { retval = 0; } else { retval = result_delete_files(result); } if (retval) { new_state = FILE_DELETE_ERROR; log_messages.printf(MSG_CRITICAL, "[RESULT#%d] file deletion failed: %s\n", result.id, boincerror(retval) ); } else { new_state = FILE_DELETE_DONE; } if (new_state != result.file_delete_state) { sprintf(buf, "file_delete_state=%d", new_state); retval = result.update_field(buf); if (retval) { log_messages.printf(MSG_CRITICAL, "[RESULT#%d] update failed: %s\n", result.id, boincerror(retval) ); } else { log_messages.printf(MSG_DEBUG, "[RESULT#%d] file_delete_state updated\n", result.id ); did_something = true; } } } return did_something; }