// Send this host any broadcast jobs. // Return true iff we sent anything // bool send_broadcast_jobs() { DB_RESULT result; int retval; char buf[256]; bool sent_something = false; for (int i=0; i<ssp->nassignments; i++) { ASSIGNMENT& asg = ssp->assignments[i]; if (config.debug_assignment) { log_messages.printf(MSG_NORMAL, "[assign] processing broadcast type %d\n", asg.target_type ); } // see if this assignment applies to this host // switch (asg.target_type) { case ASSIGN_NONE: sprintf(buf, "where hostid=%lu and workunitid=%lu", g_reply->host.id, asg.workunitid ); retval = result.lookup(buf); if (retval == ERR_DB_NOT_FOUND) { retval = send_assigned_job(asg); if (!retval) sent_something = true; } break; case ASSIGN_USER: if (g_reply->user.id != asg.target_id) continue; sprintf(buf, "where workunitid=%lu and hostid=%lu", asg.workunitid, g_reply->host.id ); retval = result.lookup(buf); if (retval == ERR_DB_NOT_FOUND) { retval = send_assigned_job(asg); if (!retval) sent_something = true; } break; case ASSIGN_TEAM: if (g_reply->team.id != asg.target_id) continue; sprintf(buf, "where workunitid=%lu and hostid=%lu", asg.workunitid, g_reply->host.id ); retval = result.lookup(buf); if (retval == ERR_DB_NOT_FOUND) { retval = send_assigned_job(asg); if (!retval) sent_something = true; } break; } } return sent_something; }
// Find a file with work, and send. // This is guaranteed to send work if ANY is available for this user. // However, it ignores the working set, // and should be done only if we fail to send work from the working set. // // logic: // min_resultname = "" // loop // R = first unsent result where filename>min_resultname order by filename // // order by filename implies order by ID // send_results_for_file(R.filename) // // this skips disqualified results // min_resultname = R.filename; // static int send_new_file_work_deterministic_seeded( int& nsent, const char *start_f, const char *end_f ) { DB_RESULT result; char filename[256], min_resultname[256], query[1024]; int retval; if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] send_new_file_work_deterministic_seeded() start=%s end=%s\n", start_f, end_f?end_f:"+Inf" ); } strcpy(min_resultname, start_f); while (1) { // are we done with the search yet? if (end_f && strcmp(min_resultname, end_f)>=0) break; #if 0 // an alternative here is to add ANOTHER index on name, server_state // to the result table. sprintf(query, "where server_state=%d and name>'%s' order by name limit 1", RESULT_SERVER_STATE_UNSENT, min_resultname ); #endif sprintf(query, "where name>'%s' order by name limit 1", min_resultname ); retval = result.lookup(query); if (retval) break; // no more unsent results or at the end of the filenames, return -1 retval = extract_filename(result.name, filename); if (retval) return retval; // not locality scheduled, now what??? if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] send_new_file_work_deterministic will try filename %s\n", filename ); } retval = send_results_for_file(filename, nsent, false); if (retval==ERR_NO_APP_VERSION || retval==ERR_INSUFFICIENT_RESOURCE) return retval; if (nsent>0 || !work_needed(true)) break; // construct a name which is lexically greater than the name of any result // which uses this file. sprintf(min_resultname, "%s__~", filename); } return 0; }
// send non-multi assigned jobs // bool send_assigned_jobs() { DB_ASSIGNMENT asg; DB_RESULT result; DB_WORKUNIT wu; bool sent_something = false; int retval; // for now, only look for user assignments // char buf[256]; sprintf(buf, "where target_type=%d and target_id=%d and multi=0", ASSIGN_USER, g_reply->user.id ); while (!asg.enumerate(buf)) { if (!work_needed(false)) continue; // if the WU doesn't exist, delete the assignment record. // retval = wu.lookup_id(asg.workunitid); if (retval) { asg.delete_from_db(); continue; } // don't send if WU is validation pending or completed, // or has transition pending // if (wu.need_validate) continue; if (wu.canonical_resultid) continue; if (wu.transition_time < time(0)) continue; // don't send if we already sent one to this host // sprintf(buf, "where workunitid=%d and hostid=%d", asg.workunitid, g_request->host.id ); retval = result.lookup(buf); if (retval != ERR_DB_NOT_FOUND) continue; // don't send if there's already one in progress to this user // sprintf(buf, "where workunitid=%d and userid=%d and server_state=%d", asg.workunitid, g_reply->user.id, RESULT_SERVER_STATE_IN_PROGRESS ); retval = result.lookup(buf); if (retval != ERR_DB_NOT_FOUND) continue; // OK, send the job // retval = send_assigned_job(asg); if (retval) continue; sent_something = true; // update the WU's transition time to time out this job // retval = wu.lookup_id(asg.workunitid); if (retval) continue; int new_tt = time(0) + wu.delay_bound; if (new_tt < wu.transition_time) { char buf2[256]; sprintf(buf2, "transition_time=%d", new_tt); wu.update_field(buf2); } } return sent_something; }
// try to send jobs for non-CPU-intensive (NCI) apps // for which the host doesn't have a job in progress // int send_nci() { int retval; vector<APP> nci_apps; char buf[1024]; if (config.debug_send) { log_messages.printf(MSG_NORMAL, "checking for NCI jobs\n"); } // make a vector of NCI apps // for (int i=0; i<ssp->napps; i++) { if (!ssp->apps[i].non_cpu_intensive) continue; APP app = ssp->apps[i]; app.have_job = false; nci_apps.push_back(app); } // scan through the list of in-progress jobs, // flagging the associated apps as having jobs // for (unsigned int i=0; i<g_request->other_results.size(); i++) { DB_RESULT r; OTHER_RESULT &ores = g_request->other_results[i]; sprintf(buf, "where name='%s'", ores.name); retval = r.lookup(buf); if (retval) { log_messages.printf(MSG_NORMAL, "No such result: %s\n", ores.name); continue; } for (unsigned int j=0; j<nci_apps.size(); j++) { APP& app = nci_apps[j]; if (app.id == r.appid) { app.have_job = true; break; } } } // For each NCI app w/o a job, try to send one // for (unsigned int i=0; i<nci_apps.size(); i++) { APP& app = nci_apps[i]; if (app.have_job) { if (config.debug_send) { log_messages.printf(MSG_NORMAL, "Already have job for %s\n", app.name ); } continue; } if (app.beta && !g_wreq->project_prefs.allow_beta_work) { if (config.debug_send) { log_messages.printf(MSG_NORMAL, "%s is beta\n", app.name); } continue; } if (app_not_selected(app.id)) { if (!g_wreq->project_prefs.allow_non_preferred_apps) { if (config.debug_send) { log_messages.printf(MSG_NORMAL, "%s is not selected\n", app.name ); } continue; } } retval = send_job_for_app(app); if (retval) { log_messages.printf(MSG_NORMAL, "failed to send job for NCI app %s\n", app.user_friendly_name ); } } return 0; }
// DAVID, this is missing a return value! Am I right that this will // also eventually move 'non locality' work through and out of the // system? // // This looks for work created in the range t_min < t < t_max. Use // t_min=INT_MIN if you wish to leave off the left constraint. // static int send_old_work(int t_min, int t_max) { char buf[1024], filename[256]; int retval, extract_retval, nsent; DB_RESULT result; int now=time(0); if (!work_needed(true)) { return 0; } boinc_db.start_transaction(); if (t_min != INT_MIN) { sprintf(buf, "where server_state=%d and %d<create_time and create_time<%d limit 1", RESULT_SERVER_STATE_UNSENT, t_min, t_max ); } else { sprintf(buf, "where server_state=%d and create_time<%d limit 1", RESULT_SERVER_STATE_UNSENT, t_max ); } retval = result.lookup(buf); if (!retval) { retval = possibly_send_result(result); boinc_db.commit_transaction(); if (!retval) { double age=(now-result.create_time)/3600.0; if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] send_old_work(%s) sent result created %.1f hours ago [RESULT#%d]\n", result.name, age, result.id ); } extract_retval=extract_filename(result.name, filename); if (!extract_retval) { send_results_for_file(filename, nsent, false); } else { // David, is this right? Is this the only place in // the locality scheduler that non-locality work // // gets done? if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] Note: sent NON-LOCALITY result %s\n", result.name ); } } } else if (retval == ERR_NO_APP_VERSION || retval==ERR_INSUFFICIENT_RESOURCE) { // if no app version found or no resources, give up completely! return retval; } } else { boinc_db.commit_transaction(); } if (retval) { double older=(now-t_max)/3600.0; if (t_min != INT_MIN) { double young=(now-t_min)/3600.0; if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] send_old_work() no feasible result younger than %.1f hours and older than %.1f hours\n", young, older ); } } else { if (config.debug_locality) { log_messages.printf(MSG_NORMAL, "[locality] send_old_work() no feasible result older than %.1f hours\n", older ); } } } // DAVID, YOU CHANGED THIS FROM VOID TO INT. IS THIS THE RIGHT // RETURN VAL? You should probably use the return value from // sent_results_for_file as well. return retval; }