xml writing and parsing

svn path=/trunk/boinc/; revision=2401
This commit is contained in:
Karl Chen 2003-10-03 06:46:22 +00:00
parent cc7efbf814
commit 5453f279e4
9 changed files with 96 additions and 56 deletions

View File

@ -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

View File

@ -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 <tag>string</tag>
//
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;

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <cstdio>
#include <cstdlib>
#include <string>
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*);

View File

@ -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):

View File

@ -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')

View File

@ -19,8 +19,10 @@
// Parse a server configuration file
#include <stdio.h>
#include <string.h>
#include <cstring>
#include <string>
#include <fstream>
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, "</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, "<download_url>", download_url, sizeof(download_url))) continue;
else if (parse_str(buf, "<download_dir>", download_dir, sizeof(download_dir))) continue;
else if (parse_str(buf, "<upload_url>", upload_url, sizeof(upload_url))) 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;
}
parse_str(buf.c_str(), "<db_name>", db_name, sizeof(db_name));
parse_str(buf.c_str(), "<db_passwd>", db_passwd, sizeof(db_passwd));
parse_int(buf.c_str(), "<shmem_key>", shmem_key);
parse_str(buf.c_str(), "<key_dir>", key_dir, sizeof(key_dir));
parse_str(buf.c_str(), "<download_url>", download_url, sizeof(download_url));
parse_str(buf.c_str(), "<download_dir>", download_dir, sizeof(download_dir));
parse_str(buf.c_str(), "<upload_url>", upload_url, sizeof(upload_url));
parse_str(buf.c_str(), "<upload_dir>", upload_dir, sizeof(upload_dir));
parse_str(buf.c_str(), "<user_name>", user_name, sizeof(user_name));
if (match_tag(buf.c_str(), "</config>")) 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);
}

View File

@ -20,6 +20,9 @@
#ifndef _SCHED_CONFIG_
#define _SCHED_CONFIG_
#include <fstream>
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=".");
};

View File

@ -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)

View File

@ -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 <apps_dir> which specifies the directory to search.
config.xml must contain an <app_dir> which specifies the directory to search.
apps/boinc/ contains core client versions.
apps/APPLICATION_NAME/ contains application versions for each application.