diff --git a/samples/vboxwrapper/vboxwrapper.cpp b/samples/vboxwrapper/vboxwrapper.cpp index 1b8672cdbd921851f4bf1d8538912e89e7a7a1cb..c4345aa6ed694fecdb423f95a086f7d5e1dc17af 100644 --- a/samples/vboxwrapper/vboxwrapper.cpp +++ b/samples/vboxwrapper/vboxwrapper.cpp @@ -76,6 +76,9 @@ using std::vector; using std::string; +double elapsed_time = 0; + // job's total elapsed time (over all sessions) +double trickle_period = 0; bool is_boinc_client_version_newer(APP_INIT_DATA& aid, int maj, int min, int rel) { if (maj < aid.major_version) return true; @@ -437,6 +440,37 @@ void VBOX_VM::check_trickle_triggers() { } } +// see if it's time to send trickle-up reporting elapsed time +// +void check_trickle_period() { + char buf[256]; + static double last_trickle_report_time = 0; + + if ((elapsed_time - last_trickle_report_time) < trickle_period) { + return; + } + last_trickle_report_time = elapsed_time; + fprintf( + stderr, + "%s Status Report: Trickle-Up Event.\n", + vboxwrapper_msg_prefix(buf, sizeof(buf)) + ); + sprintf(buf, + "<cpu_time>%f</cpu_time>", last_trickle_report_time + ); + int retval = boinc_send_trickle_up( + const_cast<char*>("cpu_time"), buf + ); + if (retval) { + fprintf( + stderr, + "%s Sending Trickle-Up Event failed (%d).\n", + vboxwrapper_msg_prefix(buf, sizeof(buf)), + retval + ); + } +} + int main(int argc, char** argv) { int retval; int loop_iteration = 0; @@ -444,14 +478,11 @@ int main(int argc, char** argv) { VBOX_VM vm; APP_INIT_DATA aid; double random_checkpoint_factor = 0; - double elapsed_time = 0; - double trickle_period = 0; double fraction_done = 0; double current_cpu_time = 0; double starting_cpu_time = 0; double last_checkpoint_time = 0; double last_status_report_time = 0; - double last_trickle_report_time = 0; double stopwatch_starttime = 0; double stopwatch_endtime = 0; double stopwatch_elapsedtime = 0; @@ -487,9 +518,6 @@ int main(int argc, char** argv) { boinc_options.main_program = true; boinc_options.check_heartbeat = true; boinc_options.handle_process_control = true; - if (trickle_period > 0.0) { - boinc_options.handle_trickle_ups = true; - } boinc_init_options(&boinc_options); // Prepare environment for detecting system conditions @@ -1183,29 +1211,10 @@ int main(int argc, char** argv) { } } + // send elapsed-time trickle message if needed + // if (trickle_period) { - if ((elapsed_time - last_trickle_report_time) >= trickle_period) { - last_trickle_report_time = elapsed_time; - fprintf( - stderr, - "%s Status Report: Trickle-Up Event.\n", - vboxwrapper_msg_prefix(buf, sizeof(buf)) - ); - sprintf(buf, - "<cpu_time>%f</cpu_time>", last_trickle_report_time - ); - retval = boinc_send_trickle_up( - const_cast<char*>("cpu_time"), buf - ); - if (retval) { - fprintf( - stderr, - "%s Sending Trickle-Up Event failed (%d).\n", - vboxwrapper_msg_prefix(buf, sizeof(buf)), - retval - ); - } - } + check_trickle_period(); } if (boinc_status.reread_init_data_file) { diff --git a/samples/wrapper/wrapper.cpp b/samples/wrapper/wrapper.cpp index e2d86250926fe3ecfd23a83b732a18f4db3ae649..39ed9586fa69ba292ef434da847171d44441bf73 100644 --- a/samples/wrapper/wrapper.cpp +++ b/samples/wrapper/wrapper.cpp @@ -15,8 +15,17 @@ // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see <http://www.gnu.org/licenses/>. -// wrapper.cpp -// wrapper program - lets you use non-BOINC apps with BOINC +// BOINC wrapper - lets you use non-BOINC apps with BOINC +// See http://boinc.berkeley.edu/trac/wiki/WrapperApp +// +// cmdline options: +// --device N macro-substitute N for $GPU_DEVICE_NUM +// in worker cmdlines and env values +// --nthreads X macro-substitute X for $NTHREADS +// in worker cmdlines and env values +// --trickle X send a trickle-up message reporting elapsed time every X sec +// (use this for credit granting if your app does its +// own job management) // // Handles: // - suspend/resume/quit/abort @@ -25,14 +34,6 @@ // - checkpointing // (at the level of task; or potentially within task) // -// See http://boinc.berkeley.edu/trac/wiki/WrapperApp for details -// -// cmdline options: -// --nthreads X: macro-substitute X for $NTHREADS -// in worker cmdlines and env values -// --device N: macro-substitute N for $GPU_DEVICE_NUM -// in worker cmdlines and env values -// // Contributor: Andrew J. Younge (ajy4490@umiacs.umd.edu) #ifndef _WIN32 @@ -74,6 +75,9 @@ #include "regexp.h" +using std::vector; +using std::string; + //#define DEBUG #if 1 #define debug_msg(x) @@ -88,10 +92,15 @@ inline void debug_msg(const char* x) { #define POLL_PERIOD 1.0 -using std::vector; -using std::string; int nthreads = 1; int gpu_device_num = -1; +double runtime = 0; + // run time this session +double trickle_period = 0; +vector<string> unzip_filenames; +string zip_filename; +vector<regexp*> zip_patterns; +APP_INIT_DATA aid; struct TASK { string application; @@ -220,10 +229,6 @@ struct TASK { vector<TASK> tasks; vector<TASK> daemons; -vector<string> unzip_filenames; -string zip_filename; -vector<regexp*> zip_patterns; -APP_INIT_DATA aid; // replace s1 with s2 // @@ -931,32 +936,51 @@ void poll_boinc_messages(TASK& task) { } } +// see if it's time to send trickle-up reporting elapsed time +// +void check_trickle_period() { + char buf[256]; + static double last_trickle_report_time = 0; + + if ((runtime - last_trickle_report_time) < trickle_period) { + return; + } + last_trickle_report_time = runtime; + sprintf(buf, + "<cpu_time>%f</cpu_time>", last_trickle_report_time + ); + boinc_send_trickle_up( + const_cast<char*>("cpu_time"), buf + ); +} + // Support for multiple tasks. // We keep a checkpoint file that says how many tasks we've completed -// and how much CPU time has been used so far +// and how much CPU time and runtime has been used so far // -void write_checkpoint(int ntasks_completed, double cpu) { +void write_checkpoint(int ntasks_completed, double cpu, double rt) { boinc_begin_critical_section(); FILE* f = fopen(CHECKPOINT_FILENAME, "w"); if (!f) return; - fprintf(f, "%d %f\n", ntasks_completed, cpu); + fprintf(f, "%d %f %f\n", ntasks_completed, cpu, rt); fclose(f); boinc_checkpoint_completed(); } -int read_checkpoint(int& ntasks_completed, double& cpu) { +int read_checkpoint(int& ntasks_completed, double& cpu, double& rt) { int nt; - double c; + double c, r; ntasks_completed = 0; cpu = 0; FILE* f = fopen(CHECKPOINT_FILENAME, "r"); if (!f) return ERR_FOPEN; - int n = fscanf(f, "%d %lf", &nt, &c); + int n = fscanf(f, "%d %lf %lf", &nt, &c, &r); fclose(f); if (n != 2) return 0; ntasks_completed = nt; cpu = c; + rt = r; return 0; } @@ -978,6 +1002,8 @@ int main(int argc, char** argv) { nthreads = atoi(argv[++j]); } else if (!strcmp(argv[j], "--device")) { gpu_device_num = atoi(argv[++j]); + } else if (!strcmp(argv[j], "--trickle")) { + trickle_period = atof(argv[++j]); } } @@ -992,14 +1018,14 @@ int main(int argc, char** argv) { do_unzip_inputs(); - retval = read_checkpoint(ntasks_completed, checkpoint_cpu_time); + retval = read_checkpoint(ntasks_completed, checkpoint_cpu_time, runtime); if (retval && !zip_filename.empty()) { // this is the first time we've run. // If we're going to zip output files, // make a list of files present at this point // so we can exclude them. // - write_checkpoint(0, 0); + write_checkpoint(0, 0, 0); get_initial_file_list(); } @@ -1109,11 +1135,17 @@ int main(int argc, char** argv) { if (task.has_checkpointed()) { cpu_time = task.cpu_time(); checkpoint_cpu_time = task.starting_cpu + cpu_time; - write_checkpoint(i, checkpoint_cpu_time); + write_checkpoint(i, checkpoint_cpu_time, runtime); } + + if (trickle_period) { + check_trickle_period(); + } + boinc_sleep(POLL_PERIOD); if (!task.suspended) { task.elapsed_time += POLL_PERIOD; + runtime += POLL_PERIOD; } counter++; } @@ -1131,7 +1163,7 @@ int main(int argc, char** argv) { checkpoint_cpu_time, frac_done + task.weight/total_weight ); - write_checkpoint(i+1, checkpoint_cpu_time); + write_checkpoint(i+1, checkpoint_cpu_time, runtime); weight_completed += task.weight; } kill_daemons();