mirror of https://github.com/BOINC/boinc.git
new preferences scheme
svn path=/trunk/boinc/; revision=444
This commit is contained in:
parent
c12b1df84b
commit
cbf997aa71
|
@ -1992,3 +1992,34 @@ David Sept 26 2002
|
|||
test_uc.php
|
||||
tools/
|
||||
add.C
|
||||
|
||||
David Sept 28 2002
|
||||
- Clarified the way that preferences (global and project)
|
||||
are stored in the database and in the core client,
|
||||
and the protocol (part of scheduler RPC) for maintaining them.
|
||||
See doc/prefs_impl.html
|
||||
- Implemented the above: lots of small changes to client, server
|
||||
- Changed names from "prefs" to "global_prefs" where relevant
|
||||
|
||||
client/
|
||||
client_state.C,h
|
||||
client_types.C,h
|
||||
cs_scheduler.C
|
||||
file_names.C,h
|
||||
prefs.C,h
|
||||
scheduler_op.C,h
|
||||
db/
|
||||
db.h
|
||||
db_mysql.C
|
||||
schema.sql
|
||||
doc/
|
||||
boinc_dev.html
|
||||
prefs_impl.html (new)
|
||||
prefs_mod.html (removed)
|
||||
html_user/
|
||||
prefs.inc
|
||||
sched/
|
||||
handle_request.C
|
||||
server_types.C,h
|
||||
tools/
|
||||
add.C
|
||||
|
|
|
@ -64,20 +64,11 @@ int CLIENT_STATE::init() {
|
|||
//
|
||||
nslots = 1;
|
||||
|
||||
// Read the user preferences file, if it exists.
|
||||
// Read the global preferences file, if it exists.
|
||||
//
|
||||
retval = prefs.parse_file();
|
||||
retval = global_prefs.parse_file();
|
||||
if (retval) {
|
||||
retval = write_initial_prefs();
|
||||
if (retval) {
|
||||
printf("can't initialize prefs.xml\n");
|
||||
return retval;
|
||||
}
|
||||
retval = prefs.parse_file();
|
||||
if (retval) {
|
||||
printf("can't initialize prefs.xml\n");
|
||||
return retval;
|
||||
}
|
||||
printf("No global preferences file; will use defaults.\n");
|
||||
}
|
||||
|
||||
// parse account files.
|
||||
|
@ -192,11 +183,14 @@ double CLIENT_STATE::allowed_disk_usage() {
|
|||
double percent_space, min_val;
|
||||
|
||||
// Calculate allowed disk usage based on % pref
|
||||
percent_space = host_info.d_total*prefs.disk_max_used_pct/100.0;
|
||||
//
|
||||
percent_space = host_info.d_total*global_prefs.disk_max_used_pct/100.0;
|
||||
|
||||
min_val = host_info.d_free - global_prefs.disk_min_free_gb*1e9;
|
||||
|
||||
min_val = host_info.d_free - prefs.disk_min_free_gb*1e9;
|
||||
// Return the minimum of the three
|
||||
return min(min(prefs.disk_max_used_gb*1e9, percent_space), min_val);
|
||||
//
|
||||
return min(min(global_prefs.disk_max_used_gb*1e9, percent_space), min_val);
|
||||
}
|
||||
|
||||
// See if (on the basis of user prefs) we should suspend activities.
|
||||
|
@ -204,7 +198,7 @@ double CLIENT_STATE::allowed_disk_usage() {
|
|||
//
|
||||
int CLIENT_STATE::check_suspend_activities() {
|
||||
bool should_suspend = false;
|
||||
if (prefs.dont_run_on_batteries && host_is_running_on_batteries()) {
|
||||
if (global_prefs.dont_run_on_batteries && host_is_running_on_batteries()) {
|
||||
should_suspend = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
FILE_XFER_SET* file_xfers;
|
||||
ACTIVE_TASK_SET active_tasks;
|
||||
HOST_INFO host_info;
|
||||
PREFS prefs;
|
||||
GLOBAL_PREFS global_prefs;
|
||||
NET_STATS net_stats;
|
||||
|
||||
CLIENT_STATE();
|
||||
|
|
|
@ -64,6 +64,7 @@ int PROJECT::parse_account(FILE* in) {
|
|||
|
||||
strcpy(master_url, "");
|
||||
strcpy(authenticator, "");
|
||||
if (project_specific_prefs) free(project_specific_prefs);
|
||||
while (fgets(buf, 256, in)) {
|
||||
if (match_tag(buf, "<account>")) continue;
|
||||
if (match_tag(buf, "</account>")) return 0;
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
char master_url[256]; // url of site that contains scheduler tags
|
||||
// for this project
|
||||
char authenticator[256]; // user's authenticator on this project
|
||||
char* project_specific_prefs;
|
||||
char* project_specific_prefs; // without enclosing tags
|
||||
double resource_share; // project's resource share
|
||||
// relative to other projects. Arbitrary scale.
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ double CLIENT_STATE::current_water_days() {
|
|||
//
|
||||
double CLIENT_STATE::work_needed_secs() {
|
||||
double x = current_water_days();
|
||||
if (x > prefs.high_water_days) return 0;
|
||||
return (prefs.high_water_days - x)*86400;
|
||||
if (x > global_prefs.high_water_days) return 0;
|
||||
return (global_prefs.high_water_days - x)*86400;
|
||||
}
|
||||
|
||||
// update exponentially-averaged CPU times of all projects
|
||||
|
@ -185,10 +185,13 @@ int CLIENT_STATE::make_scheduler_request(PROJECT* p, double work_req) {
|
|||
fprintf(f, "<code_sign_key>\n%s</code_sign_key>\n", p->code_sign_key);
|
||||
}
|
||||
|
||||
FILE* fprefs = fopen(PREFS_FILE_NAME, "r");
|
||||
if (!fprefs) return ERR_FOPEN;
|
||||
copy_stream(fprefs, f);
|
||||
fclose(fprefs);
|
||||
// insert global preferences if present
|
||||
//
|
||||
FILE* fprefs = fopen(GLOBAL_PREFS_FILE_NAME, "r");
|
||||
if (fprefs) {
|
||||
copy_stream(fprefs, f);
|
||||
fclose(fprefs);
|
||||
}
|
||||
|
||||
time_stats.write(f, true);
|
||||
net_stats.write(f, true);
|
||||
|
@ -247,7 +250,7 @@ bool CLIENT_STATE::scheduler_rpc_poll() {
|
|||
|
||||
switch(scheduler_op->state) {
|
||||
case SCHEDULER_OP_STATE_IDLE:
|
||||
below_low_water = (current_water_days() <= prefs.low_water_days);
|
||||
below_low_water = (current_water_days() <= global_prefs.low_water_days);
|
||||
if (below_low_water && some_project_rpc_ok()) {
|
||||
compute_resource_debts();
|
||||
scheduler_op->init_get_work();
|
||||
|
@ -276,7 +279,7 @@ bool CLIENT_STATE::scheduler_rpc_poll() {
|
|||
return action;
|
||||
}
|
||||
|
||||
// Parse the reply from a scheduler
|
||||
// Handle the reply from a scheduler
|
||||
//
|
||||
void CLIENT_STATE::handle_scheduler_reply(
|
||||
PROJECT* project, char* scheduler_url
|
||||
|
@ -315,32 +318,52 @@ void CLIENT_STATE::handle_scheduler_reply(
|
|||
if (sr.request_delay) {
|
||||
project->min_rpc_time = time(0) + sr.request_delay;
|
||||
}
|
||||
|
||||
if (sr.hostid) {
|
||||
project->hostid = sr.hostid;
|
||||
project->rpc_seqno = 0;
|
||||
}
|
||||
|
||||
// if the scheduler reply includes preferences
|
||||
// that are newer than what we have on disk, write them to disk
|
||||
// if the scheduler reply includes global preferences,
|
||||
// insert extra elements, write to disk, and parse
|
||||
//
|
||||
|
||||
if (sr.prefs_mod_time > prefs.mod_time) {
|
||||
f = fopen(PREFS_FILE_NAME, "w");
|
||||
if (sr.global_prefs_xml) {
|
||||
f = fopen(GLOBAL_PREFS_FILE_NAME, "w");
|
||||
fprintf(f,
|
||||
"<preferences>\n"
|
||||
" <prefs_mod_time>%d</prefs_mod_time>\n"
|
||||
" <from_project>%s</from_project>\n"
|
||||
" <from_scheduler>%s</from_scheduler>\n",
|
||||
sr.prefs_mod_time,
|
||||
"<global_preferences>\n"
|
||||
" <source_project>%s</source_project>\n"
|
||||
" <source_scheduler>%s</source_scheduler>\n"
|
||||
"%s"
|
||||
"</global_preferences>\n",
|
||||
project->master_url,
|
||||
scheduler_url
|
||||
);
|
||||
fputs(sr.prefs_xml, f);
|
||||
fprintf(f,
|
||||
"</preferences>\n"
|
||||
scheduler_url,
|
||||
sr.global_prefs_xml
|
||||
);
|
||||
fclose(f);
|
||||
prefs.parse_file();
|
||||
global_prefs.parse_file();
|
||||
}
|
||||
|
||||
// deal with project preferences (should always be there)
|
||||
//
|
||||
if (sr.project_prefs_xml) {
|
||||
char path[256];
|
||||
f = fopen(TEMP_FILE_NAME, "w");
|
||||
fprintf(f,
|
||||
"<account>\n"
|
||||
" <master_url>%s</master_url>\n"
|
||||
" <authenticator>%s</authenticator>\n"
|
||||
"%s"
|
||||
"</account>\n",
|
||||
project->master_url,
|
||||
project->authenticator,
|
||||
sr.project_prefs_xml
|
||||
);
|
||||
fclose(f);
|
||||
get_account_filename(project->master_url, path);
|
||||
retval = boinc_rename(TEMP_FILE_NAME, path);
|
||||
f = fopen(path, "r");
|
||||
project->parse_account(f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
// if the scheduler reply includes a code-signing key,
|
||||
|
|
|
@ -189,13 +189,6 @@ int make_slot_dir(int slot) {
|
|||
|
||||
#endif
|
||||
|
||||
// Returns a filename used for prefs backup
|
||||
//
|
||||
int make_prefs_backup_name(PREFS& prefs, char* name) {
|
||||
sprintf(name, "prefs_backup_%d", prefs.mod_time);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_account_filename(char* master_url, char* path) {
|
||||
char buf[256];
|
||||
escape_project_url(master_url, buf);
|
||||
|
|
|
@ -31,7 +31,6 @@ extern void get_slot_dir(int slot, char* path);
|
|||
|
||||
extern int make_project_dir(PROJECT&);
|
||||
extern int make_slot_dir(int);
|
||||
extern int make_prefs_backup_name(PREFS&, char*);
|
||||
extern void get_account_filename(char* master_url, char* path);
|
||||
extern bool is_account_file(char*);
|
||||
|
||||
|
@ -39,9 +38,9 @@ extern bool is_account_file(char*);
|
|||
#define SLOTS_DIR "slots"
|
||||
#define STATE_FILE_TEMP "state_file_temp.xml"
|
||||
#define STATE_FILE_NAME "client_state.xml"
|
||||
#define PREFS_FILE_NAME "prefs.xml"
|
||||
#define GLOBAL_PREFS_FILE_NAME "global_prefs.xml"
|
||||
#define MASTER_FILE_NAME "master.html"
|
||||
#define PREFS_TEMP_FILE_NAME "prefs_temp.xml"
|
||||
#define SCHED_OP_REQUEST_FILE "sched_request.xml"
|
||||
#define SCHED_OP_RESULT_FILE "sched_reply.xml"
|
||||
#define LOG_FLAGS_FILE "log_flags.xml"
|
||||
#define TEMP_FILE_NAME "temp.xml"
|
||||
|
|
|
@ -31,10 +31,9 @@
|
|||
#include "prefs.h"
|
||||
|
||||
// the following values determine how the client behaves
|
||||
// if the user didn't set preferences via web
|
||||
// if there are no global prefs yet
|
||||
//
|
||||
PREFS::PREFS() {
|
||||
mod_time = 0;
|
||||
GLOBAL_PREFS::GLOBAL_PREFS() {
|
||||
dont_run_on_batteries = false;
|
||||
dont_run_if_user_active = false;
|
||||
confirm_before_connecting = false;
|
||||
|
@ -45,14 +44,13 @@ PREFS::PREFS() {
|
|||
disk_min_free_gb = 0.1;
|
||||
};
|
||||
|
||||
// Parse XML based prefs, usually from prefs.xml
|
||||
// Parse XML global prefs
|
||||
//
|
||||
int PREFS::parse(FILE* in) {
|
||||
int GLOBAL_PREFS::parse(FILE* in) {
|
||||
char buf[256];
|
||||
PROJECT* project;
|
||||
|
||||
while (fgets(buf, 256, in)) {
|
||||
if (match_tag(buf, "</preferences>")) {
|
||||
if (match_tag(buf, "</global_preferences>")) {
|
||||
return 0;
|
||||
} else if (match_tag(buf, "<dont_run_on_batteries/>")) {
|
||||
dont_run_on_batteries = true;
|
||||
|
@ -78,32 +76,15 @@ int PREFS::parse(FILE* in) {
|
|||
return ERR_XML_PARSE;
|
||||
}
|
||||
|
||||
// Parse prefs.xml for user preferences
|
||||
// Parse global prefs file
|
||||
//
|
||||
int PREFS::parse_file() {
|
||||
int GLOBAL_PREFS::parse_file() {
|
||||
FILE* f;
|
||||
int retval;
|
||||
|
||||
f = fopen(PREFS_FILE_NAME, "r");
|
||||
f = fopen(GLOBAL_PREFS_FILE_NAME, "r");
|
||||
if (!f) return ERR_FOPEN;
|
||||
retval = parse(f);
|
||||
fclose(f);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Write the default preferences
|
||||
// TODO: should mod_time really be 1?
|
||||
//
|
||||
int write_initial_prefs() {
|
||||
FILE* f = fopen(PREFS_FILE_NAME, "w");
|
||||
if (!f) return ERR_FOPEN;
|
||||
fprintf(f,
|
||||
"<preferences>\n"
|
||||
" <mod_time>1</mod_time>\n"
|
||||
" <high_water_days>2</high_water_days>\n"
|
||||
" <low_water_days>1</low_water_days>\n"
|
||||
"</preferences>\n"
|
||||
);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
|
||||
// The following structure is a parsed version of the prefs file
|
||||
//
|
||||
struct PREFS {
|
||||
int mod_time;
|
||||
struct GLOBAL_PREFS {
|
||||
bool dont_run_on_batteries;
|
||||
bool dont_run_if_user_active;
|
||||
bool confirm_before_connecting;
|
||||
|
@ -44,11 +43,9 @@ struct PREFS {
|
|||
double disk_max_used_pct;
|
||||
double disk_min_free_gb;
|
||||
|
||||
PREFS();
|
||||
GLOBAL_PREFS();
|
||||
int parse(FILE*);
|
||||
int parse_file();
|
||||
};
|
||||
|
||||
extern int write_initial_prefs();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -340,13 +340,15 @@ bool SCHEDULER_OP::poll() {
|
|||
}
|
||||
|
||||
SCHEDULER_REPLY::SCHEDULER_REPLY() {
|
||||
prefs_xml = 0;
|
||||
global_prefs_xml = 0;
|
||||
project_prefs_xml = 0;
|
||||
code_sign_key = 0;
|
||||
code_sign_key_signature = 0;
|
||||
}
|
||||
|
||||
SCHEDULER_REPLY::~SCHEDULER_REPLY() {
|
||||
if (prefs_xml) free(prefs_xml);
|
||||
if (global_prefs_xml) free(global_prefs_xml);
|
||||
if (project_prefs_xml) free(project_prefs_xml);
|
||||
if (code_sign_key) free(code_sign_key);
|
||||
if (code_sign_key_signature) free(code_sign_key_signature);
|
||||
}
|
||||
|
@ -359,8 +361,8 @@ int SCHEDULER_REPLY::parse(FILE* in) {
|
|||
strcpy(message_priority, "");
|
||||
request_delay = 0;
|
||||
hostid = 0;
|
||||
prefs_mod_time = 0;
|
||||
prefs_xml = 0;
|
||||
global_prefs_xml = 0;
|
||||
project_prefs_xml = 0;
|
||||
code_sign_key = 0;
|
||||
code_sign_key_signature = 0;
|
||||
|
||||
|
@ -388,10 +390,11 @@ int SCHEDULER_REPLY::parse(FILE* in) {
|
|||
continue;
|
||||
} else if (parse_int(buf, "<request_delay>", request_delay)) {
|
||||
continue;
|
||||
} else if (parse_int(buf, "<prefs_mod_time>", prefs_mod_time)) {
|
||||
continue;
|
||||
} else if (match_tag(buf, "<preferences>")) {
|
||||
retval = dup_element_contents(in, "</preferences>", &prefs_xml);
|
||||
} else if (match_tag(buf, "<global_preferences>")) {
|
||||
retval = dup_element_contents(in, "</global_preferences>", &global_prefs_xml);
|
||||
if (retval) return ERR_XML_PARSE;
|
||||
} else if (match_tag(buf, "<project_preferences>")) {
|
||||
retval = dup_element_contents(in, "</project_preferences>", &project_prefs_xml);
|
||||
if (retval) return ERR_XML_PARSE;
|
||||
} else if (match_tag(buf, "<code_sign_key>")) {
|
||||
retval = dup_element_contents(in, "</code_sign_key>", &code_sign_key);
|
||||
|
|
|
@ -76,8 +76,8 @@ struct SCHEDULER_REPLY {
|
|||
char message[1024];
|
||||
char message_priority[256];
|
||||
char project_name[256];
|
||||
int prefs_mod_time;
|
||||
char* prefs_xml;
|
||||
char* global_prefs_xml; // not including <global_preferences> tags
|
||||
char* project_prefs_xml; // not including <project_preferences> tags
|
||||
char user_name[256];
|
||||
double total_credit;
|
||||
double expavg_credit;
|
||||
|
|
6
db/db.h
6
db/db.h
|
@ -116,10 +116,10 @@ struct USER {
|
|||
double expavg_credit; // credit per second, recent average
|
||||
double expavg_time; // when the above was computed
|
||||
char global_prefs[MAX_BLOB_SIZE]; // global preferences
|
||||
unsigned int global_prefs_mod_time; // When global prefs were last updated
|
||||
// zero if they're not defined
|
||||
// within <global_preferences> tag
|
||||
char project_prefs[MAX_BLOB_SIZE];
|
||||
int teamid; // if the user is part of a team
|
||||
// within <project_preferences> tag
|
||||
int teamid; // if user is part of a team
|
||||
};
|
||||
|
||||
#define TEAM_TYPE_COMPANY_SMALL 1
|
||||
|
|
|
@ -120,7 +120,7 @@ void struct_to_str(void* vp, char* q, int type) {
|
|||
"web_password='%s', authenticator='%s', "
|
||||
"country='%s', postal_code='%s', "
|
||||
"total_credit=%f, expavg_credit=%f, expavg_time=%f, "
|
||||
"global_prefs='%s', global_prefs_mod_time=%d, project_prefs='%s', "
|
||||
"global_prefs='%s', project_prefs='%s', "
|
||||
"teamid=%d",
|
||||
up->id,
|
||||
up->create_time,
|
||||
|
@ -134,7 +134,6 @@ void struct_to_str(void* vp, char* q, int type) {
|
|||
up->expavg_credit,
|
||||
up->expavg_time,
|
||||
up->global_prefs,
|
||||
up->global_prefs_mod_time,
|
||||
up->project_prefs,
|
||||
up->teamid
|
||||
);
|
||||
|
@ -296,7 +295,6 @@ void row_to_struct(MYSQL_ROW& r, void* vp, int type) {
|
|||
up->expavg_credit = atof(r[i++]);
|
||||
up->expavg_time = atof(r[i++]);
|
||||
strcpy(up->global_prefs, r[i++]);
|
||||
up->global_prefs_mod_time = atoi(r[i++]);
|
||||
strcpy(up->project_prefs, r[i++]);
|
||||
up->teamid = atoi(r[i++]);
|
||||
break;
|
||||
|
|
|
@ -49,7 +49,6 @@ create table user (
|
|||
expavg_credit float not null,
|
||||
expavg_time float not null,
|
||||
global_prefs blob,
|
||||
global_prefs_mod_time integer not null,
|
||||
project_prefs blob,
|
||||
teamid integer not null,
|
||||
primary key (id)
|
||||
|
|
|
@ -37,8 +37,11 @@ before getting into the source code.
|
|||
<ul>
|
||||
<li> <a href=protocol.html>The scheduling server protocol</a>
|
||||
<li> <a href=rpc_policy.html>Scheduling server timing and retry policies</a>
|
||||
<li> <a href=prefs_propagate.html>Preferences propagation</a>
|
||||
<li> <a href=upload.html>Data server protocol</a>
|
||||
<li> <a href=pers_file_xfer.html>Persistent file transfers</a>
|
||||
</ul>
|
||||
<li> Miscellaneous
|
||||
<ul>
|
||||
<li> <a href=prefs_impl.html>Preferences</a>
|
||||
</ul>
|
||||
</ul>
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<pre>
|
||||
In database:
|
||||
user.global_prefs: XML, within <lt;global_preferences> tags
|
||||
may be empty; nonempty only if user has actually seen
|
||||
always includes <lt;mod_time> element
|
||||
includes <lt;source_project>, <lt;source_scheduler> elements if
|
||||
prefs came from another project
|
||||
user.project_prefs: XML, within <lt;project_preferences> tags
|
||||
always present.
|
||||
contains at least <lt;resource_share> element
|
||||
|
||||
In client:
|
||||
global_prefs.xml (present ONLY if have obtained from a server)
|
||||
same as user.global_prefs,
|
||||
but the following is inserted at start:
|
||||
<lt;source_project>
|
||||
<lt;source_scheduler>
|
||||
stored in memory:
|
||||
in parsed form (as struct)
|
||||
account_XXX.xml
|
||||
same as user.project_prefs, but with the following added:
|
||||
<lt;master_url>
|
||||
<lt;authenticator>
|
||||
stored in memory:
|
||||
in PROJECT struct
|
||||
master_url, authenticator, resource share parsed;
|
||||
project_specific_prefs raw XML (with enclosing tags)
|
||||
|
||||
|
||||
RPC request:
|
||||
includes global_prefs.xml if it's there
|
||||
|
||||
RPC handling and reply:
|
||||
always send project prefs
|
||||
if request message includes global prefs
|
||||
if missing in DB, or request copy is newer:
|
||||
install in DB
|
||||
else if DB copy is newer
|
||||
include DB copy in reply
|
||||
else
|
||||
if present in DB, include in reply
|
||||
|
||||
handling of RPC reply
|
||||
if includes global prefs
|
||||
insert <lt;source_project>, <lt;source_scheduler> elements if missing
|
||||
write to global_prefs.xml
|
||||
parse into memory
|
||||
project prefs
|
||||
insert <lt;master_url>, <lt;authenticator> elements,
|
||||
write to account_XXX.xml file
|
||||
parse; update resource share, project_specific_prefs in PROJECT struct
|
||||
</pre>
|
|
@ -1,4 +0,0 @@
|
|||
<title>Modifying Preferences</title>
|
||||
<body bgcolor=ffffff>
|
||||
<h2>Modifying Preferences</h2>
|
||||
<p>
|
|
@ -287,6 +287,8 @@ function prefs_project_parse_form(&$prefs) {
|
|||
//
|
||||
function global_prefs_make_xml($prefs) {
|
||||
$xml = "<global_preferences>\n";
|
||||
$now = time();
|
||||
$xml = $xml."<mod_time>$now</mod_time>\n";
|
||||
if ($prefs->dont_run_on_batteries) {
|
||||
$xml = $xml."<dont_run_on_batteries/>\n";
|
||||
}
|
||||
|
@ -322,14 +324,12 @@ function project_prefs_make_xml($prefs) {
|
|||
//
|
||||
function global_prefs_update($user, $prefs) {
|
||||
$prefs_xml = global_prefs_make_xml($prefs);
|
||||
$now = time();
|
||||
mysql_query("update user set global_prefs='$prefs_xml', global_prefs_mod_time=$now where id=$user->id");
|
||||
mysql_query("update user set global_prefs='$prefs_xml' where id=$user->id");
|
||||
$user->global_prefs = $prefs_xml;
|
||||
}
|
||||
|
||||
function project_prefs_update($user, $prefs) {
|
||||
$prefs_xml = project_prefs_make_xml($prefs);
|
||||
$now = time();
|
||||
mysql_query("update user set project_prefs='$prefs_xml' where id=$user->id");
|
||||
$user->project_prefs = $prefs_xml;
|
||||
}
|
||||
|
|
|
@ -224,23 +224,39 @@ int update_host_record(SCHEDULER_REQUEST& sreq, HOST& host) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Deal with global preferences.
|
||||
// If the client sent global prefs, and they're more recent than ours,
|
||||
// update user record in DB.
|
||||
// If we our DB has more recent global prefs than client's, send them.
|
||||
// If DB has more recent global prefs than client's, send them.
|
||||
//
|
||||
int handle_global_prefs(SCHEDULER_REQUEST& sreq, SCHEDULER_REPLY& reply) {
|
||||
if (sreq.global_prefs_mod_time > reply.user.global_prefs_mod_time
|
||||
&& strlen(sreq.global_prefs_xml)
|
||||
) {
|
||||
strncpy(reply.user.global_prefs, sreq.global_prefs_xml, sizeof(reply.user.global_prefs));
|
||||
reply.user.global_prefs_mod_time = sreq.global_prefs_mod_time;
|
||||
if (reply.user.global_prefs_mod_time > (unsigned)time(0)) {
|
||||
reply.user.global_prefs_mod_time = (unsigned)time(0);
|
||||
unsigned int req_mod_time, db_mod_time;
|
||||
bool need_update;
|
||||
reply.send_global_prefs = false;
|
||||
if (sreq.global_prefs_xml) {
|
||||
need_update = false;
|
||||
parse_int(sreq.global_prefs_xml, "<mod_time>", (int)req_mod_time);
|
||||
if (strlen(reply.user.global_prefs)) {
|
||||
parse_int(reply.user.global_prefs, "<mod_time>", (int)db_mod_time);
|
||||
if (req_mod_time > db_mod_time) {
|
||||
need_update = true;
|
||||
} else if (req_mod_time < db_mod_time) {
|
||||
reply.send_global_prefs = true;
|
||||
}
|
||||
} else {
|
||||
need_update = true;
|
||||
}
|
||||
if (need_update) {
|
||||
strncpy(
|
||||
reply.user.global_prefs, sreq.global_prefs_xml,
|
||||
sizeof(reply.user.global_prefs)
|
||||
);
|
||||
db_user_update(reply.user);
|
||||
}
|
||||
} else {
|
||||
if (strlen(reply.user.global_prefs)) {
|
||||
reply.send_global_prefs = true;
|
||||
}
|
||||
db_user_update(reply.user);
|
||||
}
|
||||
if (reply.user.global_prefs_mod_time > sreq.global_prefs_mod_time) {
|
||||
reply.send_global_prefs = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ int SCHEDULER_REQUEST::parse(FILE* fin) {
|
|||
strcpy(authenticator, "");
|
||||
hostid = 0;
|
||||
work_req_seconds = 0;
|
||||
global_prefs_mod_time = 0;
|
||||
global_prefs_xml = strdup("");
|
||||
|
||||
fgets(buf, 256, fin);
|
||||
|
@ -59,14 +58,13 @@ int SCHEDULER_REQUEST::parse(FILE* fin) {
|
|||
else if (parse_str(buf, "<platform_name>", platform_name, sizeof(platform_name))) continue;
|
||||
else if (parse_int(buf, "<core_client_version>", core_client_version)) continue;
|
||||
else if (parse_int(buf, "<work_req_seconds>", work_req_seconds)) continue;
|
||||
else if (parse_int(buf, "<global_prefs_mod_time>", (int)global_prefs_mod_time)) {
|
||||
continue;
|
||||
}
|
||||
else if (match_tag(buf, "<preferences>")) {
|
||||
else if (match_tag(buf, "<global_preferences>")) {
|
||||
global_prefs_xml = strdup("<global_preferences>\n");
|
||||
while (fgets(buf, 256, fin)) {
|
||||
if (strstr(buf, "</preferences>")) break;
|
||||
if (strstr(buf, "</global_preferences>")) break;
|
||||
strcatdup(global_prefs_xml, buf);
|
||||
}
|
||||
strcatdup(global_prefs_xml, "</global_preferences>\n");
|
||||
}
|
||||
else if (match_tag(buf, "<host_info>")) {
|
||||
host.parse(fin);
|
||||
|
@ -145,13 +143,13 @@ int SCHEDULER_REPLY::write(FILE* fout) {
|
|||
}
|
||||
|
||||
if (send_global_prefs) {
|
||||
fprintf(fout,
|
||||
"<global_prefs_mod_time>%d</global_prefs_mod_time>\n",
|
||||
user.global_prefs_mod_time
|
||||
);
|
||||
fputs(user.global_prefs, fout);
|
||||
}
|
||||
|
||||
// always send project prefs
|
||||
//
|
||||
fputs(user.project_prefs, fout);
|
||||
|
||||
// acknowledge results
|
||||
//
|
||||
for (i=0; i<result_acks.size(); i++) {
|
||||
|
|
|
@ -32,7 +32,6 @@ struct SCHEDULER_REQUEST {
|
|||
int core_client_version;
|
||||
int rpc_seqno;
|
||||
int work_req_seconds;
|
||||
unsigned int global_prefs_mod_time;
|
||||
char* global_prefs_xml;
|
||||
char* code_sign_key;
|
||||
|
||||
|
|
|
@ -237,7 +237,6 @@ void add_user() {
|
|||
printf("read_file: %s", global_prefs_file);
|
||||
return;
|
||||
}
|
||||
user.global_prefs_mod_time = time(0);
|
||||
}
|
||||
retval = db_user_new(user);
|
||||
if (retval) {
|
||||
|
|
Loading…
Reference in New Issue