boinc/client/cs_prefs.C

327 lines
9.2 KiB
C

// The contents of this file are subject to the BOINC Public License
// 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.
//
// 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.
//
// Contributor(s):
//
// Logic related to general (also known as global) preferences:
// when to compute, how much disk to use, etc.
//
#ifdef _WIN32
#include "boinc_win.h"
#endif
#ifndef _WIN32
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#endif
#include "util.h"
#include "filesys.h"
#include "parse.h"
#include "file_names.h"
#include "cpu_benchmark.h"
#include "client_msgs.h"
#include "client_state.h"
using std::min;
using std::string;
void CLIENT_STATE::install_global_prefs() {
net_xfers->max_bytes_sec_up = global_prefs.max_bytes_sec_up;
net_xfers->max_bytes_sec_down = global_prefs.max_bytes_sec_down;
net_xfers->bytes_left_up = global_prefs.max_bytes_sec_up;
net_xfers->bytes_left_down = global_prefs.max_bytes_sec_down;
// max_cpus may have changed, so update ncpus
//
set_ncpus();
}
// Return the maximum allowed disk usage as determined by user preferences.
// There are three different settings in the prefs;
// return the least of the three.
//
int CLIENT_STATE::allowed_disk_usage(double& size) {
double percent_space, min_val;
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*(1024.*1024.*1024.);
size = min(min(global_prefs.disk_max_used_gb*(1024.*1024.*1024.), percent_space), min_val);
if (size < 0) size = 0;
return 0;
}
int CLIENT_STATE::project_disk_usage(PROJECT* p, double& size) {
char buf[256];
unsigned int i;
double s;
get_project_dir(p, buf);
dir_size(buf, size);
for (i=0; i<active_tasks.active_tasks.size(); i++) {
ACTIVE_TASK* atp = active_tasks.active_tasks[i];
if (atp->wup->project != p) continue;
get_slot_dir(atp->slot, buf);
dir_size(buf, s);
size += s;
}
return 0;
}
int CLIENT_STATE::total_disk_usage(double& size) {
return dir_size(".", size);
}
int CLIENT_STATE::allowed_project_disk_usage(double& size) {
double other_disk_used;
double total_disk_available;
double project_disk_used;
total_disk_usage(other_disk_used);
allowed_disk_usage(total_disk_available);
for(unsigned int i=0; i<projects.size(); i++) {
project_disk_usage(projects[i], project_disk_used);
other_disk_used -= project_disk_used;
}
size = total_disk_available - other_disk_used;
return 0;
}
// returns true if start_hour == end_hour or start_hour <= now < end_hour
//
inline bool now_between_two_hours(int start_hour, int end_hour) {
if (start_hour == end_hour) {
return true;
}
time_t now = time(0);
struct tm *tmp = localtime(&now);
int hour = tmp->tm_hour;
if (start_hour < end_hour) {
return (hour >= start_hour && hour < end_hour);
} else {
return !(hour >= end_hour && hour < start_hour);
}
}
// See if (on the basis of user run request and prefs)
// we should suspend activities.
//
int CLIENT_STATE::check_suspend_activities(double now, int& reason) {
static double last_time = 0;
reason = 0;
// Don't work while we're running CPU benchmarks
//
if (are_cpu_benchmarks_running()) {
reason |= SUSPEND_REASON_BENCHMARKS;
}
if (user_run_request == USER_RUN_REQUEST_ALWAYS) return 0;
if (user_run_request == USER_RUN_REQUEST_NEVER) {
reason |= SUSPEND_REASON_USER_REQ;
return 0;
}
if (now - last_time < 5.0) return 1;
last_time = now;
if (!global_prefs.run_on_batteries
&& host_info.host_is_running_on_batteries()
) {
reason |= SUSPEND_REASON_BATTERIES;
}
if (!global_prefs.run_if_user_active
&& !host_info.users_idle(
check_all_logins, global_prefs.idle_time_to_run
)
) {
reason |= SUSPEND_REASON_USER_ACTIVE;
}
if (!now_between_two_hours(global_prefs.start_hour, global_prefs.end_hour)) {
reason |= SUSPEND_REASON_TIME_OF_DAY;
}
return 0;
}
int CLIENT_STATE::suspend_activities(int reason) {
string s_reason;
s_reason = "Suspending computation and network activity";
if (reason & SUSPEND_REASON_BATTERIES) {
s_reason += " - on batteries";
}
if (reason & SUSPEND_REASON_USER_ACTIVE) {
s_reason += " - user is active";
}
if (reason & SUSPEND_REASON_USER_REQ) {
s_reason += " - user request";
}
if (reason & SUSPEND_REASON_TIME_OF_DAY) {
s_reason += " - time of day";
}
if (reason & SUSPEND_REASON_BENCHMARKS) {
s_reason += " - running CPU benchmarks";
}
if (reason & SUSPEND_REASON_DISK_SIZE) {
s_reason += " - out of disk space - change global prefs";
}
msg_printf(NULL, MSG_INFO, const_cast<char*>(s_reason.c_str()));
active_tasks.suspend_all(global_prefs.leave_apps_in_memory);
pers_file_xfers->suspend();
return 0;
}
// persistent file xfers will resume of their own accord
// since activities_suspended is now true
//
int CLIENT_STATE::resume_activities() {
msg_printf(NULL, MSG_INFO, "Resuming computation and network activity");
active_tasks.unsuspend_all();
return 0;
}
void CLIENT_STATE::check_suspend_network(double now, int& reason) {
reason = 0;
if (user_network_request == USER_RUN_REQUEST_ALWAYS) return;
if (user_network_request == USER_RUN_REQUEST_NEVER) {
reason |= SUSPEND_REASON_USER_REQ;
return;
}
return;
}
int CLIENT_STATE::suspend_network(int reason) {
string s_reason;
s_reason = "Suspending network activity";
if (reason & SUSPEND_REASON_USER_REQ) {
s_reason += " - user request";
}
msg_printf(NULL, MSG_INFO, const_cast<char*>(s_reason.c_str()));
pers_file_xfers->suspend();
return 0;
}
int CLIENT_STATE::resume_network() {
msg_printf(NULL, MSG_INFO, "Resuming network activity");
return 0;
}
// call this only after parsing global prefs
//
PROJECT* CLIENT_STATE::global_prefs_source_project() {
return lookup_project(global_prefs.source_project);
}
void CLIENT_STATE::show_global_prefs_source(bool found_venue) {
PROJECT* pp = global_prefs_source_project();
if (pp) {
msg_printf(NULL, MSG_INFO,
"General prefs: from %s (last modified %s)\n",
pp->get_project_name(), time_to_string(global_prefs.mod_time)
);
} else {
msg_printf(NULL, MSG_INFO,
"General prefs: from unknown project %s (last modified %s)\n",
global_prefs.source_project,
time_to_string(global_prefs.mod_time)
);
}
if (strlen(main_host_venue)) {
if (found_venue) {
msg_printf(NULL, MSG_INFO,
"General prefs: using separate prefs for %s\n", main_host_venue
);
} else {
msg_printf(NULL, MSG_INFO,
"General prefs: no separate prefs for %s; using your defaults\n",
main_host_venue
);
}
} else {
msg_printf(NULL, MSG_INFO, "General prefs: using your defaults\n");
}
}
// parse user's project preferences,
// generating FILE_REF and FILE_INFO objects for each <app_file> element.
//
int PROJECT::parse_preferences_for_user_files() {
char* p, *q, *q2;
char buf[1024];
string timestamp, open_name, url, filename;
FILE_INFO* fip;
FILE_REF fr;
STRING256 url_str;
char prefs_buf[MAX_BLOB_LEN];
strcpy(prefs_buf, project_specific_prefs.c_str());
p = prefs_buf;
user_files.clear();
while (1) {
q = strstr(p, "<app_file>");
if (!q) break;
q2 = strstr(q, "</app_file>");
if (!q2) break;
*q2 = 0;
strcpy(buf, q);
if (!parse_str(buf, "<timestamp>", timestamp)) break;
if (!parse_str(buf, "<open_name>", open_name)) break;
if (!parse_str(buf, "<url>", url)) break;
strcpy(url_str.text, url.c_str());
filename = open_name + "_" + timestamp;
fip = gstate.lookup_file_info(this, filename.c_str());
if (!fip) {
fip = new FILE_INFO;
fip->project = this;
fip->urls.push_back(url_str);
strcpy(fip->name, filename.c_str());
fip->is_user_file = true;
gstate.file_infos.push_back(fip);
}
fr.file_info = fip;
strcpy(fr.open_name, open_name.c_str());
user_files.push_back(fr);
p = q2+strlen("</app_file>");
}
return 0;
}
#ifdef __GNUC__
static volatile const char __attribute__((unused)) *BOINCrcsid="$Id$";
#else
static volatile const char *BOINCrcsid="$Id$";
#endif