mirror of https://github.com/BOINC/boinc.git
client: parse keyword file and export keywords in get_state() GUI RPC
- This adds overhead to the get_state() call, but this happens only once per minute with the Manager. - rename things so that "keyword_ids" refers to lists of keyword IDs and "keywords" refers to full KEYWORD objects - have boinccmd include keywords in workunit properties
This commit is contained in:
parent
093e00a07c
commit
d15d0b95de
|
@ -484,6 +484,26 @@ int CLIENT_STATE::init() {
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
// parse keyword file if present
|
||||
//
|
||||
f = fopen(KEYWORD_FILENAME, "r");
|
||||
if (f) {
|
||||
MIOFILE mf;
|
||||
mf.init_file(f);
|
||||
XML_PARSER xp(&mf);
|
||||
retval = keywords.parse(xp);
|
||||
if (!retval) keywords.present = true;
|
||||
fclose(f);
|
||||
#if 0
|
||||
std::map<int, KEYWORD>::iterator it;
|
||||
for (it = keywords.keywords.begin(); it != keywords.keywords.end(); it++) {
|
||||
int id = it->first;
|
||||
KEYWORD& kw = it->second;
|
||||
printf("keyword %d: %s\n", id, kw.name.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
parse_account_files();
|
||||
parse_statistics_files();
|
||||
|
||||
|
|
|
@ -1125,8 +1125,8 @@ int WORKUNIT::parse(XML_PARSER& xp) {
|
|||
#endif
|
||||
continue;
|
||||
}
|
||||
if (xp.parse_str("job_keywords", buf, sizeof(buf))) {
|
||||
job_keywords.parse_str(buf );
|
||||
if (xp.parse_str("job_keyword_ids", buf, sizeof(buf))) {
|
||||
job_keyword_ids.parse_str(buf );
|
||||
continue;
|
||||
}
|
||||
// unused stuff
|
||||
|
@ -1176,13 +1176,13 @@ int WORKUNIT::write(MIOFILE& out, bool gui) {
|
|||
input_files[i].write(out);
|
||||
}
|
||||
|
||||
if (!job_keywords.empty()) {
|
||||
if (!job_keyword_ids.empty()) {
|
||||
if (gui) {
|
||||
if (gstate.keywords.present) {
|
||||
job_keywords.write_xml_text(out, gstate.keywords);
|
||||
job_keyword_ids.write_xml_text(out, gstate.keywords);
|
||||
}
|
||||
} else {
|
||||
job_keywords.write_xml_num(out);
|
||||
job_keyword_ids.write_xml_num(out);
|
||||
}
|
||||
}
|
||||
out.printf("</workunit>\n");
|
||||
|
|
|
@ -368,7 +368,7 @@ struct WORKUNIT {
|
|||
double rsc_fpops_bound;
|
||||
double rsc_memory_bound;
|
||||
double rsc_disk_bound;
|
||||
JOB_KEYWORDS job_keywords;
|
||||
JOB_KEYWORD_IDS job_keyword_ids;
|
||||
|
||||
WORKUNIT(){
|
||||
safe_strcpy(name, "");
|
||||
|
@ -376,7 +376,7 @@ struct WORKUNIT {
|
|||
version_num = 0;
|
||||
command_line = "";
|
||||
input_files.clear();
|
||||
job_keywords.clear();
|
||||
job_keyword_ids.clear();
|
||||
project = NULL;
|
||||
app = NULL;
|
||||
ref_cnt = 0;
|
||||
|
|
|
@ -74,6 +74,7 @@ extern void send_log_after(const char* filename, double t, MIOFILE& mf);
|
|||
#define GLOBAL_PREFS_FILE_NAME "global_prefs.xml"
|
||||
#define GLOBAL_PREFS_OVERRIDE_FILE "global_prefs_override.xml"
|
||||
#define JOB_LOG_BASE "job_log_"
|
||||
#define KEYWORD_FILENAME "keywords.xml"
|
||||
#define LOOKUP_ACCOUNT_FILENAME "lookup_account.xml"
|
||||
#define LOOKUP_WEBSITE_FILENAME "lookup_website.html"
|
||||
#define MASTER_BASE "master_"
|
||||
|
|
|
@ -334,6 +334,7 @@ int RPC_CLIENT::get_reply(char*& mbuf) {
|
|||
if (n <= 0) return ERR_READ;
|
||||
buf[n]=0;
|
||||
mf.puts(buf);
|
||||
printf("%s\n", buf);
|
||||
if (strchr(buf, '\003')) break;
|
||||
}
|
||||
mf.get_buf(mbuf, n);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "common_defs.h"
|
||||
#include "filesys.h"
|
||||
#include "hostinfo.h"
|
||||
#include "keyword.h"
|
||||
#include "miofile.h"
|
||||
#include "network.h"
|
||||
#include "notice.h"
|
||||
|
@ -232,6 +233,7 @@ struct WORKUNIT {
|
|||
double rsc_disk_bound;
|
||||
PROJECT* project;
|
||||
APP* app;
|
||||
JOB_KEYWORDS job_keywords;
|
||||
|
||||
WORKUNIT();
|
||||
|
||||
|
|
|
@ -601,6 +601,10 @@ int WORKUNIT::parse(XML_PARSER& xp) {
|
|||
if (xp.parse_double("rsc_fpops_bound", rsc_fpops_bound)) continue;
|
||||
if (xp.parse_double("rsc_memory_bound", rsc_memory_bound)) continue;
|
||||
if (xp.parse_double("rsc_disk_bound", rsc_disk_bound)) continue;
|
||||
if (xp.match_tag("job_keywords")) {
|
||||
job_keywords.parse(xp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,13 @@ void WORKUNIT::print() {
|
|||
printf(" FP bound: %e\n", rsc_fpops_bound);
|
||||
printf(" memory bound: %.2f MB\n", rsc_memory_bound/MEGA);
|
||||
printf(" disk bound: %.2f MB\n", rsc_disk_bound/MEGA);
|
||||
if (!job_keywords.empty()) {
|
||||
printf(" keywords:\n");
|
||||
for (unsigned int i=0; i<job_keywords.keywords.size(); i++) {
|
||||
KEYWORD &kw = job_keywords.keywords[i];
|
||||
printf(" %s\n", kw.name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RESULT::print() {
|
||||
|
|
|
@ -27,6 +27,7 @@ int KEYWORD::parse(XML_PARSER& xp) {
|
|||
if (xp.match_tag("/keyword")) {
|
||||
return 0;
|
||||
}
|
||||
if (xp.parse_int("id", id)) continue;
|
||||
if (xp.parse_string("name", name)) continue;
|
||||
if (xp.parse_string("description", description)) continue;
|
||||
if (xp.parse_int("parent", parent)) continue;
|
||||
|
@ -43,16 +44,27 @@ void KEYWORD::write_xml(MIOFILE& mf) {
|
|||
" <description>%s</description>\n"
|
||||
" <parent>%d</parent>\n"
|
||||
" <level>%d</level>\n"
|
||||
" <category>%d</category>\n",
|
||||
name, description, parent, level, category
|
||||
" <category>%d</category>\n"
|
||||
"</keyword>\n",
|
||||
name.c_str(), description.c_str(), parent, level, category
|
||||
);
|
||||
}
|
||||
|
||||
int KEYWORDS::parse(XML_PARSER& xp) {
|
||||
while (!xp.get_tag()) {
|
||||
if (xp.match_tag("/keyword")) {
|
||||
if (xp.match_tag("/keywords")) {
|
||||
return 0;
|
||||
}
|
||||
if (xp.match_tag("keyword")) {
|
||||
KEYWORD kw;
|
||||
int retval = kw.parse(xp);
|
||||
if (retval) {
|
||||
printf("KEYWORD parse fail: %d\n", retval);
|
||||
return retval;
|
||||
}
|
||||
keywords[kw.id] = kw;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
@ -88,7 +100,7 @@ void USER_KEYWORDS::write(FILE* f) {
|
|||
fprintf(f, "</user_keywords>\n");
|
||||
}
|
||||
|
||||
void JOB_KEYWORDS::parse_str(char* buf) {
|
||||
void JOB_KEYWORD_IDS::parse_str(char* buf) {
|
||||
char* p = strtok(buf, " ");
|
||||
if (!p) return;
|
||||
ids.push_back(atoi(p));
|
||||
|
@ -99,7 +111,9 @@ void JOB_KEYWORDS::parse_str(char* buf) {
|
|||
}
|
||||
}
|
||||
|
||||
void JOB_KEYWORDS::write_xml_text(MIOFILE& mf, KEYWORDS& k) {
|
||||
// write list of full keywords
|
||||
//
|
||||
void JOB_KEYWORD_IDS::write_xml_text(MIOFILE& mf, KEYWORDS& k) {
|
||||
mf.printf("<job_keywords>\n");
|
||||
for (unsigned int i=0; i<ids.size(); i++) {
|
||||
int id = ids[i];
|
||||
|
@ -108,9 +122,11 @@ void JOB_KEYWORDS::write_xml_text(MIOFILE& mf, KEYWORDS& k) {
|
|||
mf.printf("</job_keywords>\n");
|
||||
}
|
||||
|
||||
void JOB_KEYWORDS::write_xml_num(MIOFILE& out) {
|
||||
// write 1-line list of keyword IDs
|
||||
//
|
||||
void JOB_KEYWORD_IDS::write_xml_num(MIOFILE& out) {
|
||||
bool first = true;
|
||||
out.printf(" <keywords>");
|
||||
out.printf(" <job_keyword_ids>");
|
||||
for (unsigned int i=0; i<ids.size(); i++) {
|
||||
if (first) {
|
||||
out.printf("%d", ids[i]);
|
||||
|
@ -119,5 +135,20 @@ void JOB_KEYWORDS::write_xml_num(MIOFILE& out) {
|
|||
out.printf(", %d", ids[i]);
|
||||
}
|
||||
}
|
||||
out.printf("</keywords>\n");
|
||||
out.printf("</job_keyword_ids>\n");
|
||||
}
|
||||
|
||||
int JOB_KEYWORDS::parse(XML_PARSER& xp) {
|
||||
while (!xp.get_tag()) {
|
||||
if (xp.match_tag("/job_keywords")) {
|
||||
return 0;
|
||||
}
|
||||
if (xp.match_tag("keyword")) {
|
||||
KEYWORD kw;
|
||||
int retval = kw.parse(xp);
|
||||
if (retval) return retval;
|
||||
keywords.push_back(kw);
|
||||
}
|
||||
}
|
||||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
#define BOINC_KEYWORD_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "parse.h"
|
||||
|
||||
// a keyword
|
||||
//
|
||||
struct KEYWORD {
|
||||
int id;
|
||||
std::string name;
|
||||
|
@ -35,6 +38,8 @@ struct KEYWORD {
|
|||
int parse(XML_PARSER&);
|
||||
};
|
||||
|
||||
// the set of all keywords
|
||||
//
|
||||
struct KEYWORDS {
|
||||
std::map<int, KEYWORD> keywords;
|
||||
bool present;
|
||||
|
@ -45,6 +50,8 @@ struct KEYWORDS {
|
|||
inline KEYWORD& get(int id) {return keywords[id];}
|
||||
};
|
||||
|
||||
// a user's keyword preferences
|
||||
//
|
||||
struct USER_KEYWORDS {
|
||||
std::vector<int> yes;
|
||||
std::vector<int> no;
|
||||
|
@ -59,7 +66,9 @@ struct USER_KEYWORDS {
|
|||
}
|
||||
};
|
||||
|
||||
struct JOB_KEYWORDS {
|
||||
// the keywords IDs associated with a job (workunit)
|
||||
//
|
||||
struct JOB_KEYWORD_IDS {
|
||||
std::vector<int> ids;
|
||||
void parse_str(char*);
|
||||
// parse space-separated list
|
||||
|
@ -73,4 +82,18 @@ struct JOB_KEYWORDS {
|
|||
void write_xml_num(MIOFILE&);
|
||||
};
|
||||
|
||||
// same, but the entire keyword objects (for GUI RPC client)
|
||||
//
|
||||
struct JOB_KEYWORDS {
|
||||
std::vector<KEYWORD> keywords;
|
||||
inline bool empty() {
|
||||
return keywords.empty();
|
||||
}
|
||||
inline void clear() {
|
||||
keywords.clear();
|
||||
}
|
||||
int parse(XML_PARSER&);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
//
|
||||
// A job's keywords are stored in workunit.keywords as a char string.
|
||||
// We don't want to parse that every time we score the job,
|
||||
// so we maintain a list of JOB_KEYWORDs paralleling the job array.
|
||||
// so we maintain a list of JOB_KEYWORD_IDS paralleling the job array.
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
@ -27,13 +27,13 @@
|
|||
#include "sched_main.h"
|
||||
#include "keyword.h"
|
||||
|
||||
JOB_KEYWORDS *job_keywords_array;
|
||||
JOB_KEYWORD_IDS *job_keywords_array;
|
||||
|
||||
// compute the score increment for the given job and user keywords
|
||||
// (or -1 if the keywords are incompatible)
|
||||
//
|
||||
double keyword_score_aux(
|
||||
USER_KEYWORDS& uks, JOB_KEYWORDS& jks
|
||||
USER_KEYWORDS& uks, JOB_KEYWORD_IDS& jks
|
||||
) {
|
||||
double score = 0;
|
||||
|
||||
|
@ -61,7 +61,7 @@ double keyword_score(int i) {
|
|||
|
||||
// parse job keywords if not already done
|
||||
//
|
||||
JOB_KEYWORDS& jk = job_keywords_array[i];
|
||||
JOB_KEYWORD_IDS& jk = job_keywords_array[i];
|
||||
if (jk.empty()) {
|
||||
WU_RESULT& wr = ssp->wu_results[i];
|
||||
if (empty(wr.workunit.keywords)) {
|
||||
|
@ -88,5 +88,5 @@ void keyword_sched_remove_job(int i) {
|
|||
// called at CGI start to initialize job keyword array
|
||||
//
|
||||
void keyword_sched_init() {
|
||||
job_keywords_array = new JOB_KEYWORDS[ssp->max_wu_results];
|
||||
job_keywords_array = new JOB_KEYWORD_IDS[ssp->max_wu_results];
|
||||
}
|
||||
|
|
|
@ -556,7 +556,7 @@ static int insert_wu_tags(WORKUNIT& wu, APP& app) {
|
|||
if (!empty(wu.keywords)) {
|
||||
char buf2[1024];
|
||||
sprintf(buf2,
|
||||
" <job_keywords>%s</job_keywords>\n",
|
||||
" <job_keyword_ids>%s</job_keyword_ids>\n",
|
||||
wu.keywords
|
||||
);
|
||||
strcat(buf, buf2);
|
||||
|
|
Loading…
Reference in New Issue