mirror of https://github.com/BOINC/boinc.git
xml writing and parsing
svn path=/trunk/boinc/; revision=2401
This commit is contained in:
parent
cc7efbf814
commit
5453f279e4
|
@ -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
|
||||
|
|
41
lib/parse.C
41
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 <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;
|
||||
|
|
21
lib/parse.h
21
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 <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*);
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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')
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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=".");
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue