📜 ⬆️ ⬇️

BOINC: work generator

During its operation, the BOINC server must constantly generate any tasks that will then be sent to clients for processing. For these purposes, a special demon generator is used. Most often it is called work_generator.

An example generator can be found at ~ / server_stable / sched / sample_work_generatr.cpp.
This file can be changed in accordance with the needs.

Consider a simple example of building and running a generator.
')
0. If the BOINC server is running, stop it ~ / projects / test / bin / stop (~ / projects / test / - home directory of the working project)

1. Go to ~ / server_stable / sched /

2. Putting the generator: make. Superuser rights may be required. There is a ready MakeFile to build examples. It can also be used to build a rewritten generator. The file is quite large and confusing. You can dig deeper in it and extract only what concerns the generator. You can also rewrite for yourself (for example, I needed to add the -lntl flag to the CXXFLAGS variable to connect the NTL library). I repeat, and without editing everything will be fine to assemble.

3. As a result, we get 2 files: sample_work_generator.o (executable) and sample_work_generator (script). These files are copied to ~ / projects / test / bin /

4. Now we need to fix the project configuration file: ~ / projects / test / config.xml. At the very end of this file there is a description of the daemons launched at the project start. We add there the following:
<daemon> <cmd> sample_work_generator -d 3 </cmd> </daemon> 


There similar structures should already be. It is necessary to add this by analogy. The -d 3 flags mean that the command starts the daemon with a third debug level.

5. Run the ~ / projects / test / bin / start project

Now, during the operation of the BOINC server, jobs will be constantly generated. The files of tasks will be recorded in the folder ~ / projects / test / download, which will then be sent to clients. Tasks will also be registered in the BOINC database in the workunit table.

Now consider an example file generator.

 #include <unistd.h> #include <cstdlib> #include <string> #include <cstring> #include "boinc_db.h" #include "error_numbers.h" #include "backend_lib.h" #include "parse.h" #include "util.h" #include "svn_version.h" #include "sched_config.h" #include "sched_util.h" #include "sched_msgs.h" #include "str_util.h" #define CUSHION 1000 //  ,    //    #define REPLICATION_FACTOR 2 char* wu_template; DB_APP app; int start_time; int seqno; //   int make_job(ZZ &num) { DB_WORKUNIT wu; char name[256], path[256]; const char* infiles[1]; int retval; //   - sprintf(name, "s_%d_%d", start_time, seqno++); //     retval = config.download_path(name, path); if (retval) return retval; //     ofstreamfile file(path); file << num; file.close(); //   wu.clear(); wu.appid = app.id; strcpy(wu.name, name); wu.rsc_fpops_est = 1e12; wu.rsc_fpops_bound = 1e14; wu.rsc_memory_bound = 1e8; wu.rsc_disk_bound = 1e8; wu.delay_bound = 86400; wu.min_quorum = REPLICATION_FACTOR; wu.target_nresults = REPLICATION_FACTOR; wu.max_error_results = REPLICATION_FACTOR*4; wu.max_total_results = REPLICATION_FACTOR*8; wu.max_success_results = REPLICATION_FACTOR*4; infiles[0] = name; //   BOINC (  ) return create_work( wu, wu_template, "templates/uc_result", config.project_path("templates/uc_result"), infiles, 1, config ); } //    void main_loop() { int retval; ZZ curr_num=to_ZZ("5"); while (1) { check_stop_daemons(); //,    int n; retval = count_unsent_results(n, 0); //   if (n > CUSHION) { //      -  sleep(60); } else { int njobs = (CUSHION-n)/REPLICATION_FACTOR; log_messages.printf(MSG_DEBUG, "Making %d jobs\n", njobs ); for (int i=0; i<njobs; i++) { retval = make_job(curr_num); while (1) { curr_num++; if (curr_num%2==0 || curr_num%3==0 || curr_num%5==0) continue; break; } if (retval) { //  log_messages.printf(MSG_CRITICAL, "can't make job: %d\n", retval ); exit(retval); } } sleep(5); } } } int main(int argc, char** argv) { int i, retval; start_num=0; end_num = 0; for (i=1; i<argc; i++) { if (is_arg(argv[i], "d")) { if (!argv[++i]) { log_messages.printf(MSG_CRITICAL, "%s requires an argument\n\n", argv[--i]); exit(1); } int dl = atoi(argv[i]); log_messages.set_debug_level(dl); if (dl == 4) g_print_queries = true; } else { log_messages.printf(MSG_CRITICAL, "unknown command line argument: %s\n\n", argv[i]); usage(argv[0]); exit(1); } } retval = config.parse_file(); if (retval) { log_messages.printf(MSG_CRITICAL, "Can't parse config.xml: %s\n", boincerror(retval) ); exit(1); } retval = boinc_db.open( config.db_name, config.db_host, config.db_user, config.db_passwd ); if (retval) { log_messages.printf(MSG_CRITICAL, "can't open db\n"); exit(1); } if (app.lookup("where name='uppercase'")) { log_messages.printf(MSG_CRITICAL, "can't find app\n"); exit(1); } if (read_file_malloc(config.project_path("templates/uc_wu"), wu_template)) { log_messages.printf(MSG_CRITICAL, "can't read WU template\n"); exit(1); } start_time = time(0); seqno = 0; log_messages.printf(MSG_NORMAL, "Starting\n"); main_loop(); } 

Source: https://habr.com/ru/post/131687/


All Articles