test framework

svn path=/trunk/boinc/; revision=457
This commit is contained in:
David Anderson 2002-10-03 18:33:46 +00:00
parent f1a858b6ff
commit c0813dcd55
25 changed files with 740 additions and 200 deletions

View File

@ -2023,3 +2023,50 @@ David Sept 28 2002
server_types.C,h
tools/
add.C
David Oct 3 2002
- Changed the PHP framework for testing to facilitate
multi-project, multi-host tests (all on one machine).
See doc/test.html for details.
- NOTE: the BOINC-related environment variables have changed.
There are no longer any project-specific variables
(e.g. database name, shmem key)
- NOTE: the server programs now expect a configuration file
in their directory.
- TODO: enhance the testing framework to allow projects with
multiple scheduling servers or data servers
- TODO: enhance the testing framework to allow specification
of failure and recovery of servers
- changed things so a NULL in the DB won't crash db_mysql.C
- parse_int() can now handle hex
- "add" now takes args for DB name/passwd
- "create_work" now takes args for DB name/passwd,
upload/download URL, download dir
db/
db_mysql.C
mysql_util.C
doc/
data_server_setup.html
sched_server_setup.html
test.html
web_site.html
html_user/
index.html
lib/
md5_file.C
parse.C
sched/
Makefile.in
config.C,h (new)
feeder.C
file_upload_handler.C
main.C
validate.C
validate_test.C
tools/
add.C
backend_lib.C,h
create_work.C
process_result_template.C

View File

@ -25,15 +25,15 @@
#include "db.h"
#define TYPE_PROJECT 1
#define TYPE_PLATFORM 2
#define TYPE_PROJECT 1
#define TYPE_PLATFORM 2
#define TYPE_APP 3
#define TYPE_APP_VERSION 4
#define TYPE_USER 5
#define TYPE_TEAM 6
#define TYPE_HOST 7
#define TYPE_WORKUNIT 8
#define TYPE_RESULT 9
#define TYPE_USER 5
#define TYPE_TEAM 6
#define TYPE_HOST 7
#define TYPE_WORKUNIT 8
#define TYPE_RESULT 9
char* table_name[] = {
"",
@ -230,6 +230,11 @@ void struct_to_str(void* vp, char* q, int type) {
}
}
static void strcpy2(char* dest, char* src) {
if (!src) *dest = 0;
else strcpy(dest, src);
}
void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
PROJECT* prp;
PLATFORM* pp;
@ -248,23 +253,23 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
prp = (PROJECT*)vp;
memset(prp, 0, sizeof(PROJECT));
prp->id = atoi(r[i++]);
strcpy(prp->name, r[i++]);
strcpy2(prp->name, r[i++]);
break;
case TYPE_PLATFORM:
pp = (PLATFORM*)vp;
memset(pp, 0, sizeof(PLATFORM));
pp->id = atoi(r[i++]);
pp->create_time = atoi(r[i++]);
strcpy(pp->name, r[i++]);
strcpy2(pp->name, r[i++]);
break;
case TYPE_APP:
app = (APP*)vp;
memset(app, 0, sizeof(APP));
app->id = atoi(r[i++]);
app->create_time = atoi(r[i++]);
strcpy(app->name, r[i++]);
strcpy2(app->name, r[i++]);
app->min_version = atoi(r[i++]);
strcpy(app->result_xml_template, r[i++]);
strcpy2(app->result_xml_template, r[i++]);
break;
case TYPE_APP_VERSION:
avp = (APP_VERSION*)vp;
@ -274,10 +279,10 @@ 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->xml_doc, r[i++]);
strcpy2(avp->xml_doc, r[i++]);
avp->min_core_version = atoi(r[i++]);
avp->max_core_version = atoi(r[i++]);
strcpy(avp->message, r[i++]);
strcpy2(avp->message, r[i++]);
avp->deprecated = atoi(r[i++]);
break;
case TYPE_USER:
@ -285,17 +290,17 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
memset(up, 0, sizeof(USER));
up->id = atoi(r[i++]);
up->create_time = atoi(r[i++]);
strcpy(up->email_addr, r[i++]);
strcpy(up->name, r[i++]);
strcpy(up->web_password, r[i++]);
strcpy(up->authenticator, r[i++]);
strcpy(up->country, r[i++]);
strcpy(up->postal_code, r[i++]);
strcpy2(up->email_addr, r[i++]);
strcpy2(up->name, r[i++]);
strcpy2(up->web_password, r[i++]);
strcpy2(up->authenticator, r[i++]);
strcpy2(up->country, r[i++]);
strcpy2(up->postal_code, r[i++]);
up->total_credit = atof(r[i++]);
up->expavg_credit = atof(r[i++]);
up->expavg_time = atof(r[i++]);
strcpy(up->global_prefs, r[i++]);
strcpy(up->project_prefs, r[i++]);
strcpy2(up->global_prefs, r[i++]);
strcpy2(up->project_prefs, r[i++]);
up->teamid = atoi(r[i++]);
break;
case TYPE_TEAM:
@ -303,11 +308,11 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
memset(tp, 0, sizeof(TEAM));
tp->id = atoi(r[i++]);
tp->userid = atoi(r[i++]);
strcpy(tp->name, r[i++]);
strcpy(tp->name_lc, r[i++]);
strcpy(tp->url, r[i++]);
strcpy(tp->name_html, r[i++]);
strcpy(tp->description, r[i++]);
strcpy2(tp->name, r[i++]);
strcpy2(tp->name_lc, r[i++]);
strcpy2(tp->url, r[i++]);
strcpy2(tp->name_html, r[i++]);
strcpy2(tp->description, r[i++]);
tp->nusers = atoi(r[i++]);
break;
case TYPE_HOST:
@ -322,21 +327,21 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
hp->expavg_credit = atof(r[i++]);
hp->expavg_time = atof(r[i++]);
hp->timezone = atoi(r[i++]);
strcpy(hp->domain_name, r[i++]);
strcpy(hp->serialnum, r[i++]);
strcpy(hp->last_ip_addr, r[i++]);
strcpy2(hp->domain_name, r[i++]);
strcpy2(hp->serialnum, r[i++]);
strcpy2(hp->last_ip_addr, r[i++]);
hp->nsame_ip_addr = atoi(r[i++]);
hp->on_frac = atof(r[i++]);
hp->connected_frac = atof(r[i++]);
hp->active_frac = atof(r[i++]);
hp->p_ncpus = atoi(r[i++]);
strcpy(hp->p_vendor, r[i++]);
strcpy(hp->p_model, r[i++]);
strcpy2(hp->p_vendor, r[i++]);
strcpy2(hp->p_model, r[i++]);
hp->p_fpops = atof(r[i++]);
hp->p_iops = atof(r[i++]);
hp->p_membw = atof(r[i++]);
strcpy(hp->os_name, r[i++]);
strcpy(hp->os_version, r[i++]);
strcpy2(hp->os_name, r[i++]);
strcpy2(hp->os_version, r[i++]);
hp->m_nbytes = atof(r[i++]);
hp->m_cache = atof(r[i++]);
hp->m_swap = atof(r[i++]);
@ -354,8 +359,8 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
wup->appid = atoi(r[i++]);
wup->previous_wuid = atoi(r[i++]);
wup->has_successor = (atoi(r[i++])!=0);
strcpy(wup->name, r[i++]);
strcpy(wup->xml_doc, r[i++]);
strcpy2(wup->name, r[i++]);
strcpy2(wup->xml_doc, r[i++]);
wup->batch = atoi(r[i++]);
wup->rsc_fpops = atof(r[i++]);
wup->rsc_iops = atof(r[i++]);
@ -382,12 +387,12 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
rp->report_deadline = atoi(r[i++]);
rp->sent_time = atoi(r[i++]);
rp->received_time = atoi(r[i++]);
strcpy(rp->name, r[i++]);
strcpy2(rp->name, r[i++]);
rp->exit_status = atoi(r[i++]);
rp->cpu_time = atof(r[i++]);
strcpy(rp->xml_doc_in, r[i++]);
strcpy(rp->xml_doc_out, r[i++]);
strcpy(rp->stderr_out, r[i++]);
strcpy2(rp->xml_doc_in, r[i++]);
strcpy2(rp->xml_doc_out, r[i++]);
strcpy2(rp->stderr_out, r[i++]);
rp->batch = atoi(r[i++]);
rp->project_state = atoi(r[i++]);
rp->validate_state = atoi(r[i++]);

View File

@ -54,6 +54,7 @@ int db_close() {
void db_print_error(char* p) {
if (mp) {
printf("<br>%s: Database error: %s\n", p, mysql_error(mp));
fprintf(stderr, "%s: Database error: %s\n", p, mysql_error(mp));
}
}

View File

@ -2,28 +2,20 @@
<h2>Setting up a data server</h2>
<p>
The BOINC data server is implemented as an Apache
or similar web server.
Its upload function runs as a CGI program.
It has been tested under Linux and Solaris.
The BOINC data server is implemented using Apache
or a similar web server.
It is used both to upload and to download files.
File download is handled by the web server, using GET operations.
File upload is done by a CGI program, <b>file_upload_handler</b>.
The host need not have access to the BOINC database.
<p>
You must copy the file upload authentication key
to each data server.
<h3>Compiling the file upload handler</h3>
<p>
The upload handler, file_upload_handler,
is compiled by the makefile in sched/.
The following environment variables must be defined first:
<pre>
setenv BOINC_UPLOAD_DIR /users/barry/upload
setenv BOINC_KEY_DIR /users/barry/keys
</pre>
<p>
BOINC_UPLOAD_DIR is that path of the upload directory.
BOINC_KEY_DIR is a directory containing the
file upload authentication public key.
The file upload handler uses a configuration of
the same format as used by the
<a href=sched_server_setup.html>scheduling server</a>.
<h3>Web server configuration</h3>
<p>

View File

@ -4,40 +4,48 @@
<p>
The BOINC scheduling server runs as a CGI or fast CGI
program under Apache or similar web server.
It has been tested on Linux and Solaris.
The host must have access to the BOINC database.
The host must have access to the project's BOINC database.
<p>
The scheduling server uses an auxiliary program
called "feeder"; the two programs communicate
through a shared-memory segment.
The scheduling server uses an auxiliary program called "feeder";
the two programs communicate through a shared-memory segment.
<p>
The scheduling server and feeder programs are compiled
by typing "configure" and "make" in the sched/ directory.
Prior to doing this, you must define
the following environment variables:
Both programs read a configuration file <b>config.xml</b>
with the following form:
<pre>
setenv BOINC_DB_NAME boinc_barry
setenv BOINC_DB_PASSWD
setenv BOINC_SHMEM_KEY 0xdabacafe
setenv BOINC_KEY_DIR /users/david/boinc_server/keys
&lt;config>
&lt;db_name>david_test&lt;/db_name>
&lt;db_passwd>&lt;/db_passwd>
&lt;shmem_key>0xbeefacafe&lt;/shmem_key>
&lt;key_dir>/home/david/boinc_keys&lt;/key_dir>
&lt;upload_dir>/home/david/boinc_projects/test/upload&lt;/upload_dir>
&lt;user_name>david&lt;/user_name>
&lt;/config>
</pre>
BOINC_DB_NAME and BOINC_DB_PASSWORD are the
name and password of the BOINC database.
The elements are as follows:
<p>
BOINC_SHMEM_KEY is the identifier of the
shared-memory segment;
<table border=1 cellpadding=10>
<tr><td>db_name</td><td>The name of the BOINC database</td></tr>
<tr><td>db_password</td><td>The password of the BOINC database</td></tr>
<tr><td>shmem_key</td><td>
The identifier of the shared-memory segment;
it is an arbitrary 32-bit quantity,
but must be unique among different BOINC servers
sharing a single host.
<p>
BOINC_KEY_DIR is the directory containing
</td></tr>
<tr><td>key_dir</td><td>
The directory containing
the file upload authentication private key.
<p>
If any of these variables changes,
you must do a "make clean; make" in the sched directory.
</td></tr>
<tr><td>upload_dir</td><td>
The directory where uploaded files are stored
(this is used by the <a href=data_server_setup.html>data server</a>).
</td></tr>
<tr><td>user_name</td><td>
This name is prepended to web log error messages
to distinguish between multiple servers on a single host.
</td></tr>
</table>
<p>
You must modify your Apache config file
to allow execution of the scheduling server.
@ -52,4 +60,4 @@ ScriptAlias /boinc-cgi/ "/users/barry/cgi/"
Order allow,deny
Allow from all
&lt;/Directory>
</pre>
</pre>

View File

@ -1,6 +1,19 @@
<title>Test applications and scripts</title>
<body bgcolor=ffffff>
<h2>Test applications and scripts</h2>
<pre>
setenv BOINC_PROJECTS_DIR /home/david/boinc_projects
setenv BOINC_HOSTS_DIR /home/david/boinc_hosts
setenv BOINC_USER_NAME david
setenv BOINC_SRC_DIR /home/david/boinc_cvs/boinc
setenv BOINC_CGI_DIR /home/david/cgi-bin
setenv BOINC_CGI_URL http://localhost/cgi-bin
setenv BOINC_HTML_DIR /home/david/html
setenv BOINC_HTML_URL http://localhost
setenv BOINC_KEY_DIR /home/david/boinc_keys
setenv BOINC_PLATFORM i686-pc-linux-gnu
</pre>
<p>
The <b>apps</b> directory contains the following test applications:
<ul>
@ -43,12 +56,3 @@ These scripts use functions defined in the PHP include file
You can use these functions to easily write test
scripts for your own applications.
<pre>
setenv BOINC_DOWNLOAD_DIR ~/download
setenv BOINC_UPLOAD_URL http://maggie.ssl.berkeley.edu/barry/cgi/file_upload_handler
setenv BOINC_DOWNLOAD_URL http://maggie.ssl.berkeley.edu/barry/download
setenv BOINC_PLATFORM sparc-sun-solaris2.7
setenv BOINC_EMAIL barry@ssl.berkeley.edu
setenv BOINC_USER barry
setenv BOINC_MASTER_URL http:\\\\\/\\\\/maggie.ssl.berkeley.edu\\\\/~barry
</pre>

View File

@ -1,7 +1,9 @@
<title>Setting up a web site</title>
<h2>Setting up a web site</h2>
<p>
<h3>The master URL</h3>
<p>
Each project is publicly identified by a <b>master URL</b>.

View File

@ -13,6 +13,6 @@ create an account, then download the BOINC client.
<li><a href=team.php>Teams</a></li>
</ul>
<!--
<scheduler>http://localhost/davea_boinc_cgi/cgi</scheduler>
<scheduler>SCHEDULER_URL</scheduler>
-->
</body>

View File

@ -33,7 +33,7 @@ int md5_file(char* path, char* output, double& nbytes) {
nbytes = 0;
f = fopen(path, "rb");
if (!f) {
fprintf(stdout, "md5_file: can't open %s\n", path);
fprintf(stderr, "md5_file: can't open %s\n", path);
perror("md5_file");
return -1;
}

View File

@ -48,7 +48,7 @@ bool match_tag(char* buf, char* tag) {
bool parse_int(char* buf, char* tag, int& x) {
char* p = strstr(buf, tag);
if (!p) return false;
x = atoi(p+strlen(tag));
x = strtol(p+strlen(tag), 0, 0); // this parses 0xabcd correctly
return true;
}

View File

@ -9,12 +9,6 @@ CFLAGS = -g -Wall @DEFS@ \
-I@top_srcdir@/db \
-I@top_srcdir@/lib \
-I@top_srcdir@/tools \
-DBOINC_DB_NAME=\"$(BOINC_DB_NAME)\" \
-DBOINC_DB_PASSWD=\"$(BOINC_DB_PASSWD)\" \
-DBOINC_SHMEM_KEY=$(BOINC_SHMEM_KEY) \
-DBOINC_KEY_DIR=\"$(BOINC_KEY_DIR)\" \
-DBOINC_UPLOAD_DIR=\"$(BOINC_UPLOAD_DIR)\" \
-DBOINC_USER=\"$(BOINC_USER)\" \
-I/usr/local/mysql/include \
-I@top_srcdir@/RSAEuro/source \
@ -22,7 +16,7 @@ CC = g++ $(CFLAGS)
CLIBS = @LIBS@
PROGS = cgi feeder show_shmem file_upload_handler fcgi validate_test
PROGS = cgi feeder show_shmem file_upload_handler validate_test
all: $(PROGS)
@ -31,6 +25,7 @@ CGI_OBJS = \
main.o \
sched_shmem.o \
server_types.o \
config.o \
../db/db_mysql.o \
../db/mysql_util.o \
../lib/shmem.o \
@ -39,8 +34,10 @@ CGI_OBJS = \
FEEDER_OBJS = \
feeder.o \
sched_shmem.o \
config.o \
../db/db_mysql.o \
../db/mysql_util.o \
../lib/parse.o \
../lib/shmem.o
SHOW_SHMEM_OBJS = \
@ -52,6 +49,7 @@ SHOW_SHMEM_OBJS = \
FILE_UPLOAD_OBJS = \
file_upload_handler.o \
config.o \
../lib/crypt.o \
../lib/parse.o \
../lib/md5.o \
@ -61,6 +59,7 @@ FILE_UPLOAD_OBJS = \
VALIDATE_OBJS = \
validate.o \
validate_test.o \
config.o \
../db/db_mysql.o \
../db/mysql_util.o \
../lib/parse.o

31
sched/config.C Normal file
View File

@ -0,0 +1,31 @@
#include <stdio.h>
#include <string.h>
#include "parse.h"
#include "error_numbers.h"
#include "config.h"
int CONFIG::parse(FILE* in) {
char buf[256];
memset(this, 0, sizeof(CONFIG));
while (fgets(buf, 256, in)) {
if (match_tag(buf, "</config>")) return 0;
else if (parse_str(buf, "<db_name>", db_name, sizeof(db_name))) continue;
else if (parse_str(buf, "<db_passwd>", db_passwd, sizeof(db_passwd))) continue;
else if (parse_int(buf, "<shmem_key>", shmem_key)) continue;
else if (parse_str(buf, "<key_dir>", key_dir, sizeof(key_dir))) continue;
else if (parse_str(buf, "<upload_dir>", upload_dir, sizeof(upload_dir))) continue;
else if (parse_str(buf, "<user_name>", user_name, sizeof(user_name))) continue;
}
return ERR_XML_PARSE;
}
int CONFIG::parse_file() {
FILE* f;
f = fopen("config.xml", "r");
if (!f) return ERR_FOPEN;
return parse(f);
}

14
sched/config.h Normal file
View File

@ -0,0 +1,14 @@
// info needed by server-side software
//
class CONFIG {
public:
char db_name[256];
char db_passwd[256];
int shmem_key;
char key_dir[256];
char upload_dir[256];
char user_name[256];
int parse(FILE*);
int parse_file();
};

View File

@ -51,11 +51,14 @@
#include "db.h"
#include "shmem.h"
#include "config.h"
#include "sched_shmem.h"
#define RESULTS_PER_ENUM 100
#define TRIGGER_FILENAME "feeder_trigger"
CONFIG config;
int check_trigger(SCHED_SHMEM* ssp) {
FILE* f;
char buf[256];
@ -66,7 +69,7 @@ int check_trigger(SCHED_SHMEM* ssp) {
fclose(f);
if (!strcmp(buf, "<quit/>\n")) {
detach_shmem((void*)ssp);
destroy_shmem(BOINC_SHMEM_KEY);
destroy_shmem(config.shmem_key);
unlink(TRIGGER_FILENAME);
exit(0);
} else if (!strcmp(buf, "<reread_db/>\n")) {
@ -175,25 +178,31 @@ int main(int argc, char** argv) {
bool asynch = false;
void* p;
retval = config.parse_file();
if (retval) {
fprintf(stderr, "feeder: can't parse config file\n");
exit(1);
}
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-asynch")) {
asynch = true;
}
}
retval = destroy_shmem(BOINC_SHMEM_KEY);
retval = destroy_shmem(config.shmem_key);
if (retval) {
fprintf(stderr, "feeder: can't destroy shmem\n");
exit(1);
}
retval = create_shmem(BOINC_SHMEM_KEY, sizeof(SCHED_SHMEM), &p);
retval = create_shmem(config.shmem_key, sizeof(SCHED_SHMEM), &p);
if (retval) {
fprintf(stderr, "feeder: can't create shmem\n");
exit(1);
}
ssp = (SCHED_SHMEM*)p;
ssp->init();
retval = db_open(getenv("BOINC_DB_NAME"), getenv("BOINC_DB_PASSWD"));
retval = db_open(config.db_name, config.db_passwd);
if (retval) {
fprintf(stderr, "feeder: db_open: %d\n", retval);
exit(1);

View File

@ -58,8 +58,11 @@
#include <errno.h>
#include "parse.h"
#include "config.h"
#include "crypt.h"
CONFIG config;
#define MAX_FILES 32
struct FILE_INFO {
@ -86,7 +89,7 @@ int FILE_INFO::parse(FILE* in) {
strcatdup(signed_xml, buf);
if (parse_str(buf, "<name>", name, sizeof(name))) continue;
if (parse_double(buf, "<max_nbytes>", max_nbytes)) continue;
//fprintf(stderr, "file_upload_handler (%s): FILE_INFO::parse: unrecognized: %s \n", BOINC_USER, buf);
//fprintf(stderr, "file_upload_handler (%s): FILE_INFO::parse: unrecognized: %s \n", config.user, buf);
}
return 1;
}
@ -97,7 +100,7 @@ int print_status(int status, char* message) {
printf("<error>%s</error>\n", message);
fprintf(stderr,
"file_upload_handler (%s): status %d: %s>\n",
BOINC_USER, status, message
config.user_name, status, message
);
}
return 0;
@ -164,7 +167,7 @@ int handle_request(FILE* in, R_RSA_PUBLIC_KEY& key) {
if (retval) {
fprintf(stderr,
"file_upload_handler (%s): FILE_INFO.parse\n",
BOINC_USER
config.user_name
);
return retval;
}
@ -182,7 +185,7 @@ int handle_request(FILE* in, R_RSA_PUBLIC_KEY& key) {
struct stat sbuf;
// TODO: check to ensure path doesn't point somewhere bad
//
sprintf( path, "%s/%s", BOINC_UPLOAD_DIR, file_name );
sprintf(path, "%s/%s", config.upload_dir, file_name );
retval = stat( path, &sbuf );
if (retval && errno != ENOENT) {
print_status( -1, "cannot open file" );
@ -226,12 +229,12 @@ int handle_request(FILE* in, R_RSA_PUBLIC_KEY& key) {
return -1;
}
sprintf(path, "%s/%s", BOINC_UPLOAD_DIR, file_info.name);
sprintf(path, "%s/%s", config.upload_dir, file_info.name);
retval = copy_socket_to_file(in, path, offset, nbytes);
if (retval) {
fprintf(stderr,
"file_upload_handler (%s): copy_socket_to_file %d %s\n",
BOINC_USER, retval, path
config.user_name, retval, path
);
}
break;
@ -244,7 +247,7 @@ int get_key(R_RSA_PUBLIC_KEY& key) {
FILE* f;
int retval;
char buf[256];
sprintf(buf, "%s/upload_public", BOINC_KEY_DIR);
sprintf(buf, "%s/upload_public", config.key_dir);
f = fopen(buf, "r");
if (!f) return -1;
retval = scan_key_hex(f, (KEY*)&key, sizeof(key));
@ -257,9 +260,14 @@ int main() {
int retval;
R_RSA_PUBLIC_KEY key;
retval = config.parse_file();
if (retval) {
print_status(-1, "can't read config file");
exit(0);
}
retval = get_key(key);
if (retval) {
fprintf(stderr, "file_upload_handler: can't read key file\n");
print_status(-1, "can't read key file");
exit(0);
}

View File

@ -29,6 +29,8 @@ using namespace std;
#include "db.h"
#include "parse.h"
#include "shmem.h"
#include "config.h"
#include "server_types.h"
#include "handle_request.h"
#include "main.h"
@ -64,22 +66,29 @@ int main() {
unsigned int counter=0;
char* code_sign_key;
bool found;
CONFIG config;
sprintf(path, "%s/code_sign_public", BOINC_KEY_DIR);
retval = config.parse_file();
if (retval) {
fprintf(stderr, "Can't parse config file\n");
exit(1);
}
sprintf(path, "%s/code_sign_public", config.key_dir);
retval = read_file_malloc(path, code_sign_key);
if (retval) {
fprintf(stderr,
"BOINC scheduler (%s): can't read code sign key file (%s)\n",
BOINC_USER, path
config.user_name, path
);
exit(1);
}
retval = attach_shmem(BOINC_SHMEM_KEY, &p);
retval = attach_shmem(config.shmem_key, &p);
if (retval) {
fprintf(stderr,
"BOINC scheduler (%s): can't attach shmem\n",
BOINC_USER
config.user_name
);
exit(1);
}
@ -88,7 +97,7 @@ int main() {
if (retval) {
fprintf(stderr,
"BOINC scheduler (%s): shmem has wrong struct sizes - recompile\n",
BOINC_USER
config.user_name
);
exit(1);
}
@ -97,23 +106,23 @@ int main() {
if (ssp->ready) break;
fprintf(stderr,
"BOINC scheduler (%s): waiting for ready flag\n",
BOINC_USER
config.user_name
);
sleep(1);
}
if (!ssp->ready) {
fprintf(stderr,
"BOINC scheduler (%s): feeder doesn't seem to be running\n",
BOINC_USER
config.user_name
);
exit(1);
}
//fprintf(stderr, "got ready flag\n");
retval = db_open(BOINC_DB_NAME, BOINC_DB_PASSWD);
retval = db_open(config.db_name, config.db_passwd);
if (retval) {
fprintf(stderr,
"BOINC scheduler (%s): can't open database\n",
BOINC_USER
config.user_name
);
return_error("can't open database");
exit(1);
@ -126,7 +135,7 @@ int main() {
if (!found) {
fprintf(stderr,
"BOINC scheduler (%s): can't find project\n",
BOINC_USER
config.user_name
);
exit(1);
}
@ -141,24 +150,40 @@ int main() {
fprintf(stdout, "Content-type: text/plain\n\n");
fout = fopen(req_path, "w");
if (!fout) {
exit(return_error("Compiled by BOINC_USER: can't write request file"));
fprintf(stderr,
"BOINC scheduler (%s): can't write request file",
config.user_name
);
exit(1);
}
copy_stream(stdin, fout);
fclose(fout);
fin = fopen(req_path, "r");
if (!fin) {
exit(return_error("Compiled by BOINC_USER: can't read request file"));
fprintf(stderr,
"BOINC scheduler (%s): can't read request file",
config.user_name
);
exit(1);
}
fout = fopen(reply_path, "w");
if (!fout) {
exit(return_error("Compiled by BOINC_USER: can't write reply file"));
fprintf(stderr,
"BOINC scheduler (%s): can't write reply file",
config.user_name
);
exit(1);
}
handle_request(fin, fout, *ssp, code_sign_key);
fclose(fin);
fclose(fout);
fin = fopen(reply_path, "r");
if (!fin) {
exit(return_error("Compiled by BOINC_USER: can't read reply file"));
fprintf(stderr,
"BOINC scheduler (%s): can't read reply file",
config.user_name
);
exit(1);
}
copy_stream(fin, stdout);
fclose(fin);

View File

@ -42,10 +42,13 @@
#include <vector>
#include "db.h"
#include "config.h"
extern int check_set(vector<RESULT>, int& canonical, double& credit);
extern int check_pair(RESULT&, RESULT&, bool&);
CONFIG config;
#define SECONDS_IN_DAY (3600*24)
#define EXP_DECAY_RATE (1./(SECONDS_IN_DAY*7))
@ -179,7 +182,12 @@ int main(int argc, char** argv) {
APP app;
bool did_something;
retval = db_open(getenv("BOINC_DB_NAME"), getenv("BOINC_DB_PASSWD"));
retval = config.parse_file();
if (retval) {
fprintf(stderr, "Can't parse config file\n");
exit(1);
}
retval = db_open(config.db_name, config.db_passwd);
if (retval) {
fprintf(stderr, "validate: db_open: %d\n", retval);
exit(1);

View File

@ -20,8 +20,11 @@
#include <vector>
#include "db.h"
#include "config.h"
#include "parse.h"
extern CONFIG config;
// get the name of a result's (first) output file
//
void get_output_file_path(RESULT& result, char* path) {
@ -31,7 +34,7 @@ void get_output_file_path(RESULT& result, char* path) {
strcpy(path, "");
retval = parse_str(result.xml_doc_in, "<name>", buf, sizeof(buf));
if (retval) return;
char* upload_dir = getenv("BOINC_UPLOAD_DIR");
char* upload_dir = config.upload_dir;
sprintf(path, "%s/%s", upload_dir, buf);
}

345
test/test.inc Normal file
View File

@ -0,0 +1,345 @@
<?php
// test.inc
//
// A set of classes for testing BOINC.
// These classes let you create multiple projects and multiple hosts
// (all running on a single machine),
// add applications and work units, run the system,
// and verify that the results are correct.
//
// See doc/test.html for details
// get an enviroment variable, and abort script if missing
//
function get_env_var($name) {
$x = getenv($name);
if ($x == null) {
echo "Environment variable $name not defined\n";
exit();
}
return $x;
}
function run_db_script($script, $db_name) {
$db_dir = get_env_var("BOINC_SRC_DIR")."/db";
$x = "sed -e s/BOINC_DB_NAME/$db_name/ $db_dir/$script | mysql";
//echo $x;
PassThru($x);
}
function db_open($db_name) {
$retval = mysql_connect();
if (!$retval) {
echo "mysql_connect() failed\n";
exit();
}
$retval = mysql_select_db($db_name);
if (!$retval) {
echo "mysql_select_db() failed\n";
exit();
}
}
function db_query($query) {
if (!mysql_query($query)) {
echo "mysql_query failed: $query\n";
echo mysql_error();
exit();
}
}
function run_tool($cmd) {
$tool_dir = get_env_var("BOINC_SRC_DIR")."/tools/";
$cmd = $tool_dir.$cmd;
PassThru($cmd);
}
class App {
var $name;
function App($name) {
$this->name = $name;
}
}
class App_Version {
var $app;
var $version;
var $exec_name;
function App_Version($app) {
$this->app = $app;
$this->version = 1;
$this->exec_name = $app->name;
}
}
class Project {
var $name;
var $users;
var $apps;
var $app_versions;
var $project_dir;
var $db_name;
var $generate_keys;
var $shmem_key;
var $key_dir;
var $download_url;
var $scheduler_url;
var $upload_url;
var $user_name;
var $master_url;
function Project() {
$this->name = "test";
$this->users = array();
$this->apps = array();
$this->app_versions = array();
$this->generate_keys = false;
$this->shmem_key = "0xbeefacafe";
}
function add_user($user) {
array_push($this->users, $user);
}
function add_app($app) {
array_push($this->apps, $app);
}
function add_app_version($app_version) {
array_push($this->app_versions, $app_version);
}
// Set up the database and directory structures for a project
//
function Install() {
$base_dir = get_env_var("BOINC_PROJECTS_DIR");
$source_dir = get_env_var("BOINC_SRC_DIR");
$this->download_url = get_env_var("BOINC_HTML_URL")."/".$this->name."/download";
$this->upload_url = get_env_var("BOINC_CGI_URL")."/".$this->name."/file_upload_handler";
$this->scheduler_url = get_env_var("BOINC_CGI_URL")."/".$this->name."/cgi";
$this->project_dir = $base_dir."/".$this->name;
$this->master_url = get_env_var("BOINC_HTML_URL")."/".$this->name."/html_user/index.html";
PassThru("rm -rf $this->project_dir");
PassThru("mkdir $this->project_dir");
PassThru("mkdir $this->project_dir/cgi");
PassThru("mkdir $this->project_dir/upload; chmod uog+w $this->project_dir/upload");
PassThru("mkdir $this->project_dir/download");
PassThru("mkdir $this->project_dir/keys");
PassThru("mkdir $this->project_dir/html_ops");
PassThru("mkdir $this->project_dir/html_user");
if ($this->generate_keys) {
} else {
$this->key_dir = get_env_var("BOINC_KEY_DIR");
PassThru("cp $this->key_dir/* $this->project_dir/keys");
}
// set up the database
//
$this->user_name = get_env_var("BOINC_USER_NAME");
$this->db_name = $this->user_name."_".$this->name;
run_db_script("drop.sql", $this->db_name);
run_db_script("schema.sql", $this->db_name);
run_db_script("constraints.sql", $this->db_name);
db_open($this->db_name);
db_query("insert into project(name) values('$this->name')");
$platform = get_env_var("BOINC_PLATFORM");
db_query("insert into platform(name) values('$platform')");
for ($i=0; $i<sizeof($this->users); $i++) {
$user = $this->users[$i];
$now = time(0);
db_query("insert into user values (0, $now, '$user->email_addr', '$user->name', 'foobar', '$user->authenticator', 'Peru', '12345', 0, 0, 0, '', '', 0)");
}
echo "adding apps\n";
for ($i=0; $i<sizeof($this->apps); $i++) {
$app = $this->apps[$i];
db_query("insert into app(name, create_time) values ('$app->name', $now)");
}
echo "adding app versions\n";
for ($i=0; $i<sizeof($this->app_versions); $i++) {
$app_version = $this->app_versions[$i];
$app = $app_version->app;
run_tool("add app_version -db_name $this->db_name -app_name $app->name -platform_name $platform -version $app_version->version -download_dir $this->project_dir/download -download_url $this->download_url -code_sign_keyfile $this->key_dir/code_sign_private -exec_dir $source_dir/apps -exec_files $app_version->exec_name");
}
// copy the CGI programs and feeder to the project dir,
// and make a config file there
//
PassThru("cp $source_dir/sched/cgi $this->project_dir/cgi/");
PassThru("cp $source_dir/sched/file_upload_handler $this->project_dir/cgi/");
PassThru("cp $source_dir/sched/feeder $this->project_dir/cgi/");
$f = fopen("$this->project_dir/cgi/config.xml", "w");
fputs($f, "<config>\n");
fputs($f, " <db_name>$this->db_name</db_name>\n");
fputs($f, " <db_passwd>$this->db_passwd</db_passwd>\n");
fputs($f, " <shmem_key>$this->shmem_key</shmem_key>\n");
fputs($f, " <key_dir>$this->key_dir</key_dir>\n");
fputs($f, " <upload_dir>$this->project_dir/upload</upload_dir>\n");
fputs($f, " <user_name>$this->user_name</user_name>\n");
fputs($f, "</config>\n");
fclose($f);
// copy the user and administrative PHP files to the project dir,
//
PassThru("cp -f $source_dir/html_user/* $this->project_dir/html_user");
PassThru("cp -f $source_dir/html_ops/* $this->project_dir/html_ops");
// put a file with the database name in each directory
//
$f = fopen("$this->project_dir/html_user/db_name", "w");
fputs($f, "$this->db_name\n");
fclose($f);
$f = fopen("$this->project_dir/html_ops/db_name", "w");
fputs($f, "$this->db_name\n");
fclose($f);
// edit "index.html" in the user directory to have
// the right scheduler URL
//
$u = str_replace("/", "\\\/", $this->scheduler_url);
$x = "sed -e s/SCHEDULER_URL/$u/ $this->project_dir/html_user/index.html > temp; mv temp $this->project_dir/html_user/index.html";
echo "$x\n";
PassThru($x);
// create symbolic links to the CGI and HTML directories
//
$cgi_dir = get_env_var("BOINC_CGI_DIR");
$cgi_url = get_env_var("BOINC_CGI_URL");
$html_dir = get_env_var("BOINC_HTML_DIR");
$html_url = get_env_var("BOINC_HTML_URL");
PassThru("rm -f $cgi_dir/$this->name");
PassThru("ln -s $this->project_dir/cgi $cgi_dir/$this->name");
PassThru("rm -f $html_dir/$this->name");
PassThru("ln -s $this->project_dir $html_dir/$this->name");
}
function start(){
PassThru("cd $this->project_dir/cgi; feeder -asynch > feeder_out");
}
function stop() {
$f = fopen($this->project_dir."/cgi/feeder_trigger", "w");
fputs($f, "<quit/>\n");
fclose($f);
}
function check_results_done() {
db_open($this->db_name);
$result = mysql_query("select * from result where state<>4");
while ($x = mysql_fetch_object($result)) {
echo "result $x->id is not done\n";
}
}
function compare_file($result, $correct) {
PassThru("diff $this->project_dir/upload/$result $correct", $retval);
if ($retval) {
echo "File mismatch: $out $correct\n";
} else {
echo "Files match: $out $correct\n";
}
}
}
class User {
var $name;
var $authenticator;
function User() {
$this->name = "John";
$this->email_addr = "john@boinc.org";
$this->authenticator = "3f7b90793a0175ad0bda68684e8bd136";
}
}
class Host {
var $name;
var $projects;
var $user;
var $host_dir;
function Host($user) {
$this->user = $user;
$this->name = "test";
$this->projects = array();
}
function add_project($project) {
array_push($this->projects, $project);
}
function install() {
$base_dir = get_env_var("BOINC_HOSTS_DIR");
$this->host_dir = $base_dir."/".$this->name;
$user = $this->user;
PassThru("rm -rf $this->host_dir");
PassThru("mkdir $this->host_dir");
// create account files
//
echo "creating account files\n";
for ($i=0; $i<sizeof($this->projects); $i++) {
$project = $this->projects[$i];
$encoded_name = strtr($project->name, "/", "_");
echo "writing $this->host_dir/account_$encoded_name.xml\n";
$f = fopen($this->host_dir."/account_$encoded_name.xml", "w");
fputs($f, "<account>\n");
fputs($f, " <master_url>$project->master_url</master_url>\n");
fputs($f, " <authenticator>$user->authenticator</authenticator>\n");
fputs($f, " <resource_share>1</resource_share>\n");
fputs($f, "</account>\n");
fclose($f);
}
// copy log_flags.xml
//
PassThru("cp log_flags.xml $this->host_dir");
}
function run($args) {
echo "Running core client\n";
$source_dir = get_env_var("BOINC_SRC_DIR");
$platform = get_env_var("BOINC_PLATFORM");
PassThru("cd $this->host_dir; $source_dir/client/boinc_1_$platform $args");
}
}
class Work {
var $project;
var $app;
var $wu_template;
var $result_template;
var $nresults;
var $input_files;
function Work($project, $app) {
$this->project = $project;
$this->app = $app;
$this->input_files = array();
}
function install() {
$project = $this->project;
$app = $this->app;
for ($i=0; $i<sizeof($this->input_files); $i++) {
$x = $this->input_files[$i];
PassThru("cp $x $project->project_dir/download");
}
$cmd = "create_work -db_name $project->db_name -download_dir $project->project_dir/download -upload_url $project->upload_url -download_url $project->download_url/ -keyfile $project->key_dir/upload_private -appname $app->name -rsc_iops 180000000000.0 -rsc_fpops 0.0 -wu_name $this->wu_template -wu_template $this->wu_template -result_template $this->result_template -nresults $this->nresults ";
for ($i=0; $i<sizeof($this->input_files); $i++) {
$x = $this->input_files[$i];
$cmd = $cmd." ".$x;
}
run_tool($cmd);
}
}

View File

@ -1,33 +1,35 @@
#! /usr/local/bin/php
<?php
// test the uc (upper-case) application
//
// You must have done "make" in all source directories
include_once("test.inc");
include_once("init.inc");
$project = new Project;
$user = new User();
$host = new Host($user);
$app = new App("upper_case");
$app_version = new App_Version($app);
check_env_vars();
clear_db();
if (true) {
clear_server_dirs(false);
} else {
clear_server_dirs(true);
create_keys();
}
clear_client_dirs();
init_client_dirs("prefs1.xml", "account1.xml");
copy_to_download_dir("input");
add_project("Test Project");
add_platform(null);
add_user(null);
add_app("upper_case", null, null);
add_core_client(null);
create_work("-appname upper_case -rsc_iops 180000000000.0 -rsc_fpops 0.0 -wu_name uc_wu -wu_template uc_wu -result_template uc_result -nresults 2 input input input input input");
start_feeder();
//run_client("-exit_after 10");
run_client("-exit_when_idle");
stop_feeder();
check_results_done();
compare_file("uc_wu_0_0", "uc_correct_output");
compare_file("uc_wu_1_0", "uc_correct_output");
$project->add_user($user);
$project->add_app($app);
$project->add_app_version($app_version);
$project->install(); // must install projects before adding to hosts
$host->add_project($project);
$host->install();
echo "adding work\n";
$work = new Work($project, $app);
$work->wu_template = "uc_wu";
$work->result_template = "uc_result";
$work->nresults = 2;
array_push($work->input_files, "input");
$work->install();
$project->start();
$host->run("-exit_when_idle");
$project->stop();
$project->check_results_done();
$project->compare_file("uc_wu_0_0", "uc_correct_output");
$project->compare_file("uc_wu_1_0", "uc_correct_output");
?>

View File

@ -57,11 +57,11 @@ int version, retval, nexec_files;
double nbytes;
bool signed_exec_files;
char buf[256], md5_cksum[64];
char *app_name=0, *platform_name=0, *project_name=0;
char *db_name=0, *db_passwd=0, *app_name=0, *platform_name=0, *project_name=0;
char* exec_dir=0, *exec_files[10], *signature_files[10];
char *email_addr=0, *user_name=0, *web_password=0, *authenticator=0;
char *global_prefs_file=0, *download_dir, *download_url;
char* code_sign_keyfile;
char* code_sign_keyfile=0;
char *message=0, *message_priority=0;
void add_project() {
@ -248,12 +248,12 @@ void add_user() {
int main(int argc, char** argv) {
int i, retval;
retval = db_open(getenv("BOINC_DB_NAME"), getenv("BOINC_DB_PASSWD"));
if (retval) {
printf("can't open DB %s\n", getenv("BOINC_DB_NAME"));
}
for (i=2; i<argc; i++) {
if (!strcmp(argv[i], "-project_name")) {
if (!strcmp(argv[i], "-db_name")) {
db_name = argv[++i];
} else if (!strcmp(argv[i], "-db_passwd")) {
db_passwd = argv[++i];
} else if (!strcmp(argv[i], "-project_name")) {
i++;
project_name = argv[i];
} else if (!strcmp(argv[i], "-app_name")) {
@ -321,6 +321,11 @@ int main(int argc, char** argv) {
code_sign_keyfile = argv[i];
}
}
retval = db_open(db_name, db_passwd);
if (retval) {
fprintf(stderr, "can't open DB %s\n", db_name);
exit(1);
}
if (!strcmp(argv[1], "project")) {
add_project();
} else if (!strcmp(argv[1], "app")) {

View File

@ -61,12 +61,13 @@ int read_filename(char* path, char* buf) {
//
static int process_wu_template(
char* wu_name, char* tmplate, char* out,
char* dirpath, char** infiles, int n
char* dirpath, char** infiles, int n,
char* upload_url, char* download_url
) {
char* p;
char buf[MAX_BLOB_SIZE], md5[33], path[256];
bool found;
int i;
int i, retval;
double nbytes;
assert(wu_name!=NULL);
assert(tmplate!=NULL);
@ -82,7 +83,7 @@ static int process_wu_template(
found = true;
i = atoi(p+strlen(INFILE_MACRO));
if (i >= n) {
fprintf(stderr, "invalid file number\n");
fprintf(stderr, "process_wu_template: invalid file number\n");
return 1;
}
strcpy(buf, p+strlen(INFILE_MACRO)+1+2); // assume <= 10 files
@ -93,14 +94,14 @@ static int process_wu_template(
if (p) {
found = true;
strcpy(buf, p+strlen(UPLOAD_URL_MACRO));
strcpy(p, getenv("BOINC_UPLOAD_URL"));
strcpy(p, upload_url);
strcat(p, buf);
}
p = strstr(out, DOWNLOAD_URL_MACRO);
if (p) {
found = true;
strcpy(buf, p+strlen(DOWNLOAD_URL_MACRO));
strcpy(p, getenv("BOINC_DOWNLOAD_URL"));
strcpy(p, download_url);
strcat(p, buf);
}
p = strstr(out, MD5_MACRO);
@ -108,11 +109,15 @@ static int process_wu_template(
found = true;
i = atoi(p+strlen(MD5_MACRO));
if (i >= n) {
fprintf(stderr, "invalid file number\n");
fprintf(stderr, "process_wu_template: invalid file number\n");
return 1;
}
sprintf(path, "%s/%s", dirpath, infiles[i]);
md5_file(path, md5, nbytes);
retval = md5_file(path, md5, nbytes);
if (retval) {
fprintf(stderr, "process_wu_template: md5_file %d\n", retval);
return 1;
}
strcpy(buf, p+strlen(MD5_MACRO)+1+2); // assume <= 10 files
strcpy(p, md5);
strcat(p, buf);
@ -130,7 +135,8 @@ static int process_wu_template(
}
int create_result(
WORKUNIT& wu, char* result_template_filename, int i, R_RSA_PRIVATE_KEY& key
WORKUNIT& wu, char* result_template_filename, int i, R_RSA_PRIVATE_KEY& key,
char* upload_url, char* download_url
) {
RESULT r;
char base_outfile_name[256];
@ -155,7 +161,8 @@ int create_result(
result_template_file,
tempfile,
key,
base_outfile_name, wu.name, r.name
base_outfile_name, wu.name, r.name,
upload_url, download_url
);
rewind(tempfile);
read_file(tempfile, r.xml_doc_in);
@ -176,7 +183,8 @@ int create_work(
char* infile_dir,
char** infiles,
int ninfiles,
R_RSA_PRIVATE_KEY& key
R_RSA_PRIVATE_KEY& key,
char* upload_url, char* download_url
) {
int i, retval;
assert(wu_template!=NULL);
@ -188,20 +196,30 @@ int create_work(
wu.create_time = time(0);
retval = process_wu_template(
wu.name, wu_template, wu.xml_doc, infile_dir, infiles, ninfiles
wu.name, wu_template, wu.xml_doc, infile_dir, infiles, ninfiles,
upload_url, download_url
);
if (retval) return retval;
if (retval) {
fprintf(stderr, "process_wu_template: %d\n", retval);
return retval;
}
if (wu.dynamic_results) {
wu.max_results = nresults;
} else {
wu.nresults_unsent = nresults;
}
retval = db_workunit_new(wu);
if (retval) {
fprintf(stderr, "create_work: db_workunit_new %d\n", retval);
return retval;
}
wu.id = db_insert_id();
if (!wu.dynamic_results) {
for (i=0; i<nresults; i++) {
create_result(wu, result_template_file, i, key);
create_result(
wu, result_template_file, i, key, upload_url, download_url
);
}
}
return 0;

View File

@ -22,7 +22,8 @@
extern int process_result_template(
FILE* in, FILE* out,
R_RSA_PRIVATE_KEY& key,
char* base_filename, char* wu_name, char* result_name
char* base_filename, char* wu_name, char* result_name,
char* upload_url, char* download_url
);
extern int read_file(FILE*, char* buf);
@ -36,7 +37,9 @@ extern int create_work(
char* infile_dir,
char** infiles,
int ninfiles,
R_RSA_PRIVATE_KEY&
R_RSA_PRIVATE_KEY&,
char* upload_url,
char* download_url
);
extern int grant_credit(int resultid, double cobblestones);

View File

@ -19,6 +19,7 @@
// create_work
// -appname name
// -download_dir x
// -rsc_fpops n
// -rsc_iops n
// -rsc_memory n
@ -58,20 +59,14 @@ int main(int argc, char** argv) {
char** infiles;
int i, ninfiles, nresults;
R_RSA_PRIVATE_KEY key;
char* boinc_download_dir = getenv("BOINC_DOWNLOAD_DIR");
char download_dir[256], db_name[256], db_passwd[256];
char upload_url[256], download_url[256];
srand(time(NULL));
if (!boinc_download_dir) {
printf("must define BOINC_DOWNLOAD_DIR");
exit(1);
}
if (db_open(getenv("BOINC_DB_NAME"), getenv("BOINC_DB_PASSWD"))) {
printf( "Error opening database.\n" );
exit(0);
}
strcpy(wu_template_file, "");
strcpy(result_template_file, "");
strcpy(app.name, "");
strcpy(db_passwd, "");
strcpy(keyfile, "");
nresults = 1;
i = 1;
@ -81,6 +76,16 @@ int main(int argc, char** argv) {
if (!strcmp(argv[i], "-appname")) {
i++;
strcpy(app.name, argv[i]);
} else if (!strcmp(argv[i], "-db_name")) {
strcpy(db_name, argv[++i]);
} else if (!strcmp(argv[i], "-db_passwd")) {
strcpy(db_passwd, argv[++i]);
} else if (!strcmp(argv[i], "-upload_url")) {
strcpy(upload_url, argv[++i]);
} else if (!strcmp(argv[i], "-download_url")) {
strcpy(download_url, argv[++i]);
} else if (!strcmp(argv[i], "-download_dir")) {
strcpy(download_dir, argv[++i]);
} else if (!strcmp(argv[i], "-wu_name")) {
i++;
strcpy(wu.name, argv[i]);
@ -123,41 +128,44 @@ int main(int argc, char** argv) {
if (!strlen(app.name) || !strlen(wu.name) || !strlen(wu_template_file)
|| !strlen(result_template_file)
) {
printf("bad cmdline\n");
fprintf(stderr, "create_work: bad cmdline\n");
exit(1);
}
if (db_open(db_name, db_passwd)) {
fprintf(stderr, "create_work: error opening database.\n" );
exit(0);
}
retval = db_app_lookup_name(app);
if (retval) {
printf("app not found\n");
fprintf(stderr, "create_work: app not found\n");
exit(1);
}
//fprintf(stderr, "wu_template = %s\n", wu_template);
retval = read_filename(wu_template_file, wu_template);
if (retval) {
fprintf(stderr, "can't open WU template\n");
fprintf(stderr, "create_work: can't open WU template\n");
exit(1);
}
if (wu.dynamic_results) {
strcpy(app.result_xml_template, result_template);
retval = db_app_update(app);
if (retval) printf("db_app_update: %d\n", retval);
if (retval) fprintf(stderr, "create_work: db_app_update: %d\n", retval);
}
wu.appid = app.id;
FILE* fkey = fopen(keyfile, "r");
rewind(fkey);
if (!fkey) {
printf("create_work: can't open key file (%s)\n", keyfile);
fprintf(stderr, "create_work: can't open key file (%s)\n", keyfile);
exit(1);
}
rewind(fkey);
retval = scan_key_hex(fkey, (KEY*)&key, sizeof(key));
fclose(fkey);
if (retval) {
printf("can't parse key\n");
fprintf(stderr, "create_work: can't parse key\n");
exit(1);
}
@ -166,10 +174,12 @@ int main(int argc, char** argv) {
wu_template,
result_template_file,
nresults,
boinc_download_dir,
download_dir,
infiles,
ninfiles,
key
key,
upload_url,
download_url
);
if (retval) fprintf(stderr, "create_work: %d\n", retval);
db_close();

View File

@ -41,7 +41,8 @@
int process_result_template(
FILE* in, FILE* out,
R_RSA_PRIVATE_KEY& key,
char* base_filename, char* wu_name, char* result_name
char* base_filename, char* wu_name, char* result_name,
char* upload_url, char* download_url
) {
char* p,*q, *signed_xml=strdup("");
char buf[256], temp[256];
@ -102,14 +103,14 @@ int process_result_template(
if (p) {
found = true;
strcpy(temp, p+strlen(UPLOAD_URL_MACRO));
strcpy(p, getenv("BOINC_UPLOAD_URL"));
strcpy(p, upload_url);
strcat(p, temp);
}
p = strstr(buf, DOWNLOAD_URL_MACRO);
if (p) {
found = true;
strcpy(temp, p+strlen(DOWNLOAD_URL_MACRO));
strcpy(p, getenv("BOINC_DOWNLOAD_URL"));
strcpy(p, download_url);
strcat(p, temp);
}
p = strstr(buf, WU_NAME_MACRO);