diff --git a/TODO b/TODO index 29742b3874..7ee9bf9ec7 100644 --- a/TODO +++ b/TODO @@ -1,54 +1,41 @@ -- test environment-var mechanism - -- design alpha/beta/prod mechanism for core and apps - Should have flag in host record - (maybe separate flags for core/app). - Project should control which hosts are alpha/beta. - Test. - -- include shared memory allocation with key data values (current running projects, est. time, etc) to allow easier development of third party addons (Eric) +HIGH-PRIORITY (must be done to support SETI@home) - test versioning mechanisms for core - message, deprecation + send messages if either + 1) some WU couldn't be sent because core is too old + 2) no WUs could be sent because core is too old - test incompatible-core mechanism for apps + same as above? - test reporting of app errors -- test sticky files - - test checksumming of executables -- test on a multiprocessor - -- mechanism for returning app stderr output to server? store in blob? - -- define logging system on client - - proxy support -- put core client version in client state file - - add country, postal code to user collect on login - implement scheme for distributing scheduling server addresses - each project provides a URL for file with list of address, + each project provides a URL for file with list of scheduler address, and email address of "problems" contact -- server-side estimates of WU time requirements - - DB entry for WU has int/FP/RAM/disk/net +- implement and test hi/lo water mark scheme + - core client must estimate how much work it has left, + based on %done (if available) and time estimates -- server sends only feasible WUs - - limit by RAM, disk - - test +- CPU accounting in the presence of checkpoint/restart + core client periodically gets CPU time, accumulates in state file -- review and complete documentation +- scalable/efficient server architecture: alternatives + use our own process framework, shared memory for result/WU lists + use fast CGI w/ shared mem -- define a notion of "app preferences": arbitrary XML edited on server, - passed to app client. - This could be used to e.g. select a color scheme for graphics - Could pass entire prefs? +- measure hardware parameters: CPU speed, #CPUs, memory, disk + - define CPU benchmarks + - do this for other platforms + - Get info periodically rather than always at startup - core client / app trigger file interface core->app @@ -86,12 +73,66 @@ capable of offscreen drawing. OpenGL version? -- CPU accounting in the presence of checkpoint/restart - core client periodically gets CPU time, accumulates in state file +- GUI and screensaver around core client + design default (core client) display + screensaver options + move around screen? + system tray icon behavior -- hi/lo water mark scheme - - core client must estimate how much work it has left, - based on %done (if available) and time estimates + +- get idle-only behavior without screensaver + +- Network retry policies + can't download file: when to give up? how to retry? + exponential backoff + can't upload file: when to give up/retry? + can't connect to sched server + error return from sched server + +- sched server should return total credit info (user, team?) + could display in default core client display + +- edit user account + +- team system +-------------------------- +MEDIUM-PRIORITY (must be done for CM) + +- review and complete documentation + +- test sticky files + +- test multiple-file applications + change add.C to support multi-file applications + +- implement WU/result sequences + +-------------------------- +LOW-PRIORITY + +- implement checkpoint/restart for file transfers + use features of HTTP 1.1 + Return an error to server if transfer fails + (store in DB in server) + +- implement and test the batch mechanism + +- test environment-var mechanism + +- test alpha/beta/prod for apps + +- test on a multiprocessor + +- define logging system on client + +- server-side estimates of WU time requirements + - DB entry for WU has int/FP/RAM/disk/net + +- server sends only feasible WUs + - limit by RAM, disk + - test + +- implement file upload/download requests - preferences finish PHP web interface @@ -107,52 +148,24 @@ implement in client control over priorities? -- scalable/efficient server architecture: alternatives - use our own process framework, shared memory for result/WU lists - use fast CGI w/ shared mem - -- add size to FILE_INFO - server, client sides - -- implement checkpoint/restart for file transfers - use features of HTTP 1.1 - -- measure bandwidth on each network xfer - maintain exponential average, weighted by #bytes xferred - -- measure hardware parameters: CPU speed, #CPUs, memory, disk - - define CPU benchmarks - - do this for other platforms - - Get info periodically rather than always at startup +- define a notion of "app preferences": arbitrary XML edited on server, + passed to app client. + This could be used to e.g. select a color scheme for graphics + Could pass entire prefs? - NET_XFER_SET:: do_select: prevent one stream from starving others -- GUI and screensaver around core client - design default (core client) display - screensaver options - move around screen? - system tray icon behavior - -- get idle-only behavior without screensaver - -- Network retry policies - can't download file: when to give up? how to retry? - exponential backoff - can't upload file: when to give up/retry? - can't connect to sched server - error return from sched server - -- implement WU/result sequences - - add the ability to store input data directly in WU, and output directly in result (blob). For projects with small data. -- implement file upload/download requests +-------------------------- +DONE (may need test) -- sched server should return total credit info (user, team?) - could display in default core client display +- mechanism for returning app stderr output to server? store in blob? -- edit user account +- add size to FILE_INFO + server, client sides -- team system +- measure bandwidth on each network xfer + maintain exponential average, weighted by #bytes xferred diff --git a/checkin_notes b/checkin_notes index 29a7432cd1..df4c972f25 100755 --- a/checkin_notes +++ b/checkin_notes @@ -9,50 +9,49 @@ David A. April 11 2002 - Pass in platform name, version number from Makefile (platform name comes from configure) -David A. April 12 2002 - - Think through application-version logic. Here's how it works: - On the server side, WUs don't have a version number, - either in the DB or in the XML doc. - When the server sends a WU, - it precedes it with an tag containing a version number. - This instructs the client to process all WUs included in - the reply using that app version. - On the client side, WU records DO have a version number - (obtained as above). - - Change the "add" program so that command-line arguments are named - (e.g., "-app_name" foo instead of just "foo") - Modify test scripts accordingly. - - Have the scheduler read static tables (platform, app, app_version) - into memory at the beginning (new class: DB_CACHE) - This is a first step towards making the server efficient - (also need to convert it to fast CGI) - - Have the scheduler use files of the form - /tmp/boinc_req_PID and /tmp/boinc_reply_PID - rather than fixed-named files - - Have the scheduler send back error message when it can't open files - - client - Makefile.in - client_state.C - cs_scheduler.C - hostinfo_unix.C - types.C,h - db - db.h - db_mysql.C - html_user - db.inc - sched - handle_request.C,h - main.C - server_types.C,h - test - *wu - init.inc - tools - add.C -David A. April 15, 2002 - Change name from BOINC to BONC :-( +David A. May 15 2002 + - Allow applications to have multiple files + (e.g. scripts, libraries, pre- and post-processing programs). + The app_version table now has an xml_doc field, + which contains a list of and elements. + Note: the utility for adding applications (tools/add.C) + still handles only single-file applications. + - Changed IO_FILE_DESC to FILE_REF since it now represents + an association of a file to workunit, result or application -David A. April 25, 2002 - Change name from BONC back to BOINC :-) + client + app.C + client_state.C,h + cs_apps.C + cs_scheduler.C + main.C + message.h (new) + parse.C,h + scheduler_reply.C,h + types.C,h + Makefile.in + db + db.h + db_mysql.C + schema.sql + doc + app.html (new) + files.html + index.html + intro.html + project.gif + project.html + project.png + protocol.html + result.html (new) + work.html + html_user + db.inc + sched + handle_request.C + server_types.C,h + test + test_uc.php + init.inc + tools + add.C diff --git a/client/Makefile.in b/client/Makefile.in index 7c4241b533..3696d0a0e5 100644 --- a/client/Makefile.in +++ b/client/Makefile.in @@ -1,10 +1,10 @@ VERSION = 1 CFLAGS = -g -Wall @DEFS@ \ - -DHOSTTYPE=\"@host@\" \ + -DHOST=\"@host@\" \ -DVERSION=$(VERSION) -CC = g++ $(CFLAGS) -I ../lib +CC = @CC@ $(CFLAGS) -I ../lib CLIBS = @LIBS@ @@ -35,7 +35,6 @@ OBJS = \ time_stats.o \ types.o \ util.o \ - version.o \ ../lib/md5_file.o \ ../lib/md5.o @@ -74,7 +73,7 @@ tar: tar cf boinc_client.tar *.C *.h Makefile.in clean: - rm -f *.o $(PROGS) core dependencies config.cache + rm -f *.o $(PROGS) core dependencies Makefile config.cache dependencies: *.C $(CC) -M *.C > dependencies diff --git a/client/app.C b/client/app.C index cac050ff0b..25609188d5 100644 --- a/client/app.C +++ b/client/app.C @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -91,7 +90,8 @@ int ACTIVE_TASK::start(bool first_time) { char exec_name[256], file_path[256], link_path[256]; char* argv[100]; unsigned int i; - IO_FILE_DESC ifd; + FILE_REF file_ref; + FILE_INFO* fip; int fd, retval; @@ -104,28 +104,34 @@ int ACTIVE_TASK::start(bool first_time) { // knows there was a problem. // make a link to the executable - get_pathname(app_version->file_info, file_path); - strcpy(exec_name, app_version->file_info->name); - if (first_time) { - sprintf(link_path, "%s/%s", dirname, exec_name); - retval = link(file_path, link_path); - if (log_flags.task_debug) { - printf("link %s to %s\n", file_path, link_path); + // + for (i=0; iapp_files.size(); i++) { + fip = app_version->app_files[i].file_info; + get_pathname(fip, file_path); + if (i == 0) { + strcpy(exec_name, fip->name); } - if (retval) { - perror("link"); - exit(retval); + if (first_time) { + sprintf(link_path, "%s/%s", dirname, fip->name); + retval = link(file_path, link_path); + if (log_flags.task_debug) { + printf("link %s to %s\n", file_path, link_path); + } + if (retval) { + perror("link"); + exit(retval); + } } } // create symbolic links, and hook up descriptors, for input files // for (i=0; iinput_files.size(); i++) { - ifd = wup->input_files[i]; - get_pathname(ifd.file_info, file_path); - if (strlen(ifd.open_name)) { + file_ref = wup->input_files[i]; + get_pathname(file_ref.file_info, file_path); + if (strlen(file_ref.open_name)) { if (first_time) { - sprintf(link_path, "%s/%s", dirname, ifd.open_name); + sprintf(link_path, "%s/%s", dirname, file_ref.open_name); if (log_flags.task_debug) { printf("link %s to %s\n", file_path, link_path); } @@ -137,10 +143,10 @@ int ACTIVE_TASK::start(bool first_time) { } } else { fd = open(file_path, O_RDONLY); - if (fd != ifd.fd) { - retval = dup2(fd, ifd.fd); + if (fd != file_ref.fd) { + retval = dup2(fd, file_ref.fd); if (retval < 0) { - fprintf(stderr, "dup2 %d %d returned %d\n", fd, ifd.fd, retval); + fprintf(stderr, "dup2 %d %d returned %d\n", fd, file_ref.fd, retval); exit(retval); } close(fd); @@ -151,12 +157,12 @@ int ACTIVE_TASK::start(bool first_time) { // hook up the output files // for (i=0; ioutput_files.size(); i++) { - ifd = result->output_files[i]; - get_pathname(ifd.file_info, file_path); - if (strlen(ifd.open_name)) { + file_ref = result->output_files[i]; + get_pathname(file_ref.file_info, file_path); + if (strlen(file_ref.open_name)) { if (first_time) { creat(file_path, 0660); - sprintf(link_path, "%s/%s", dirname, ifd.open_name); + sprintf(link_path, "%s/%s", dirname, file_ref.open_name); if (log_flags.task_debug) { printf("link %s to %s\n", file_path, link_path); } @@ -168,10 +174,10 @@ int ACTIVE_TASK::start(bool first_time) { } } else { fd = open(file_path, O_WRONLY|O_CREAT, 0660); - if (fd != ifd.fd) { - retval = dup2(fd, ifd.fd); + if (fd != file_ref.fd) { + retval = dup2(fd, file_ref.fd); if (retval < 0) { - fprintf(stderr, "dup2 %d %d returned %d\n", fd, ifd.fd, retval); + fprintf(stderr, "dup2 %d %d returned %d\n", fd, file_ref.fd, retval); exit(retval); } close(fd); diff --git a/client/client_state.C b/client/client_state.C index 4265461fe8..dc031afdb0 100644 --- a/client/client_state.C +++ b/client/client_state.C @@ -37,6 +37,8 @@ CLIENT_STATE::CLIENT_STATE() { exit_when_idle = false; contacted_sched_server = false; activities_suspended = false; + version = VERSION; + platform_name = HOST; } int CLIENT_STATE::init(ACCOUNTS& accounts) { @@ -139,7 +141,7 @@ int CLIENT_STATE::parse_state_file() { if (!f) { if (log_flags.state_debug) { - printf("can't open state file: %s\n", STATE_FILE_NAME); + printf("No state file; will create one\n"); } return ERR_FOPEN; } @@ -187,6 +189,11 @@ int CLIENT_STATE::parse_state_file() { net_stats.parse(f); } else if (match_tag(buf, "")) { active_tasks.parse(f, this); + } else if (match_tag(buf, "")) { + // should match out current platform name + } else if (match_tag(buf, "")) { + // could put logic here to detect incompatible state files + // after core client update } else { fprintf(stderr, "CLIENT_STATE::parse_state_file: unrecognized: %s\n", buf); } @@ -246,6 +253,12 @@ int CLIENT_STATE::write_state_file() { } } active_tasks.write(f); + fprintf(f, + "%s\n" + "%d\n", + platform_name, + version + ); fprintf(f, "\n"); fclose(f); retval = rename(STATE_FILE_TEMP, STATE_FILE_NAME); @@ -307,7 +320,7 @@ FILE_INFO* CLIENT_STATE::lookup_file_info(PROJECT* p, char* name) { } // functions to create links between state objects -// (which, in their XML form, refer to one another by name) +// (which, in their XML form, reference one another by name) // int CLIENT_STATE::link_app(PROJECT* p, APP* app) { app->project = p; @@ -322,6 +335,10 @@ int CLIENT_STATE::link_file_info(PROJECT* p, FILE_INFO* fip) { int CLIENT_STATE::link_app_version(PROJECT* p, APP_VERSION* avp) { APP* app; FILE_INFO* fip; + FILE_REF file_ref; + unsigned int i; + + avp->project = p; app = lookup_app(p, avp->app_name); if (!app) { @@ -330,30 +347,34 @@ int CLIENT_STATE::link_app_version(PROJECT* p, APP_VERSION* avp) { ); return 1; } - fip = lookup_file_info(p, avp->file_name); - if (!fip) { - fprintf(stderr, - "app_version refers to nonexistent file: %s\n", avp->file_name - ); - return 1; - } - avp->project = p; avp->app = app; - avp->file_info = fip; + + for (i=0; iapp_files.size(); i++) { + file_ref = avp->app_files[i]; + fip = lookup_file_info(p, file_ref.file_name); + if (!fip) { + fprintf(stderr, + "app_version refers to nonexistent file: %s\n", + file_ref.file_name + ); + return 1; + } + avp->app_files[i].file_info = fip; + } return 0; } -int CLIENT_STATE::link_io_file_desc(PROJECT* p, IO_FILE_DESC* ifd) { +int CLIENT_STATE::link_file_ref(PROJECT* p, FILE_REF* file_refp) { FILE_INFO* fip; - fip = lookup_file_info(p, ifd->file_name); + fip = lookup_file_info(p, file_refp->file_name); if (!fip) { fprintf(stderr, - "I/O desc links to nonexistent file: %s\n", ifd->file_name + "I/O desc links to nonexistent file: %s\n", file_refp->file_name ); return 1; } - ifd->file_info = fip; + file_refp->file_info = fip; return 0; } @@ -382,7 +403,7 @@ int CLIENT_STATE::link_workunit(PROJECT* p, WORKUNIT* wup) { wup->app = app; wup->avp = avp; for (i=0; iinput_files.size(); i++) { - retval = link_io_file_desc(p, &wup->input_files[i]); + retval = link_file_ref(p, &wup->input_files[i]); if (retval) return retval; } return 0; @@ -401,7 +422,7 @@ int CLIENT_STATE::link_result(PROJECT* p, RESULT* rp) { rp->wup = wup; rp->app = wup->app; for (i=0; ioutput_files.size(); i++) { - retval = link_io_file_desc(p, &rp->output_files[i]); + retval = link_file_ref(p, &rp->output_files[i]); if (retval) return retval; } return 0; diff --git a/client/client_state.h b/client/client_state.h index 38770ba7aa..a292b78b50 100644 --- a/client/client_state.h +++ b/client/client_state.h @@ -47,6 +47,8 @@ private: vector workunits; vector results; + int version; + char* platform_name; HTTP_OP scheduler_op; PROJECT* scheduler_op_project; NET_XFER_SET* net_xfers; @@ -68,7 +70,7 @@ private: int write_state_file_if_needed(); int link_app(PROJECT*, APP*); int link_file_info(PROJECT*, FILE_INFO*); - int link_io_file_desc(PROJECT*, IO_FILE_DESC*); + int link_file_ref(PROJECT*, FILE_REF*); int link_app_version(PROJECT*, APP_VERSION*); int link_workunit(PROJECT*, WORKUNIT*); int link_result(PROJECT*, RESULT*); diff --git a/client/cs_apps.C b/client/cs_apps.C index 815ae63a8e..1f47c5e700 100644 --- a/client/cs_apps.C +++ b/client/cs_apps.C @@ -82,8 +82,14 @@ bool CLIENT_STATE::input_files_available(RESULT* rp) { WORKUNIT* wup = rp->wup; FILE_INFO* fip; unsigned int i; + APP_VERSION* avp; + + avp = wup->avp; + for (i=0; iapp_files.size(); i++) { + fip = avp->app_files[i].file_info; + if (!fip->file_present) return false; + } - if (!wup->avp->file_info->file_present) return false; for (i=0; iinput_files.size(); i++) { fip = wup->input_files[i].file_info; if (!fip->file_present) return false; diff --git a/client/cs_scheduler.C b/client/cs_scheduler.C index 7f153cb83a..5227fea036 100644 --- a/client/cs_scheduler.C +++ b/client/cs_scheduler.C @@ -25,8 +25,8 @@ #include "file_names.h" #include "parse.h" #include "log_flags.h" +#include "message.h" #include "scheduler_reply.h" -#include "version.h" #include "client_state.h" @@ -104,8 +104,8 @@ int CLIENT_STATE::make_scheduler_request(PROJECT* p, int work_req) { p->authenticator, p->hostid, p->rpc_seqno, - gplatform_name, - gversion, + platform_name, + version, work_req ); @@ -211,6 +211,10 @@ void CLIENT_STATE::handle_scheduler_reply(PROJECT* project) { f = fopen(SCHED_OP_RESULT_FILE, "r"); retval = sr.parse(f); + if (strlen(sr.message)) { + show_message(sr.message, sr.message_priority); + } + // copy new entities to client state // diff --git a/client/main.C b/client/main.C index 50603b9129..eeb5ac3b89 100644 --- a/client/main.C +++ b/client/main.C @@ -17,6 +17,8 @@ // Contributor(s): // +// command-line version of the BOINC core client + #include #include "accounts.h" @@ -24,6 +26,14 @@ #include "log_flags.h" #include "client_state.h" +void show_message(char* message, char* priority) { + if (!strcmp(priority, "high")) { + fprintf(stderr, "BOINC core client: %s\n", message); + } else { + printf("BOINC core client: %s\n", message); + } +} + int main(int argc, char** argv) { CLIENT_STATE cs; ACCOUNTS accounts; diff --git a/client/message.h b/client/message.h new file mode 100644 index 0000000000..12e5ded37d --- /dev/null +++ b/client/message.h @@ -0,0 +1,4 @@ +// show a message. +// Implemented in different ways in cmdline client versus GUI client +// +extern void show_message(char* message, char* priority); diff --git a/client/parse.C b/client/parse.C index d30f3db06e..b5264eb36a 100644 --- a/client/parse.C +++ b/client/parse.C @@ -17,6 +17,13 @@ // Contributor(s): // +// A very crude interface for parsing XML files; +// assumes all elements are either single-line or +// have start and end tags on separate lines. +// This is meant to be used ONLY for parsing XML files produced +// by the BOINC scheduling server or client. +// Could replace this with a more general parser. + #include #include @@ -44,12 +51,27 @@ bool parse_double(char* buf, char* tag, double& x) { bool parse_str(char* buf, char* tag, char* x) { char* p = strstr(buf, tag); if (!p) return false; + p = strchr(p, '>'); char* q = strchr(p+1, '<'); *q = 0; - strcpy(x, p+strlen(tag)); + strcpy(x, p+1); return true; } +void parse_attr(char* buf, char* name, char* out) { + char* p, *q; + + strcpy(out, ""); + p = strstr(buf, name); + if (!p) return; + p = strchr(p, '"'); + if (!p) return; + q = strchr(p+1, '"'); + if (!q) return; + *q = 0; + strcpy(out, p+1); +} + void copy_stream(FILE* in, FILE* out) { char buf[1024]; int n, m; diff --git a/client/parse.h b/client/parse.h index d5c046f310..733d6e4437 100644 --- a/client/parse.h +++ b/client/parse.h @@ -23,5 +23,6 @@ extern bool parse(char*, char*); extern bool parse_int(char*, char*, int&); extern bool parse_double(char*, char*, double&); extern bool parse_str(char*, char*, char*); +extern void parse_attr(char* buf, char* attrname, char* out); extern bool match_tag(char*, char*); extern void copy_stream(FILE* in, FILE* out); diff --git a/client/scheduler_reply.C b/client/scheduler_reply.C index 1f6d2a00b7..242135598a 100644 --- a/client/scheduler_reply.C +++ b/client/scheduler_reply.C @@ -27,7 +27,8 @@ int SCHEDULER_REPLY::parse(FILE* in) { char buf[256]; - strcpy(error_message, ""); + strcpy(message, ""); + strcpy(message_priority, ""); request_delay = 0; hostid = 0; @@ -70,7 +71,8 @@ int SCHEDULER_REPLY::parse(FILE* in) { RESULT result; result.parse(in, ""); result_acks.push_back(result); - } else if (parse_str(buf, "", error_message)) { + } else if (parse_str(buf, " apps; vector file_infos; diff --git a/client/types.C b/client/types.C index 64b94b31a3..08e6754b3f 100644 --- a/client/types.C +++ b/client/types.C @@ -176,17 +176,23 @@ int FILE_INFO::delete_file() { int APP_VERSION::parse(FILE* in) { char buf[256]; + FILE_REF file_ref; strcpy(app_name, ""); - strcpy(file_name, ""); + //strcpy(file_name, ""); version_num = 0; app = NULL; project = NULL; - file_info = NULL; + //file_info = NULL; while (fgets(buf, 256, in)) { if (match_tag(buf, "")) return 0; else if (parse_str(buf, "", app_name)) continue; - else if (parse_str(buf, "", file_name)) continue; + //else if (parse_str(buf, "", file_name)) continue; + else if (match_tag(buf, "")) { + file_ref.parse(in, ""); + app_files.push_back(file_ref); + continue; + } else if (parse_int(buf, "", version_num)) continue; else fprintf(stderr, "APP_VERSION::parse(): unrecognized: %s\n", buf); } @@ -194,34 +200,44 @@ int APP_VERSION::parse(FILE* in) { } int APP_VERSION::write(FILE* out) { + unsigned int i; fprintf(out, "\n" " %s\n" - " %s\n" - " %d\n" - "\n", - app_name, file_name, version_num + //" %s\n" + " %d\n", + app_name, + //file_name, + version_num + ); + for (i=0; i\n" ); return 0; } -int IO_FILE_DESC::parse(FILE* in, char* end_tag) { +int FILE_REF::parse(FILE* in, char* end_tag) { char buf[256]; strcpy(file_name, ""); strcpy(open_name, ""); fd = -1; + main_program = false; while (fgets(buf, 256, in)) { if (match_tag(buf, end_tag)) return 0; else if (parse_str(buf, "", file_name)) continue; else if (parse_str(buf, "", open_name)) continue; else if (parse_int(buf, "", fd)) continue; - else fprintf(stderr, "IO_FILE_DESC::parse(): unrecognized: %s\n", buf); + else if (match_tag(buf, "")) main_program = true; + else fprintf(stderr, "FILE_REF::parse(): unrecognized: %s\n", buf); } return 1; } -int IO_FILE_DESC::write(FILE* out, char* tag) { +int FILE_REF::write(FILE* out, char* tag) { fprintf(out, " <%s>\n", tag); if (strlen(open_name)) { fprintf(out, " %s\n", open_name); @@ -233,13 +249,16 @@ int IO_FILE_DESC::write(FILE* out, char* tag) { if (fd >= 0) { fprintf(out, " %d\n", fd); } + if (main_program) { + fprintf(out, " \n"); + } fprintf(out, " \n", tag); return 0; } int WORKUNIT::parse(FILE* in) { char buf[256]; - IO_FILE_DESC ifd; + FILE_REF file_ref; strcpy(name, ""); strcpy(app_name, ""); @@ -255,8 +274,8 @@ int WORKUNIT::parse(FILE* in) { else if (parse_str(buf, "", command_line)) continue; else if (parse_str(buf, "", env_vars)) continue; else if (match_tag(buf, "")) { - ifd.parse(in, ""); - input_files.push_back(ifd); + file_ref.parse(in, ""); + input_files.push_back(file_ref); continue; } else fprintf(stderr, "WORKUNIT::parse(): unrecognized: %s\n", buf); @@ -284,7 +303,7 @@ int WORKUNIT::write(FILE* out) { int RESULT::parse(FILE* in, char* end_tag) { char buf[256]; - IO_FILE_DESC ifd; + FILE_REF file_ref; strcpy(name, ""); strcpy(wu_name, ""); @@ -302,8 +321,8 @@ int RESULT::parse(FILE* in, char* end_tag) { else if (parse_str(buf, "", name)) continue; else if (parse_str(buf, "", wu_name)) continue; else if (match_tag(buf, "")) { - ifd.parse(in, ""); - output_files.push_back(ifd); + file_ref.parse(in, ""); + output_files.push_back(file_ref); continue; } else if (parse_double(buf, "", cpu_time)) continue; diff --git a/client/types.h b/client/types.h index ee11878df7..0fc952c9eb 100644 --- a/client/types.h +++ b/client/types.h @@ -85,33 +85,36 @@ struct FILE_INFO { int delete_file(); // attempt to delete the underlying file }; -struct APP_VERSION { - char app_name[256]; - char file_name[256]; - int version_num; - APP* app; - PROJECT* project; - FILE_INFO* file_info; - - int parse(FILE*); - int write(FILE*); -}; - -// describes a connection between a file and an application. -// Either the app will use open() or fopen() to access the file +// Describes a connection between a file and a workunit, result, or application. +// In the first two cases, +// the app will either use open() or fopen() to access the file // (in which case "open_name" is the name it will use) // or the app will be connected by the given fd (in which case fd is nonzero) // -struct IO_FILE_DESC { +struct FILE_REF { char file_name[256]; char open_name[256]; int fd; + bool main_program; FILE_INFO* file_info; int parse(FILE*, char*); int write(FILE*, char*); }; +struct APP_VERSION { + char app_name[256]; + //char file_name[256]; + int version_num; + APP* app; + PROJECT* project; + //FILE_INFO* file_info; + vector app_files; + + int parse(FILE*); + int write(FILE*); +}; + struct WORKUNIT { char name[256]; char app_name[256]; @@ -121,7 +124,7 @@ struct WORKUNIT { // (TODO: use alpha/beta/prod scheme) char command_line[256]; char env_vars[256]; // environment vars in URL format - vector input_files; + vector input_files; PROJECT* project; APP* app; APP_VERSION* avp; @@ -134,7 +137,7 @@ struct WORKUNIT { struct RESULT { char name[256]; char wu_name[256]; - vector output_files; + vector output_files; bool is_active; // an app is currently running for this bool is_compute_done; // computation finished bool is_server_ack; // ack received from scheduling server diff --git a/db/db.h b/db/db.h index 026d7f13f9..f133d8681c 100644 --- a/db/db.h +++ b/db/db.h @@ -71,9 +71,16 @@ struct APP_VERSION { int appid; int version_num; int platformid; - char url[256]; - char md5_cksum[256]; - double nbytes; + + // describes app files. format: + // ... + // ... + // + // ... + // ... + // + // + char xml_doc[MAX_BLOB_SIZE]; // The following defined for apps other than core client. // They let you handle backwards-incompatible changes to diff --git a/db/db_mysql.C b/db/db_mysql.C index ea98976b69..40309f2600 100644 --- a/db/db_mysql.C +++ b/db/db_mysql.C @@ -85,7 +85,7 @@ void struct_to_str(void* vp, char* q, int type) { avp = (APP_VERSION*)vp; sprintf(q, "id=%d, create_time=%d, appid=%d, version_num=%d, platformid=%d, " - "url='%s', md5_cksum='%s', nbytes=%f, " + "xml_doc='%s', " "min_core_version=%d, max_core_version=%d, " "message='%s', deprecated=%d", avp->id, @@ -93,9 +93,7 @@ void struct_to_str(void* vp, char* q, int type) { avp->appid, avp->version_num, avp->platformid, - avp->url, - avp->md5_cksum, - avp->nbytes, + avp->xml_doc, avp->min_core_version, avp->max_core_version, avp->message, @@ -243,9 +241,7 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) { avp->appid = atoi(r[i++]); avp->version_num = atoi(r[i++]); avp->platformid = atoi(r[i++]); - strcpy(avp->url, r[i++]); - strcpy(avp->md5_cksum, r[i++]); - avp->nbytes = atof(r[i++]); + strcpy(avp->xml_doc, r[i++]); avp->min_core_version = atoi(r[i++]); avp->max_core_version = atoi(r[i++]); strcpy(avp->message, r[i++]); diff --git a/db/schema.sql b/db/schema.sql index b23b244fcf..39c4bc3646 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -24,9 +24,7 @@ create table app_version ( appid integer not null, version_num integer not null, platformid integer not null, - url varchar(254), - md5_cksum varchar(254), - nbytes double not null, + xml_doc blob, min_core_version integer not null, max_core_version integer not null, message varchar(254), diff --git a/db/temp b/db/temp deleted file mode 100644 index c34d65cdd9..0000000000 --- a/db/temp +++ /dev/null @@ -1,5 +0,0 @@ -struct ENUM { - int active; - MYSQL_RES *rp; -}; - diff --git a/doc/app.html b/doc/app.html new file mode 100644 index 0000000000..74d5271f25 --- /dev/null +++ b/doc/app.html @@ -0,0 +1,44 @@ +

Platforms, applications, and versions

+

+A platform is a compilation target +(Windows/Intel, Linux/Intel, MacOS/PPC, etc.). +Platforms are maintained in the platform table in the BOINC DB, +and can be created using the add utility program. +

+An application is a computational task; +in concrete terms it consists of an executable program +(perhaps in versions for various platforms) +and a set of input files to be processed by the program. +A project can operate many applications. +Applications are maintained in the application table in the BOINC DB, +and can be created using the add utility. +

+An application program may go through a sequence of +versions. +A particular version, compiled for a particular platform, +is called an application version. +An application version can consist of multiple files: +for example, a controller script, +pre- and post-processing programs, and a primary. +

+Application version are maintained in the app_version +table in the BOINC DB, +Each entry includes an XML document describing the files +that make up the application version: +

+<file_info> ... </file_info>
+[ ... ]
+<app_version>
+    <app_name>foobar</app_name>
+    <version_num>4</version_num>
+    <file_ref>
+        <file_name>program_1</file_name>
+        <main_program/>
+    </file_ref>
+    <file_ref>
+        <file_name>library_12</file_name>
+    </file_ref>
+</app_version>
+
+The add utility program provides +a simplified interface for creating application versions. diff --git a/doc/files.html b/doc/files.html index 877bffeda6..b8c917d8bb 100644 --- a/doc/files.html +++ b/doc/files.html @@ -1,35 +1,83 @@ -

Compute model: files

+

Compute model: storage

+

Files

-Files are inputs and outputs to applications, -and the executable application programs. -Each file has a name that is unique within the project. -A file may also have one or more URLs, -indicating where it is (or will be) located on data servers. -Once a file is created (on the project server or on a participant host) -it is immutable. - +The BOINC storage model is based on files. +The inputs and outputs of applications, +and the applications executables, are files.

-Files have the following Boolean attributes: +A file is described by an XML element of the form +

+<file_info>
+    <name>foobar</name>
+    <url>http://a.b.c/foobar</url>
+    <url>http://x.y.z/foobar</url>
+    ...
+    <md5_cksum>123123123123</md5_cksum>
+    <nbytes>134423</nbytes>
+    [ <executable/> ]
+    [ <upload_when_present/> ]
+    [ <sticky/> ]
+</file_info>
+
+The components are as follows:
    -
  • Sticky -
  • Upload-when-present +
  • +The <name> element gives the file's name, +which must be unique within the project. + +
  • Each <url> element gives a URL +where the file is (or will be) located on a data server. +
  • The <md5_cksum> element +is the MD5 checksum of the file, +providing protection against corruption and spoofing. +
  • The <nbytes> element is the size of the file in bytes +(may be greater than 2^32). +
  • The <sticky> element, if present, +indicates that the file should be retained on the client +after its initial use. +
  • The <upload_when_present> element, if present, +indicates that the file should be uploaded after it is created. +
  • The <executable> element, +if present, indicates that the file protections +should be set to allow execution.
-Some files originate on hosts; -i.e. as output files of applications. -If the Upload-when-present flag is set, -the file (when available) is uploaded to one of its URLs. -If the Sticky flag is set, the file remains on the host -(where, e.g., it will serve as input to a later computation). +These attributes allow the specification of various types of files: +for example, input or output files that are retained for +use as input to later computations.

-Other files originate in the back-end servers, -and are placed on data servers. -If the Sticky flag is set, -the file is retained and a participant host after it is used. +Once a file is created (on a data server or a participant host) +it is immutable. +

File references

-The core agent and scheduling server exchange descriptions of files. -These descriptions include an MD5 checksum of the file, -providing protection against corruption and spoofing. +Files may be associated with +workunits, +results and +application versions. +Each such association is represented by an XML element of the form + +

+<file_ref>
+    <file_name>foobar</file_name>
+    [ <open_name>input</open_name> ]
+    [ <fd>2</fd> ]
+    [ <main_program/> ]
+</file_ref>
+
+ +The components are as follows: +
    +
  • The <file_name> element specifies a file. +
  • The <open_name> element, if present, +is the name by which the application will refer to the file +(in a call to fopen(), for example). +
  • The <fd> element, if present, +indicates the file descriptor number by which the application +will access the file. +
  • The <main_program> element is used for +files associated with application versions. +It indicates that this file is the application's main program. +
diff --git a/doc/index.html b/doc/index.html index ebe4b84c37..536951885e 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,10 +1,4 @@ -

Berkeley Open Infrastructure for Network Computing (BOINC)

-BOINC documentation is under development. -Please do not copy or distribute the URL. -
- -
  • Introduction @@ -12,9 +6,11 @@ Please do not copy or distribute the URL.

    Developing distributed applications with BOINC

    +SourceForge Logo diff --git a/doc/intro.html b/doc/intro.html index b256b947ce..46fe6a3bb8 100644 --- a/doc/intro.html +++ b/doc/intro.html @@ -1,7 +1,7 @@

    Introduction

    -Berkeley Open Infrastructure for Network Computing (BOINC) +Berkeley Open Infrastructure for Distributed Computing (BOINC) is a software platform for public-participation distributed computing projects like distributed.net and SETI@home. BOINC is distributed under the Mozilla license. @@ -20,16 +20,17 @@ Participants can control how their resources are divided among the projects.

  • BOINC supports applications that produce or consume large amounts of data. It allows data distribution and collection to be -spread across large numbers of servers, -and it allows participant hosts to transfer data transparently -over long time periods. +spread across many servers, +and it allows participant hosts to do large data transfers unobtrusively.
  • BOINC supports applications with extreme requirements for memory or other resources. -Work is dispatched only to hosts able to handle it. +Work units are dispatched only to hosts able to handle them. -
  • BOINC applications can be developed in any compiled language -(C, C++, Fortran). +
  • BOINC applications can be developed in any language +(C++, Fortran, Perl). +An application can consist of several files +(e.g. several programs and a coordinating script). New versions of applications can be released without participant download. Separate alpha, beta, and production versions are distributed to the appropriate set of hosts. diff --git a/doc/project.fig b/doc/project.fig index d75a76e9ce..c07f57f63f 100644 --- a/doc/project.fig +++ b/doc/project.fig @@ -7,58 +7,177 @@ Letter Single -2 1200 2 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 - 3600 2400 6900 2400 6900 3300 3600 3300 3600 2400 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 - 3600 2400 6900 2400 6900 3300 3600 3300 3600 2400 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 - 3600 1500 6900 1500 6900 1875 3600 1875 3600 1500 +0 32 #c7b696 +0 33 #effbff +0 34 #dfcba6 +0 35 #414141 +0 36 #868286 +0 37 #c7c3c7 +0 38 #e7e3e7 +0 39 #8e8e8e +0 40 #aeaaae +0 41 #515551 +0 42 #414141 +0 43 #868286 +0 44 #c7c3c7 +0 45 #868286 +0 46 #c7c3c7 +0 47 #e7e3e7 +0 48 #8e8e8e +0 49 #8e8e8e +0 50 #414141 +0 51 #868286 +0 52 #c7c3c7 +0 53 #e7e3e7 +0 54 #414141 +0 55 #868286 +0 56 #c7c3c7 +0 57 #e7e3e7 +0 58 #868286 +0 59 #c7c3c7 +0 60 #e7e3e7 +0 61 #c7b696 +0 62 #effbff +0 63 #dfcba6 +0 64 #c7b696 +0 65 #effbff +0 66 #dfcba6 +0 67 #aeaaae +0 68 #515551 +0 69 #8e8e8e +0 70 #414141 +0 71 #868286 +0 72 #c7c3c7 +0 73 #e7e3e7 +0 74 #414141 +0 75 #868286 +0 76 #c7c3c7 +0 77 #e7e3e7 +0 78 #868286 +0 79 #c7c3c7 +0 80 #e7e3e7 +0 81 #414141 +0 82 #868286 +0 83 #c7c3c7 +0 84 #414141 +0 85 #c7c3c7 +0 86 #e7e3e7 +0 87 #414141 +0 88 #868286 +0 89 #c7c3c7 +0 90 #8e8e8e +0 91 #414141 +0 92 #868286 +0 93 #c7c3c7 +0 94 #e7e3e7 +0 95 #414141 +0 96 #868286 +0 97 #c7c3c7 +0 98 #e7e3e7 +0 99 #bebebe +0 100 #515151 +0 101 #000049 +0 102 #797979 +0 103 #303430 +0 104 #414541 +0 105 #414141 +0 106 #868286 +0 107 #c7c3c7 +0 108 #e7e3e7 +6 3225 2625 4650 3300 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 + 3225 2625 4650 2625 4650 3300 3225 3300 3225 2625 +4 0 0 50 0 18 14 0.0000 4 210 1155 3375 2925 scheduling\001 +4 0 0 50 0 18 14 0.0000 4 120 660 3600 3150 server\001 +-6 +6 4950 3675 5925 4950 +5 1 0 1 -1 -1 0 0 -1 0.000 0 1 0 0 5400.000 4125.000 4950 4725 5400 4875 5850 4725 +1 2 0 1 -1 11 0 0 20 0.000 1 0.0000 5421 3894 450 150 4971 3894 5871 3894 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 4950 3900 4950 4725 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2 + 5850 3975 5850 4725 +4 1 -1 0 0 18 12 0.0000 6 135 600 5400 4350 BOINC\001 +4 1 -1 0 0 18 12 0.0000 6 135 270 5400 4575 DB\001 +-6 +6 7650 750 8775 1500 +2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7650 750 8775 750 8775 1500 7650 1500 7650 750 +4 0 0 50 0 18 14 0.0000 4 120 780 7800 1350 servers\001 +4 0 0 50 0 18 14 0.0000 4 165 450 7950 1050 data\001 +-6 +6 2100 4050 2775 4800 +2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2400 4575 2400 4050 +4 0 0 50 0 16 14 0.0000 4 120 630 2100 4800 server\001 +-6 +6 2100 5250 2625 6075 +2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2400 5550 2400 6075 +4 0 0 50 0 16 14 0.0000 4 165 510 2100 5475 client\001 +-6 +6 4800 2625 6225 3300 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 + 4800 2625 6225 2625 6225 3300 4800 3300 4800 2625 +4 0 0 50 0 18 14 0.0000 4 210 585 5175 2925 utility\001 +4 0 0 50 0 18 14 0.0000 4 165 1005 5025 3150 programs\001 +-6 +6 6375 2625 7800 3300 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 + 6375 2625 7800 2625 7800 3300 6375 3300 6375 2625 +4 0 0 50 0 18 14 0.0000 4 165 465 6900 2925 Web\001 +4 0 0 50 0 18 14 0.0000 4 165 1020 6600 3150 interfaces\001 +-6 2 2 0 1 0 30 50 0 20 0.000 0 0 -1 0 0 5 3600 750 6900 750 6900 1500 3600 1500 3600 750 2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 1 2 0 0 1.00 60.00 120.00 0 0 1.00 60.00 120.00 - 5250 1875 5250 2400 -2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 3900 3300 3900 5925 -2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 1 2 - 0 0 1.00 60.00 120.00 - 0 0 1.00 60.00 120.00 - 5550 5400 5550 5925 -2 1 1 1 0 3 50 0 20 4.000 0 0 -1 0 0 2 - 2700 3750 9600 3750 + 3900 3300 3900 7200 2 2 0 1 0 30 50 0 20 0.000 0 0 -1 0 0 5 9825 750 10350 750 10350 1200 9825 1200 9825 750 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 9825 1350 10350 1350 10350 1800 9825 1800 9825 1350 -2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 0 2 +2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 1 2 0 0 1.00 60.00 120.00 - 8400 3300 8400 2775 -2 1 0 1 0 3 50 0 20 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 - 8400 4200 8400 4725 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 - 4214 5025 6975 5025 6975 5400 4214 5400 4214 5025 + 5550 6675 5550 7200 +2 1 1 1 0 3 50 0 20 4.000 0 0 -1 0 0 2 + 2700 5025 9600 5025 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 + 4214 6300 6975 6300 6975 6675 4214 6675 4214 6300 2 2 0 1 0 30 50 0 20 0.000 0 0 -1 0 0 5 - 4214 4275 6975 4275 6975 5025 4214 5025 4214 4275 -2 2 0 1 0 3 50 0 20 0.000 0 0 -1 0 0 5 - 3600 5925 7650 5925 7650 6825 3600 6825 3600 5925 + 4214 5550 6975 5550 6975 6300 4214 6300 4214 5550 +2 2 0 1 0 11 50 0 20 0.000 0 0 -1 0 0 5 + 3600 7200 8850 7200 8850 8100 3600 8100 3600 7200 2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 0 0 1.00 60.00 120.00 - 7350 5925 7350 1500 -2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5 - 6975 750 8100 750 8100 1500 6975 1500 6975 750 -4 0 0 50 0 18 14 0.0000 4 210 2355 4125 2925 BOINC server complex\001 + 8250 7200 8250 1500 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4350 3300 4950 3750 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 5400 3300 5400 3675 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6825 3300 6000 3750 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6309 1488 7125 2625 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 5409 1488 5400 2625 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 10081 6123 7500 3300 4 0 0 50 0 18 14 0.0000 4 210 1740 4350 1275 project back end\001 -4 0 0 50 0 18 14 0.0000 4 165 1365 4500 1800 back end API\001 -4 0 0 50 0 16 14 0.0000 4 210 2400 10500 1200 project-specific software\001 -4 0 0 50 0 16 14 0.0000 4 165 1545 10500 1800 BOINC software\001 -4 0 0 50 0 16 14 0.0000 4 165 510 8100 4125 client\001 -4 0 0 50 0 16 14 0.0000 4 120 630 8100 3525 server\001 -4 0 0 50 0 18 14 0.0000 4 215 1826 4751 4725 application client\001 -4 0 0 50 0 18 14 0.0000 4 169 1012 4981 5325 client API\001 -4 0 0 50 0 18 14 0.0000 4 169 1120 4981 6450 core client\001 -4 0 0 50 0 18 14 0.0000 4 120 780 7125 1350 servers\001 -4 0 0 50 0 18 14 0.0000 4 165 450 7275 1050 data\001 +4 0 0 50 0 16 14 0.0000 4 210 2775 10500 1200 project-specific components\001 +4 0 0 50 0 16 14 0.0000 4 210 1920 10500 1800 BOINC components\001 +4 0 0 50 0 18 14 0.0000 4 210 1785 4751 6000 application client\001 +4 0 0 50 0 18 14 0.0000 4 165 990 4981 6600 client API\001 +4 0 0 50 0 18 14 0.0000 4 165 1095 5550 7725 core client\001 +4 0 0 50 0 18 14 0.0000 4 210 2355 2100 2400 BOINC server complex\001 +4 0 0 50 0 18 14 0.0000 4 210 1245 9450 6525 participants\001 diff --git a/doc/project.html b/doc/project.html index 855db48da0..e004ff3b89 100644 --- a/doc/project.html +++ b/doc/project.html @@ -1,12 +1,9 @@

    Projects and applications

    -A project is an organization -(e.g., an academic research project) that uses BOINC to get computing power. +A project is an organization that uses BOINC. Projects are independent; each one manages its own applications, databases and servers, and is not affected by the status of other projects. - -

    The components of a project are shown below.
    @@ -14,11 +11,17 @@ The components of a project are shown below.

    The server side of a project consists of two parts:

      -
    • A project back end part that generates -computation input files, and handles the output of computations, -in a way that depends on the particular application. +
    • A project back end that supplies +applications and work units, +and that handles the computational results. +Input and output files are distributed by data servers, +which are HTTP servers able to handle uploads. +These servers need not be owned or operated by the project. +A project might, for example, recruit other organizations to +donate network bandwidth by hosting data servers; +data could be moved on tape between the project back end and the data servers.
    • A BOINC server complex -that handles data distribution and collection. +that manages data distribution and collection.
    The BOINC server complex includes the following components: @@ -26,23 +29,7 @@ The BOINC server complex includes the following components:
  • A scheduling server that communicates with participant hosts.
  • A relational database storing information about work, results, and participants. -
  • C and scripting-language interfaces for -communication with the project back end. +
  • Utility programs and libraries that allow the +project back end to interact with the server complex.
  • Web interfaces for participants and developers.
- -

-Input and output files are distributed by data servers, -which are HTTP servers able to handle uploads. -These servers need not be owned or operated by the project. -A project might, for example, recruit other organizations to -donate network bandwidth by hosting data servers; -data could be moved on tape between the project back end and the data servers. - -

Applications and platforms

-

-A project can operate one or more applications. -Versions of an application are compiled for various platforms -(Windows/Intel, Linux/Intel, MacOS/PPC, etc.). -The BOINC core client is available for many platforms; -a project can compile an application for any or all of these. diff --git a/doc/project.png b/doc/project.png index b3e39b57e1..68f367109f 100644 Binary files a/doc/project.png and b/doc/project.png differ diff --git a/doc/protocol.html b/doc/protocol.html index 6b3a276871..0261895a11 100644 --- a/doc/protocol.html +++ b/doc/protocol.html @@ -1,7 +1,13 @@

The BOINC client/server protocol

+

Protocol nucleus

The core client communicates with scheduling servers using HTTP. +The following "nucleus" of the protocol should be considered immutable. +This will allow any version of the core client to talk to +any version of the scheduling server, +and for the server, if needed, +to tell the core client that it's out of date. The form of the request is:

 <scheduler_request>
@@ -20,39 +26,46 @@ The form of the reply is:
 <scheduler_reply>
     [ <message priority="low"> arbitrary text </message> ... ]
     [ <request_delay>3600</request_delay> ]
+    [ <redirect>URL</redirect> ]
     ... other elements
 </scheduler_reply>
 
-

-The "message" element provides message for the core client. -If the priority is "high", the core client should do what it can -to ensure the the participant sees the message -(e.g., display it in a modal dialog). +

message element is a message to the participant. +

    +
  • +If the priority is "high", the core client should try +to ensure that the participant sees the message; +for example, by displaying it in a popup window. +It should not, however, wait for user input, as this +could starve other projects. This should be reserved for situations where definitive action is required, e.g. the user must download a new version of the core client in order to continue participating in this project. +
  • If the priority is "low" (default) the core client should -allow the participant to see the message, but not require it; -e.g., by writing the message to a log file. - +allow the participant to see the message, but should not require it. +For example, it could the message to a log file. +

A reply message can contain multiple message elements.

-The optional "request_delay" tag instructs the client +A request_delay element instructs the client to not issue another request until the indicated number of seconds has elapsed. -

-The above portion of the protocol should be considered immutable. -This will allow any version of the core client to talk to -any version of the scheduling server, -and for the server, if needed, -to tell the core client that it's hopelessly out of date. +A redirect element gives the URL for a scheduling +server for this project. +If present, the core client should replace its list +of scheduling servers for this project. +The reply may contain multiple redirect elements. + + +

Extensible protocol

+

The remaining protocol may evolve over time. - -

Request elements include

diff --git a/doc/result.html b/doc/result.html
new file mode 100644
index 0000000000..900290cd85
--- /dev/null
+++ b/doc/result.html
@@ -0,0 +1,75 @@
+

Compute model: results

+ +

+A result describes an instance of a computation, +either to be performed, in progress, or completed. +Results are stored in the result table of the BOINC DB. +The attributes of a result include: +

    +
  • The name of the result (unique across all results in the project). +
  • The name of the associated workunit. +
  • An XML document listing the names of its output files; see below. +
  • An XML document giving the sizes and checksums of its output files +(this is filled in after the result is completed). +
  • The stderr output of the result. +
  • The host that computed the result. +
  • The times when the result was dispatched and received. +
  • The exit status of the application. +
  • The reported CPU time. +
  • Its state. Values include: +
      +
    • Inactive (not ready to dispatch) +
    • Unsent (ready to dispatch, but not dispatched) +
    • In progress (dispatched, not done) +
    • Done successfully +
    • Timed out +
    • Done with error +
    +
+ +The XML document listing the output files has the form: +
+<file_info>...</file_info>
+[ ... ]
+<result>
+    <name>foobar</name>
+    <wu_name>blah</wu_name>
+    <file_ref>...</file_ref>
+    [ ... ]
+</result>
+
+The components are: +
    +
  • The <name> element is the result name. +
  • The <wu_name> element is the workunit name. +
  • Each <file_ref> element is an association +to an output file, described by a corresponding +<file_info> element. +
+ +

+The XML document describing the sizes and checksums +of the output files is just a list of +<file_info> elements, with the +nbytes and md5_cksum fields present. +The project back end must parse this field to +find the locations and checksums of output files. +

+Several results may be associated with a single workunit. +Results may be generated in either of two ways +(selected as part of the application): +

    +
  • Advance generation of results. +One or more result records are stored in the database +when the workunit is produced. +The scheduling server dispatches each result to a single participant host. +When all result records have been dispatched, +participants hosts are "turned away". +
  • On-demand generation of results. +The application specifies a "result template", +which has place-holder tokens for the output filenames. +The scheduling server, in response to a host request, +generates a new result record and sends the result template. +The host generates unique output filenames, +and returns them along when it the computation is done. +
diff --git a/doc/work.html b/doc/work.html index 40c9db1f10..907e614044 100644 --- a/doc/work.html +++ b/doc/work.html @@ -1,75 +1,55 @@ -

Compute model: workunits and results

+

Compute model: workunits

A workunit describes a computation to be performed. +Workunits are maintained in the workunit table in the BOINC DB. The attributes of a workunit include:

    -
  • The application it's associated with. +
  • Its application.
  • Its name (unique across all workunits in the project). -
  • A list of its input files. -Each has an input file association -that specifies the filename or file descriptor number -by which the application will refer to the file. -
  • The command-line arguments to be passed to the application. -
  • The environment variables to be set for the application. +
  • An XML document describing its input files and other parameters +(see below).
  • The estimated resource requirements of the work unit (computation, memory, disk space, network traffic). +
  • Counts of how many times this workunit should be dispatched, +how many times it has been dispatched, how many results have +been returned, and how many failures have occurred. +
+

+The inputs of a workunit are described by an XML document of the form +

+[ <file_info>...</file_info> ]
+[ ... ]
+<workunit>
+    <name>foobar</name>
+    <app_name>blah</app_name>
+    [ <command_line>-flags xyz</command_line> ]
+    [ <env_vars>name=val&name=val</env_vars> ]
+    [ <file_ref>...</file_ref> ]
+    [ ... ]
+<workunit>
+
+The components are: +
    +
  • The <name> element is the name of the workunit. +
  • The <app_name> element is the name of the application. +
  • The <command_line> element, if present, +is the command-line arguments to be passed to the main program. +
  • The <env_vars> element, if present, +is a list of environment variables to be passed to the main program. +
  • Each <file_ref> element describes a +reference to an input file, +each of which is described by a <file_info> element.
-

A workunit is associated with an application, not with a particular version or set of versions. If the format of your input data changes in a way that is incompatible with older versions, you must create a new application. -This can often be avoided by using XML-like data representations. +This can often be avoided by using XML data format.

-A result describes a particular instance of a computation, -either to be performed or already performed. -The attributes of a result include: -

    -
  • The workunit it's associated with. -
  • Its name (unique across all results in the project). -
  • A list of its output files. -Each has an output file association -that specifies the filename or file descriptor number -by which the application will refer to the file. -
  • Its state. Values include: -
      -
    • Inactive (not ready to dispatch) -
    • Unsent (ready to dispatch, but not dispatched) -
    • In progress (dispatched, not done) -
    • Done successfully -
    • Timed out -
    • Done with error -
    -
-

-Several results may be associated with a single workunit. -Results may be generated in either of two ways -(selected as part of the application): -

    -
  • Advance generation of results. -One or more result records are stored in the database -when the workunit is produced. -The scheduling server dispatches each result to a single participant host. -When all result records have been dispatched, -participants hosts are "turned away". -
  • On-demand generation of results. -The application specifies a "result template", -which has place-holder tokens for the output filenames. -The scheduling server, in response to a host request, -generates a new result record and sends the result template. -The host generates unique output filenames, -and returns them along when it the computation is done. -
-

- -


-The following diagram illustrates the relationship between -workunits, results, files, and I/O assocations. -

- - +The create_work utility program +provides a simplified interface for creating workunits. diff --git a/html/user/db.inc b/html/user/db.inc index 6a8ba45df9..75babc71a2 100644 --- a/html/user/db.inc +++ b/html/user/db.inc @@ -39,8 +39,11 @@ function show_app_version($app_version) { row("app ID", $app_version->appid); row("version num", $app_version->version_num); row("platform ID", $app_version->platformid); - row("url", $app_version->url); - row("MD5", $app_version->md5_cksum); + row("XML doc", "

".htmlspecialchars($app_version->xml_doc)."
"); + row("min_core_version", $app_version->min_core_version); + row("max_core_version", $app_version->max_core_version); + row("message", $app_version->message); + row("deprecated", $app_version->deprecated); echo ""; } diff --git a/sched/handle_request.C b/sched/handle_request.C index 1c2cf18b70..bb8b917b02 100644 --- a/sched/handle_request.C +++ b/sched/handle_request.C @@ -77,20 +77,22 @@ int authenticate_user( if (sreq.hostid) { retval = db_host(sreq.hostid, host); if (retval) { - strcpy(reply.error_message, "invalid hostid"); + strcpy(reply.message, "Can't find host record"); + strcpy(reply.message_priority, "low"); return -1; } retval = db_user(host.userid, user); if (retval) { - strcpy(reply.error_message, "internal error - no such user"); + strcpy(reply.message, "Can't find user record"); + strcpy(reply.message_priority, "low"); return -1; } if (strcmp(sreq.authenticator, user.authenticator)) { - strcpy(reply.error_message, + strcpy(reply.message, "Invalid or missing authenticator. " - "Visit this project's web site to request your authenticator, " - "then cut and paste it into your accounts file." + "Visit this project's web site to get an authenticator." ); + strcpy(reply.message_priority, "low"); return -1; } @@ -107,7 +109,8 @@ int authenticate_user( strcpy(user.authenticator, sreq.authenticator); retval = db_user_lookup_auth(user); if (retval) { - strcpy(reply.error_message, "invalid or missing authenticator"); + strcpy(reply.message, "Invalid or missing authenticator"); + strcpy(reply.message_priority, "low"); return -1; } new_host: @@ -120,7 +123,8 @@ new_host: host.rpc_time = time(0); retval = db_host_new(host); if (retval) { - strcpy(reply.error_message, "DB operation failed"); + strcpy(reply.message, "server database error"); + strcpy(reply.message_priority, "low"); db_print_error("db_host_new"); return -1; } @@ -304,7 +308,8 @@ int send_work( } if (nresults == 0) { - strcpy(reply.error_message, "no work available"); + strcpy(reply.message, "no work available"); + strcpy(reply.message_priority, "low"); reply.request_delay = 10; } return 0; @@ -330,7 +335,8 @@ void process_request( platform = db.lookup_platform(sreq.platform_name); if (!platform) { sprintf(buf, "platform %s not found", sreq.platform_name); - strcpy(reply.error_message, buf); + strcpy(reply.message, buf); + strcpy(reply.message_priority, "low"); return; } diff --git a/sched/server_types.C b/sched/server_types.C index fd66f681ed..bce210eb56 100644 --- a/sched/server_types.C +++ b/sched/server_types.C @@ -78,7 +78,8 @@ int SCHEDULER_REQUEST::parse(FILE* fin) { SCHEDULER_REPLY::SCHEDULER_REPLY() { request_delay = 0; hostid = 0; - strcpy(error_message, ""); + strcpy(message, ""); + strcpy(message_priority, ""); send_prefs = false; } @@ -95,8 +96,12 @@ int SCHEDULER_REPLY::write(FILE* fout) { if (request_delay) { fprintf(fout, "%d\n", request_delay); } - if (strlen(error_message)) { - fprintf(fout, "%s\n", error_message); + if (strlen(message)) { + fprintf(fout, + "%s\n", + message_priority, + message + ); } if (hostid) { @@ -193,25 +198,7 @@ int APP::write(FILE* fout) { } int APP_VERSION::write(FILE* fout, APP& app) { - fprintf(fout, - "\n" - " %s_%d\n" - " \n" - " %s\n" - " %s\n" - "\n" - "\n" - " %s\n" - " %s_%d\n" - " %d\n" - "\n", - app.name, id, - url, - md5_cksum, - app.name, - app.name, id, - version_num - ); + fputs(xml_doc, fout); return 0; } diff --git a/sched/server_types.h b/sched/server_types.h index ca0c0c11cf..1343b5cb39 100644 --- a/sched/server_types.h +++ b/sched/server_types.h @@ -44,7 +44,8 @@ struct SCHEDULER_REQUEST { struct SCHEDULER_REPLY { int request_delay; // don't request again until this time elapses - char error_message[256]; // if present, don't return anything else + char message[1024]; + char message_priority[256]; int hostid; // send this only if nonzero. // this tells client to reset rpc_seqno bool send_prefs; diff --git a/test/init.inc b/test/init.inc index 84dca19926..c494f629e8 100644 --- a/test/init.inc +++ b/test/init.inc @@ -1,16 +1,15 @@ \n" + " %s\n" + " %s/%s\n" + " \n" + " %s\n" + " %f\n" + "\n" + "\n" + " %s\n" + " %d\n" + " \n" + " %s\n" + " \n" + " \n" + "\n", + exec_file, + url_base, exec_file, + md5_cksum, + nbytes, + app_name, + version, + exec_file + ); app_version.create_time = time(0); retval = db_app_version_new(app_version);