/***********************************************************************\ * The Jack LaLane Program, to completely exercise the BOINC API :-) * * (Graphics routines are now in the separate files lalane_gfx.C * and eah_poster.C) * * Eric Myers - 9 July 2004 * @(#) This is (probably) version 5.02 of 14 August 2006 \***********************************************************************/ #ifdef _WIN32 #include "boinc_win.h" #endif /* General BOINC API: */ #include "boinc_api.h" // #include "filesys.h" // boinc_fopen(), etc... #include "app_ipc.h" // #include "util.h" // parse_command_line(), boinc_sleep(), dtime() #include "diagnostics.h" #include "mfile.h" #include "version.h" // for BOINC versions #ifdef BOINC_APP_GRAPHICS # include "graphics_api.h" #endif /* Settings for this app: */ #define TIME_LIMIT 60*20 // approx length of the job/display, in sec #define POSTER_TIME 47 // time to display poster (in sec) #define CHECKPOINT_FILE "ckpt_state" // checkpoint/state file /* Globals, prototypes: */ double start_time; double stop_time; APP_INIT_DATA user_data; // User/host data structure HOST_INFO host_data; // Host data structure #ifdef BOINC_APP_GRAPHICS extern bool gfx_inited; // did the graphics start? extern bool is_ending; // signal to wrap it up and display poster #endif int do_checkpoint(int i); // checkpointing void do_work(); // computation thread int main(int argc, char **argv) { int rc; start_time = dtime(); // punch the clock first! /* Before initializing BOINC itself, intialize diagnostics so as to get stderr output, etc.. */ boinc_init_diagnostics(BOINC_DIAG_REDIRECTSTDERR| BOINC_DIAG_TRACETOSTDERR| BOINC_DIAG_DUMPCALLSTACKENABLED| BOINC_DIAG_MEMORYLEAKCHECKENABLED); fprintf(stderr, "main: compiled with BOINC version %d.%2d.\n", BOINC_MAJOR_VERSION, BOINC_MINOR_VERSION); fflush(NULL); // make sure we can see this all soon /* BOINC changed the graphics API call at version 4.52 to use * either boinc_init_graphics(worker) for graphical apps or * boinc_init() for non-graphical apps, but not both. */ #ifdef BOINC_APP_GRAPHICS rc = boinc_init_graphics(do_work); /***************************************************************\ * At this point the app_graphics_render() routine will re-draw * the screen as needed until the worker calls boinc_finish(). * The call to boinc_init_graphics() should only return on error. \***************************************************************/ if (rc) { fprintf(stderr,"APP: boinc_init_graphics(do_work) failed.\n"); boinc_finish(rc); } else { fprintf(stderr,"APP: ALL DONE (this should never print)\n"); exit(47); } #else // not BOINC_APP_GRAPHICS /* or we were compiled with graphics turned off, so note that fact */ fprintf(stderr,"main: graphics NOT enabled for this app.\n"); rc = boinc_init(); if (rc){ fprintf(stderr, "main: boinc_init() failed.\n"); boinc_finish(rc); } // ...and do the work (should not return) do_work(); exit(47); // should never get here #endif // BOINC_APP_GRAPHICS } /*************************************************** * Computation thread: the calculations are done by a separate function, * the "worker thread" function which was named to boinc_graphics_init() * if graphics are used, or otherwise invoked at the end of main(). */ void do_work() { FILE *state; FILE *f; unsigned long flags=0; int rc, i, i_start=0; char out_path[512], ckpt_path[512]; double cpu_time, frac_done; // Open an output file and write to it... rc = boinc_resolve_filename("out.txt", out_path, sizeof(out_path)); if (rc){ fprintf(stderr, "worker: cannot resolve output file name.\n"); exit(boinc_finish(rc)); } f = boinc_fopen(out_path, "a"); fprintf(f, "Hello, BOINC World!\n===================\n\n"); /** * Look for a checkpoint file. If it exists, then we have been * restarted, so read in the file and pick up where we left off. * If it does not exist then we are starting from scratch. */ boinc_resolve_filename(CHECKPOINT_FILE, ckpt_path, sizeof(ckpt_path)); state = boinc_fopen(ckpt_path, "r"); if (state){ // Exists: restarting fscanf(state, "%d",&i_start); fprintf(stderr,"worker: restarting at %d \n", i_start); } else{ // Not exist: start at the begining fprintf(stderr,"worker: Starting from scratch. \n"); } // User and Workunit information from the Core Client (from init_data.xml) fprintf(stderr,"worker: trying boinc_get_init_data()...\n"); rc = boinc_get_init_data(user_data); fprintf(f,"User: %s \t\t", user_data.user_name); fprintf(f,"Auth: %s \n", user_data.authenticator); fprintf(f,"Team: %s \n\n", user_data.team_name); fprintf(f,"Project Dir: %s \n", user_data.project_dir); fprintf(f,"BOINC Dir: %s \n", user_data.boinc_dir); fprintf(f,"\n"); fprintf(f,"Total Credit:\t %f\n", user_data.user_total_credit); fprintf(f,"Avg Credit:\t %f\n", user_data.user_expavg_credit); fprintf(f,"Host Credit:\t %f\n", user_data.host_total_credit); fprintf(f,"Host Avg: \t %f\n", user_data.host_expavg_credit); fprintf(f,"\n"); fprintf(f,"APP Name: %s \n", user_data.app_name); fprintf(f,"WU Name: %s \n", user_data.wu_name); fprintf(f,"Slot: %d \n", user_data.slot); fprintf(f,"\n================\n"); /* Now host data from HOST_INFO struct */ host_data = user_data.host_info; fprintf(f,"APP OS Name: %s \n", host_data.os_name); /** * Main Loop: wait a while, so we can see the graphics */ for(i=i_start;i (double) TIME_LIMIT ) break; if( cpu_time > 120 && ! gfx_inited ) break; }// end main loop #ifdef BOINC_APP_GRAPHICS /******************************* * Finishing up... show poster for POSTER_TIME * * Setting is_ending=true signals the graphics thread that it is * time to stop doing the animation and instead show the poster * (this is not checkpointed so it has to finish, and it does not update * the progress bar). Only do this if graphics have been in use. */ if(gfx_inited){ fprintf(stderr, "worker: begining of the end - poster display begins...\n"); is_ending=true; /* some more stalling while the picture is visible */ stop_time = dtime() + POSTER_TIME ; while( dtime() < stop_time ){ int j; double num; for (j=0;j<12345678;j++){ num = rand() * 3.14159; } } fprintf(stderr, "worker: end of the end - poster display is done..\n"); } #endif /******************************* * Record time we've used and finish up */ stop_time = dtime(); rc = boinc_wu_cpu_time(cpu_time); if ( !rc ) { fprintf(f, " CPU is %f seconds\n", cpu_time); } else { fprintf(stderr, "worker: can't get CPU time. rc=%d \n", rc); } fprintf(stderr,"worker: CPU time: %f seconds, Wall clock time: %f seconds\n", cpu_time, (stop_time-start_time)); if(gfx_inited) { fprintf(stderr,"worker: graphics WERE initialized.\n"); } else { fprintf(stderr,"worker: graphics NEVER initialzed!\n"); } /* Put secret passphrase in the output for the validator */ fprintf(f, "\nBlow me down!\n"); /* close the output file when done with it */ fclose(f); /* report that we are finished to the stderr log too */ fprintf(stderr,"worker: all done\nBlow me down!\n"); fflush(NULL); // worker calls boinc_finish() to report that it is done boinc_finish(0); } #ifdef _WIN32 /*************************************************** * Windows: Unix applications begin with main() while Windows applications * begin with WinMain, so this just makes WinMain() process the command * line and invoke main() */ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode) { LPSTR command_line; char* argv[100]; int argc; command_line = GetCommandLine(); argc = parse_command_line( command_line, argv ); return main(argc, argv); } #endif /*************************************************** * Checkpointing: write the current count to the state file */ int do_checkpoint(int i){ FILE* state; char ckpt_path[512]; boinc_resolve_filename(CHECKPOINT_FILE, ckpt_path, sizeof(ckpt_path)); state = boinc_fopen(ckpt_path, "w"); if (!state){ fprintf(stderr,"do_checkpoint: Cannot open checkpoint file to write! \n"); return (1); } else{ fprintf(state," %d \n", i); // save the count fclose(state); // close the file fflush(NULL); // flush all output streams boinc_checkpoint_completed(); // register checkpoint is complete return (0); } } //EOF