diff --git a/checkin_notes b/checkin_notes index dddab61ed7..f6e1abac76 100755 --- a/checkin_notes +++ b/checkin_notes @@ -6511,6 +6511,7 @@ Karl 2003/10/02 Karl 2003/10/02 - made C parsing of config.xml more flexible (allow multiple tags per line or tags on multiple lines) + - made config.xml and run_state.xml pretty sched/ sched_config.C @@ -6519,3 +6520,5 @@ Karl 2003/10/02 parse.C parse.h + py/ + configxml.py diff --git a/lib/parse.C b/lib/parse.C index c0cd793202..0013a49aa4 100644 --- a/lib/parse.C +++ b/lib/parse.C @@ -2,18 +2,18 @@ // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt -// +// // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// +// University of California at Berkeley. All Rights Reserved. +// // Contributor(s): // @@ -74,11 +74,30 @@ bool parse_str(const char* buf, const char* tag, char* dest, int len) { char* p = strstr(buf, tag); if (!p) return false; p = strchr(p, '>'); - char* q = strchr(p+1, '<'); + ++p; + while (isspace(*p)) ++p; + char* q = strchr(p, '<'); if (!q) return false; + while (isspace(*(q-1))) --q; + char save_q = *q; *q = 0; - safe_strncpy(dest, p+1, len); - *q = '<'; + safe_strncpy(dest, p, len); + *q = save_q; + return true; +} + +// parse a string of the form string +// +bool parse_str(const char* buf, const char* tag, string& dest) { + char const* p = strstr(buf, tag); + if (!p) return false; + p = strchr(p, '>'); + ++p; + while (isspace(*p)) ++p; + char const* q = strchr(p, '<'); + if (!q) return false; + while (isspace(*(q-1))) --q; + dest.assign(p, q-p); return true; } @@ -251,7 +270,7 @@ bool extract_xml_record(const std::string &field, const char *tag, std::string & do { j=field.rfind(">",j-1); start_pos=field.rfind(tag,j); - if ((start_pos != std::string::npos) && (field[start_pos-1]!='/')) { + if ((start_pos != std::string::npos) && (field[start_pos-1]!='/')) { start_pos=field.rfind("<",start_pos); } else { start_pos=std::string::npos; diff --git a/lib/parse.h b/lib/parse.h index d9bf04f145..847670627b 100644 --- a/lib/parse.h +++ b/lib/parse.h @@ -2,29 +2,32 @@ // Version 1.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://boinc.berkeley.edu/license_1.0.txt -// +// // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// +// under the License. +// +// The Original Code is the Berkeley Open Infrastructure for Network Computing. +// // The Initial Developer of the Original Code is the SETI@home project. // Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// +// University of California at Berkeley. All Rights Reserved. +// // Contributor(s): // -#include -#include +#include +#include #include +using std::string; + extern bool parse(char* , char* ); extern bool parse_int(const char* buf, const char*tag, int&); extern bool parse_double(const char*, const char*, double&); extern bool parse_str(const char*, const char*, char*, int); +bool parse_str(const char* buf, const char* tag, string& dest); extern void parse_attr(const char* buf, const char* attrname, char* out, int len); extern bool match_tag(const char*, const char*); extern bool match_tag(const std::string &, const char*); diff --git a/py/Boinc/configxml.py b/py/Boinc/configxml.py index 4b88d0882a..540d1d6d05 100644 --- a/py/Boinc/configxml.py +++ b/py/Boinc/configxml.py @@ -120,7 +120,7 @@ class XMLConfig: except IOError, e: if not failopen_ok: # raise - raise SystemExit("%s: Couldn't parse XML config\n%s: %s"%(sys.argv[0],sys.argv[0],e)) + raise Exception("%s: Couldn't parse XML config\n%s: %s"%(sys.argv[0],sys.argv[0],e)) print >>sys.stderr, "Warning:", e # self.xml = xml.dom.minidom.Document() self._init_empty_xml() @@ -133,7 +133,7 @@ class XMLConfig: self._set_elements() if not output: output = open(self.filename,'w') - self.xml.writexml(output) + self.xml.writexml(output, "", " ", "\n") print >>output return self def _set_elements(self): diff --git a/py/Boinc/setup_project.py b/py/Boinc/setup_project.py index 8867ad60e5..92f30c8c7b 100644 --- a/py/Boinc/setup_project.py +++ b/py/Boinc/setup_project.py @@ -249,7 +249,7 @@ def num_wus(): def num_wus_assimilated(): return database.Workunits.count(assimilate_state = ASSIMILATE_DONE) def num_wus_to_transition(): - return database.Workunits.count(_extra_params = 'transition_time<%d'%(time.time()+30*86400)) + return database.Workunits.count(_extra_params = ['transition_time<%d'%(time.time()+30*86400)]) def build_command_line(cmd, **kwargs): for (key, value) in kwargs.items(): @@ -308,10 +308,11 @@ class Project: config.download_url = os.path.join(config.master_url, 'download') config.cgi_url = cgi_url or os.path.join(options.cgi_url, self.short_name) config.upload_url = os.path.join(config.cgi_url , 'file_upload_handler') - self.scheduler_url = os.path.join(config.cgi_url , 'cgi') config.download_dir = os.path.join(self.project_dir , 'download') config.upload_dir = os.path.join(self.project_dir , 'upload') config.key_dir = key_dir or os.path.join(self.project_dir , 'keys') + config.app_dir = os.path.join(self.project_dir, 'apps') + self.scheduler_url = os.path.join(config.cgi_url , 'cgi') self.project_php_file = srcdir('html_user/project.inc.sample') self.project_specific_prefs_php_file = srcdir('html_user/project_specific_prefs.inc.sample') diff --git a/sched/sched_config.C b/sched/sched_config.C index 6a37923c45..046ed0c085 100644 --- a/sched/sched_config.C +++ b/sched/sched_config.C @@ -19,8 +19,10 @@ // Parse a server configuration file -#include -#include +#include +#include +#include +using std::ifstream; #include "parse.h" #include "error_numbers.h" @@ -29,34 +31,38 @@ const char* CONFIG_FILE = "config.xml"; -int SCHED_CONFIG::parse(FILE* in) { - char buf[256]; +inline string read_stream(istream& f) { + string buf; + buf.reserve(8192); + char c; + while (f >> c) + buf += c; + return buf; +} + +int SCHED_CONFIG::parse(istream& f) { + string buf = read_stream(f); memset(this, 0, sizeof(SCHED_CONFIG)); - while (fgets(buf, 256, in)) { - if (match_tag(buf, "")) return 0; - else if (parse_str(buf, "", db_name, sizeof(db_name))) continue; - else if (parse_str(buf, "", db_passwd, sizeof(db_passwd))) continue; - else if (parse_int(buf, "", shmem_key)) continue; - else if (parse_str(buf, "", key_dir, sizeof(key_dir))) continue; - else if (parse_str(buf, "", download_url, sizeof(download_url))) continue; - else if (parse_str(buf, "", download_dir, sizeof(download_dir))) continue; - else if (parse_str(buf, "", upload_url, sizeof(upload_url))) continue; - else if (parse_str(buf, "", upload_dir, sizeof(upload_dir))) continue; - else if (parse_str(buf, "", user_name, sizeof(user_name))) continue; - } + parse_str(buf.c_str(), "", db_name, sizeof(db_name)); + parse_str(buf.c_str(), "", db_passwd, sizeof(db_passwd)); + parse_int(buf.c_str(), "", shmem_key); + parse_str(buf.c_str(), "", key_dir, sizeof(key_dir)); + parse_str(buf.c_str(), "", download_url, sizeof(download_url)); + parse_str(buf.c_str(), "", download_dir, sizeof(download_dir)); + parse_str(buf.c_str(), "", upload_url, sizeof(upload_url)); + parse_str(buf.c_str(), "", upload_dir, sizeof(upload_dir)); + parse_str(buf.c_str(), "", user_name, sizeof(user_name)); + if (match_tag(buf.c_str(), "")) return 0; return ERR_XML_PARSE; } int SCHED_CONFIG::parse_file(char* dir) { - FILE* f; + ifstream f; char path[256]; - int retval; sprintf(path, "%s/%s", dir, CONFIG_FILE); - f = fopen(path, "r"); + f.open(path); if (!f) return ERR_FOPEN; - retval = parse(f); - fclose(f); - return retval; + return parse(f); } diff --git a/sched/sched_config.h b/sched/sched_config.h index 0d868c1935..2334e5d33f 100644 --- a/sched/sched_config.h +++ b/sched/sched_config.h @@ -20,6 +20,9 @@ #ifndef _SCHED_CONFIG_ #define _SCHED_CONFIG_ +#include +using std::istream; + // parsed version of server configuration file // class SCHED_CONFIG { @@ -34,7 +37,7 @@ public: char upload_dir[256]; char user_name[256]; - int parse(FILE*); + int parse(istream& f); int parse_file(char* dir="."); }; diff --git a/test/testbase.py b/test/testbase.py index f7fd16b441..2859bec41e 100644 --- a/test/testbase.py +++ b/test/testbase.py @@ -242,6 +242,8 @@ class TestProject(Project): kwargs['short_name'] = kwargs.get('short_name') or 'test_'+appname kwargs['long_name'] = kwargs.get('long_name') or 'Project ' + kwargs['short_name'].replace('_',' ').capitalize() + apply(Project.__init__, [self], kwargs) + (num_wu, redundancy) = get_redundancy_args(num_wu, redundancy) self.resource_share = resource_share or 1 self.num_wu = num_wu @@ -253,9 +255,8 @@ class TestProject(Project): self.platforms = [Platform()] self.core_versions = core_versions or [CoreVersion(self.platforms[0])] - self.app_versions = app_versions or [AppVersion(App(appname), - self.platforms[0], - appname)] + self.app_versions = app_versions or [ + AppVersion(App(appname), self.platforms[0], appname)] self.apps = apps or unique(map(lambda av: av.app, self.app_versions)) # convenience vars: self.app_version = self.app_versions[0] @@ -265,7 +266,6 @@ class TestProject(Project): self.work = self.works[0] self.user = self.users[0] self.host = self.hosts[0] - apply(Project.__init__, [self], kwargs) self.started = False def init_install(self): @@ -433,10 +433,12 @@ class CoreVersion(database.CoreVersion): database.CoreVersion.__init__(self) self.version_num = 1 self.platform = platform + def commit(self): self.xml_doc = tools.process_executable_file( os.path.join(boinc_path_config.TOP_BUILD_DIR,'client', options.client_bin_filename), quiet=True) + database.CoreVersion.commit(self) class User(database.User): def __init__(self): @@ -457,12 +459,15 @@ class AppVersion(database.AppVersion): self.app = app self.version_num = 1 self.platform = platform - self.xml_doc = tools.process_app_version( - app, self.version_num, - [os.path.join(boinc_path_config.TOP_BUILD_DIR,'apps',exec_file)], - quiet=True) self.min_core_version = 1 self.max_core_version = 999 + self._exec_file=exec_file + def commit(self): + self.xml_doc = tools.process_app_version( + self.app, self.version_num, + [os.path.join(boinc_path_config.TOP_BUILD_DIR,'apps',self._exec_file)], + quiet=True) + database.AppVersion.commit(self) class HostList(list): def run(self, asynch=False): map(lambda i: i.run(asynch=asynch), self) diff --git a/tools/update_versions b/tools/update_versions index cf05c07254..bd1d5ce558 100755 --- a/tools/update_versions +++ b/tools/update_versions @@ -6,7 +6,7 @@ Scans apps dir for current core client and application versions and updates the database as appropriate. -config.xml must contain an which specifies the directory to search. +config.xml must contain an which specifies the directory to search. apps/boinc/ contains core client versions. apps/APPLICATION_NAME/ contains application versions for each application.