[boinc] 01/05: Imported Upstream version 7.4.27+dfsg
Gianfranco Costamagna
locutusofborg-guest at moszumanska.debian.org
Fri Nov 7 10:03:55 UTC 2014
This is an automated email from the git hooks/post-receive script.
locutusofborg-guest pushed a commit to branch experimental
in repository boinc.
commit d366bbc1bd1fc9de835a570a01485a096b6c84b6
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date: Fri Nov 7 10:59:26 2014 +0100
Imported Upstream version 7.4.27+dfsg
---
android/BOINC/AndroidManifest.xml | 4 +-
api/boinc_api.cpp | 16 +-
api/boinc_api.h | 3 +
client/acct_setup.cpp | 32 ++-
client/app_control.cpp | 30 ++-
client/boinc.xml | 2 +
client/client_state.cpp | 22 ++-
client/client_types.cpp | 30 +++
client/client_types.h | 6 +
client/coproc_sched.cpp | 111 +----------
client/cpu_sched.cpp | 27 +--
client/cs_notice.cpp | 40 +++-
client/cs_scheduler.cpp | 3 +
client/gpu_detect.cpp | 28 +++
client/gpu_nvidia.cpp | 15 +-
client/gpu_opencl.cpp | 25 ++-
client/hostinfo_unix.cpp | 4 +-
client/hostinfo_win.cpp | 13 +-
client/log_flags.cpp | 60 ++++--
client/log_flags.h | 4 +-
client/project.cpp | 1 -
client/project.h | 6 -
client/result.h | 2 +-
client/sandbox.cpp | 2 +-
client/scheduler_op.cpp | 4 +-
client/sim.cpp | 1 +
client/work_fetch.cpp | 402 ++++++++++++++------------------------
client/work_fetch.h | 29 +--
clientgui/AccountInfoPage.cpp | 20 +-
clientgui/AdvancedFrame.cpp | 32 ++-
clientgui/AdvancedFrame.h | 1 +
clientgui/CompletionPage.cpp | 2 +-
clientgui/Events.h | 1 +
clientgui/MainDocument.cpp | 13 +-
clientgui/Makefile.am | 1 +
clientgui/ProjectInfoPage.cpp | 71 ++-----
clientgui/ProjectWelcomePage.cpp | 291 +++++++++++++++++++++++++++
clientgui/ProjectWelcomePage.h | 95 +++++++++
clientgui/WizardAttach.cpp | 53 ++++-
clientgui/WizardAttach.h | 23 ++-
clientgui/browser.cpp | 100 ++++++++--
clientgui/browser.h | 29 ++-
configure.ac | 2 +-
html/user/get_project_config.php | 4 +
html/user/lookup_account.php | 80 +++++---
lib/app_ipc.cpp | 2 +-
lib/cc_config.cpp | 18 +-
lib/cc_config.h | 4 +-
lib/coproc.h | 36 +---
lib/error_numbers.h | 1 +
lib/gui_rpc_client.h | 4 +-
lib/gui_rpc_client_ops.cpp | 11 +-
lib/notice.cpp | 5 +-
lib/opencl_boinc.cpp | 13 +-
lib/opencl_boinc.h | 1 +
lib/procinfo_mac.cpp | 5 +
lib/str_util.cpp | 1 +
lib/url.cpp | 3 +
lib/url.h | 1 +
py/Boinc/boinc_db.py | 6 +
sched/script_validator.cpp | 128 ++++++++++++
version.log | 2 +-
62 files changed, 1321 insertions(+), 660 deletions(-)
diff --git a/android/BOINC/AndroidManifest.xml b/android/BOINC/AndroidManifest.xml
index 88ee33a..0c148ba 100644
--- a/android/BOINC/AndroidManifest.xml
+++ b/android/BOINC/AndroidManifest.xml
@@ -20,8 +20,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="edu.berkeley.boinc"
android:installLocation="internalOnly"
- android:versionCode="98"
- android:versionName="7.4.23" > <!-- installation on SD card would break boot receiver -->
+ android:versionCode="101"
+ android:versionName="7.4.27" > <!-- installation on SD card would break boot receiver -->
<!-- Add Google Play store metadata informing the store we can run on tablets and other large screen devices -->
diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp
index f24f8c2..dea49f9 100644
--- a/api/boinc_api.cpp
+++ b/api/boinc_api.cpp
@@ -682,7 +682,7 @@ static void send_trickle_up_msg() {
// an "unrecoverable error", which will be reported back to server.
// A zero exit-status tells the client we've successfully finished the result.
//
-int boinc_finish(int status) {
+int boinc_finish_message(int status, const char* msg, bool is_notice) {
char buf[256];
fraction_done = 1;
fprintf(stderr,
@@ -693,9 +693,15 @@ int boinc_finish(int status) {
boinc_sleep(2.0); // let the timer thread send final messages
boinc_disable_timer_thread = true; // then disable it
- if (options.main_program && status==0) {
+ if (options.main_program) {
FILE* f = fopen(BOINC_FINISH_CALLED_FILE, "w");
- if (f) fclose(f);
+ if (f) {
+ fprintf(f, "%d\n", status);
+ if (msg) {
+ fprintf(f, "%s\n%s\n", msg, is_notice?"notice":"");
+ }
+ fclose(f);
+ }
}
boinc_exit(status);
@@ -703,6 +709,10 @@ int boinc_finish(int status) {
return 0; // never reached
}
+int boinc_finish(int status) {
+ return boinc_finish_message(status, NULL, false);
+}
+
int boinc_temporary_exit(int delay, const char* reason, bool is_notice) {
FILE* f = fopen(TEMPORARY_EXIT_FILE, "w");
if (!f) {
diff --git a/api/boinc_api.h b/api/boinc_api.h
index 9c56df3..f34d8d1 100644
--- a/api/boinc_api.h
+++ b/api/boinc_api.h
@@ -145,6 +145,9 @@ extern int boinc_report_app_status_aux(
extern int boinc_temporary_exit(
int delay, const char* reason=NULL, bool is_notice=false
);
+extern int boinc_finish_message(
+ int status, const char* message, bool is_notice
+);
/////////// API ENDS HERE
diff --git a/client/acct_setup.cpp b/client/acct_setup.cpp
index 5faaff4..1161ca1 100644
--- a/client/acct_setup.cpp
+++ b/client/acct_setup.cpp
@@ -132,16 +132,32 @@ int LOOKUP_ACCOUNT_OP::do_rpc(ACCOUNT_IN& ai) {
url = ai.url;
canonicalize_master_url(url);
+ url += "lookup_account.php";
- url += "lookup_account.php?email_addr=";
- parameter = ai.email_addr;
- escape_url(parameter);
- url += parameter;
+ if (strchr(ai.email_addr.c_str(), '@')) {
+ url += "?email_addr=";
+ parameter = ai.email_addr;
+ escape_url(parameter);
+ url += parameter;
- url += "&passwd_hash=";
- parameter = ai.passwd_hash;
- escape_url(parameter);
- url += parameter;
+ url += "&passwd_hash=";
+ parameter = ai.passwd_hash;
+ escape_url(parameter);
+ url += parameter;
+ } else {
+ // LDAP case
+ //
+ if (!is_https(ai.url.c_str())) return ERR_NEED_HTTPS;
+ url += "?ldap_auth=1&ldap_uid=";
+ parameter = ai.email_addr;
+ escape_url(parameter);
+ url += parameter;
+
+ url += "&passwd=";
+ parameter = ai.passwd_hash;
+ escape_url(parameter);
+ url += parameter;
+ }
retval = gui_http->do_rpc(
this, url.c_str(), LOOKUP_ACCOUNT_FILENAME, false
diff --git a/client/app_control.cpp b/client/app_control.cpp
index 9b683ba..fb1df52 100644
--- a/client/app_control.cpp
+++ b/client/app_control.cpp
@@ -371,12 +371,12 @@ void ACTIVE_TASK::handle_temporary_exit(
} else {
if (is_notice) {
msg_printf(result->project, MSG_USER_ALERT,
- "Can't run task: %s", reason
+ "Task postponed: %s", reason
);
} else {
- if (log_flags.task_debug) {
+ if (log_flags.task) {
msg_printf(result->project, MSG_INFO,
- "[task] task called temporary_exit(%f, %s)", backoff, reason
+ "task postponed %f sec: %s", backoff, reason
);
}
}
@@ -587,10 +587,30 @@ void ACTIVE_TASK::handle_exited_app(int stat) {
gstate.request_work_fetch("application exited");
}
+// structure of a finish file (see boinc_api.cpp)):
+// exit status (int)
+// message
+// "notice" or blank line
+// ... or empty
+//
bool ACTIVE_TASK::finish_file_present() {
- char path[MAXPATHLEN];
+ char path[MAXPATHLEN], buf[1024], buf2[256];
+ strcpy(buf, "");
+ strcpy(buf2, "");
sprintf(path, "%s/%s", slot_dir, BOINC_FINISH_CALLED_FILE);
- return (boinc_file_exists(path) != 0);
+ FILE* f = fopen(path, "r");
+ if (!f) return false;
+ fgets(buf, sizeof(buf), f);
+ fgets(buf, sizeof(buf), f);
+ fgets(buf2, sizeof(buf2), f);
+ if (strlen(buf)) {
+ msg_printf(result->project,
+ strstr(buf2, "notice")?MSG_USER_ALERT:MSG_INFO,
+ "Message from task: %s", buf
+ );
+ }
+ fclose(f);
+ return true;
}
bool ACTIVE_TASK::temporary_exit_file_present(
diff --git a/client/boinc.xml b/client/boinc.xml
index 0e7903a..1612f66 100644
--- a/client/boinc.xml
+++ b/client/boinc.xml
@@ -11,6 +11,8 @@
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
</assembly>
diff --git a/client/client_state.cpp b/client/client_state.cpp
index 73be34d..af5d20d 100644
--- a/client/client_state.cpp
+++ b/client/client_state.cpp
@@ -246,11 +246,8 @@ void CLIENT_STATE::show_host_info() {
} else {
#if defined (_WIN32) && !defined(_WIN64)
if (!strcmp(get_primary_platform(), "windows_x86_64")) {
- msg_printf(NULL, MSG_INFO,
- "VirtualBox: can't detect because this is a 32-bit client"
- );
- msg_printf(NULL, MSG_INFO,
- " (to use VirtualBox, install a 64-bit BOINC client)."
+ msg_printf(NULL, MSG_USER_ALERT,
+ "Can't detect VirtualBox because this is a 32-bit version of BOINC; to fix, please install a 64-bit version."
);
}
#endif
@@ -876,7 +873,7 @@ bool CLIENT_STATE::poll_slow_events() {
#endif
if (user_active != old_user_active) {
- request_schedule_cpus("Idle state change");
+ request_schedule_cpus(user_active?"Not idle":"Idle");
}
#if 0
@@ -1602,6 +1599,10 @@ bool CLIENT_STATE::garbage_collect_always() {
for (fi_iter = file_infos.begin(); fi_iter!=file_infos.end(); fi_iter++) {
fip = *fi_iter;
+ if (fip->sticky_expire_time && now > fip->sticky_expire_time) {
+ fip->sticky = false;
+ fip->sticky_expire_time = 0;
+ }
if (!fip->sticky) continue;
if (fip->status < 0) continue;
fip->ref_cnt++;
@@ -1957,6 +1958,15 @@ int CLIENT_STATE::reset_project(PROJECT* project, bool detaching) {
}
garbage_collect_always();
}
+#ifdef ANDROID
+ // space is likely to be an issue on Android, so clean out project dir
+ // If we did this on other platforms we'd need to avoid deleting
+ // app_config.xml, but this isn't likely to exist on Android.
+ //
+ if (!project->anonymous_platform) {
+ client_clean_out_dir(project.project_dir(), "reset project");
+ }
+#endif
// force refresh of scheduler URLs
//
diff --git a/client/client_types.cpp b/client/client_types.cpp
index 28036ab..400d121 100644
--- a/client/client_types.cpp
+++ b/client/client_types.cpp
@@ -188,6 +188,8 @@ FILE_INFO::FILE_INFO() {
executable = false;
uploaded = false;
sticky = false;
+ sticky_lifetime = 0;
+ sticky_expire_time = 0;
gzip_when_done = false;
download_gzipped = false;
signature_required = false;
@@ -279,6 +281,8 @@ int FILE_INFO::set_permissions(const char* path) {
}
#endif
+// parse a <file_info>, from state file or scheduler RPC reply
+//
int FILE_INFO::parse(XML_PARSER& xp) {
char buf2[1024];
std::string url;
@@ -366,6 +370,10 @@ int FILE_INFO::parse(XML_PARSER& xp) {
if (xp.parse_bool("executable", executable)) continue;
if (xp.parse_bool("uploaded", uploaded)) continue;
if (xp.parse_bool("sticky", sticky)) continue;
+ if (xp.parse_double("sticky_expire_time", sticky_expire_time)) continue;
+ // state file has this
+ if (xp.parse_double("sticky_lifetime", sticky_lifetime)) continue;
+ // scheduler RPC reply has this
if (xp.parse_bool("gzip_when_done", gzip_when_done)) continue;
if (xp.parse_bool("download_gzipped", download_gzipped)) continue;
if (xp.parse_bool("signature_required", signature_required)) continue;
@@ -450,6 +458,11 @@ int FILE_INFO::write(MIOFILE& out, bool to_server) {
if (is_user_file) out.printf(" <is_user_file/>\n");
if (strlen(file_signature)) out.printf(" <file_signature>\n%s\n</file_signature>\n", file_signature);
}
+ if (sticky_expire_time) {
+ out.printf(" <sticky_expire_time>%f</sticky_expire_time>\n",
+ sticky_expire_time
+ );
+ }
for (i=0; i<download_urls.urls.size(); i++) {
xml_escape(download_urls.urls[i].c_str(), buf, sizeof(buf));
out.printf(" <download_url>%s</download_url>\n", buf);
@@ -618,6 +631,23 @@ int FILE_INFO::merge_info(FILE_INFO& new_info) {
return retval;
}
+ // sticky attributes
+ //
+ if (new_info.sticky) {
+ sticky = true;
+ if (new_info.sticky_lifetime) {
+ double x = gstate.now + new_info.sticky_lifetime;
+ if (x > sticky_expire_time) {
+ sticky_expire_time = x;
+ }
+ } else {
+ sticky_expire_time = 0;
+ }
+ } else {
+ sticky = false;
+ sticky_expire_time = 0;
+ }
+
return 0;
}
diff --git a/client/client_types.h b/client/client_types.h
index 908b21e..c8cd98f 100644
--- a/client/client_types.h
+++ b/client/client_types.h
@@ -105,6 +105,12 @@ struct FILE_INFO {
bool executable; // change file protections to make executable
bool uploaded; // file has been uploaded
bool sticky; // don't delete unless instructed to do so
+ double sticky_lifetime;
+ // how long file should stay sticky.
+ // passed from the server;
+ // used by client to calculate sticky_expire_time.
+ double sticky_expire_time;
+ // if nonzero, when sticky status expires
bool signature_required; // true iff associated with app version
bool is_user_file;
bool is_project_file;
diff --git a/client/coproc_sched.cpp b/client/coproc_sched.cpp
index 14babce..34d6956 100644
--- a/client/coproc_sched.cpp
+++ b/client/coproc_sched.cpp
@@ -120,9 +120,8 @@ static inline void increment_pending_usage(
// if the app is still running, it has enough RAM
//
static inline bool current_assignment_ok(
- RESULT* rp, double usage, COPROC* cp, bool& defer_sched
+ RESULT* rp, double usage, COPROC* cp
) {
- defer_sched = false;
double x = (usage<1)?usage:1;
for (int i=0; i<usage; i++) {
int j = rp->coproc_indices[i];
@@ -153,17 +152,11 @@ static inline void confirm_current_assignment(
cp->type, j, x, rp->name
);
}
-#if DEFER_ON_GPU_AVAIL_RAM
- cp->available_ram_temp[j] -= rp->avp->gpu_ram;
-#endif
}
}
-static inline bool get_fractional_assignment(
- RESULT* rp, double usage, COPROC* cp, bool& defer_sched
-) {
+static inline bool get_fractional_assignment(RESULT* rp, double usage, COPROC* cp) {
int i;
- defer_sched = false;
// try to assign an instance that's already fractionally assigned
//
@@ -174,13 +167,6 @@ static inline bool get_fractional_assignment(
if ((cp->usage[i] || cp->pending_usage[i])
&& (cp->usage[i] + cp->pending_usage[i] + usage <= 1)
) {
-#if DEFER_ON_GPU_AVAIL_RAM
- if (rp->avp->gpu_ram > cp->available_ram_temp[i]) {
- defer_sched = true;
- continue;
- }
- cp->available_ram_temp[i] -= rp->avp->gpu_ram;
-#endif
rp->coproc_indices[0] = i;
cp->usage[i] += usage;
if (log_flags.coproc_debug) {
@@ -200,13 +186,6 @@ static inline bool get_fractional_assignment(
continue;
}
if (!cp->usage[i]) {
-#if DEFER_ON_GPU_AVAIL_RAM
- if (rp->avp->gpu_ram > cp->available_ram_temp[i]) {
- defer_sched = true;
- continue;
- }
- cp->available_ram_temp[i] -= rp->avp->gpu_ram;
-#endif
rp->coproc_indices[0] = i;
cp->usage[i] += usage;
if (log_flags.coproc_debug) {
@@ -229,10 +208,9 @@ static inline bool get_fractional_assignment(
}
static inline bool get_integer_assignment(
- RESULT* rp, double usage, COPROC* cp, bool& defer_sched
+ RESULT* rp, double usage, COPROC* cp
) {
int i;
- defer_sched = false;
// make sure we have enough free instances
//
@@ -242,18 +220,6 @@ static inline bool get_integer_assignment(
continue;
}
if (!cp->usage[i]) {
-#if DEFER_ON_GPU_AVAIL_RAM
- if (rp->avp->gpu_ram > cp->available_ram_temp[i]) {
- defer_sched = true;
- if (log_flags.coproc_debug) {
- msg_printf(rp->project, MSG_INFO,
- "[coproc] task %s needs %.0fMB RAM, %s GPU %d has %.0fMB available",
- rp->name, rp->avp->gpu_ram/MEGA, cp->type, i, cp->available_ram_temp[i]/MEGA
- );
- }
- continue;
- };
-#endif
nfree++;
}
}
@@ -263,11 +229,6 @@ static inline bool get_integer_assignment(
"[coproc] Insufficient %s for %s; need %d, available %d",
cp->type, rp->name, (int)usage, nfree
);
- if (defer_sched) {
- msg_printf(rp->project, MSG_INFO,
- "[coproc] some instances lack available memory"
- );
- }
}
return false;
}
@@ -280,16 +241,8 @@ static inline bool get_integer_assignment(
if (!can_use_gpu(rp, cp, i)) {
continue;
}
- if (!cp->usage[i]
- && !cp->pending_usage[i]
-#if DEFER_ON_GPU_AVAIL_RAM
- && (rp->avp->gpu_ram <= cp->available_ram_temp[i])
-#endif
- ) {
+ if (!cp->usage[i] && !cp->pending_usage[i]) {
cp->usage[i] = 1;
-#if DEFER_ON_GPU_AVAIL_RAM
- cp->available_ram_temp[i] -= rp->avp->gpu_ram;
-#endif
rp->coproc_indices[n++] = i;
if (log_flags.coproc_debug) {
msg_printf(rp->project, MSG_INFO,
@@ -307,15 +260,8 @@ static inline bool get_integer_assignment(
if (!can_use_gpu(rp, cp, i)) {
continue;
}
- if (!cp->usage[i]
-#if DEFER_ON_GPU_AVAIL_RAM
- && (rp->avp->gpu_ram <= cp->available_ram_temp[i])
-#endif
- ) {
+ if (!cp->usage[i]) {
cp->usage[i] = 1;
-#if DEFER_ON_GPU_AVAIL_RAM
- cp->available_ram_temp[i] -= rp->avp->gpu_ram;
-#endif
rp->coproc_indices[n++] = i;
if (log_flags.coproc_debug) {
msg_printf(rp->project, MSG_INFO,
@@ -335,43 +281,12 @@ static inline bool get_integer_assignment(
return false;
}
-static inline void mark_as_defer_sched(RESULT* rp) {
- int i = rp->avp->gpu_usage.rsc_type;
- if (i) {
- rp->project->rsc_defer_sched[i] = true;
- }
- rp->schedule_backoff = gstate.now + 300; // try again in 5 minutes
- gstate.request_schedule_cpus("insufficient GPU RAM");
-}
-
-#if DEFER_ON_GPU_AVAIL_RAM
-static void copy_available_ram(COPROC& cp, const char* name) {
- int rt = rsc_index(name);
- if (rt > 0) {
- for (int i=0; i<MAX_COPROC_INSTANCES; i++) {
- coprocs.coprocs[rt].available_ram_temp[i] = cp.available_ram;
- }
- }
-}
-#endif
-
void assign_coprocs(vector<RESULT*>& jobs) {
unsigned int i;
COPROC* cp;
double usage;
coprocs.clear_usage();
-#if DEFER_ON_GPU_AVAIL_RAM
- if (coprocs.have_nvidia()) {
- copy_available_ram(coprocs.nvidia, GPU_TYPE_NVIDIA);
- }
- if (coprocs.have_ati()) {
- copy_available_ram(coprocs.ati, GPU_TYPE_ATI);
- }
- if (coprocs.have_intel()) {
- copy_available_ram(coprocs.intel_gpu, GPU_TYPE_INTEL);
- }
-#endif
// fill in pending usage
//
@@ -407,34 +322,24 @@ void assign_coprocs(vector<RESULT*>& jobs) {
}
ACTIVE_TASK* atp = gstate.lookup_active_task_by_result(rp);
- bool defer_sched;
if (atp && atp->is_gpu_task_running()) {
- if (current_assignment_ok(rp, usage, cp, defer_sched)) {
+ if (current_assignment_ok(rp, usage, cp)) {
confirm_current_assignment(rp, usage, cp);
job_iter++;
} else {
- if (defer_sched) {
- mark_as_defer_sched(rp);
- }
job_iter = jobs.erase(job_iter);
}
} else {
if (usage < 1) {
- if (get_fractional_assignment(rp, usage, cp, defer_sched)) {
+ if (get_fractional_assignment(rp, usage, cp)) {
job_iter++;
} else {
- if (defer_sched) {
- mark_as_defer_sched(rp);
- }
job_iter = jobs.erase(job_iter);
}
} else {
- if (get_integer_assignment(rp, usage, cp, defer_sched)) {
+ if (get_integer_assignment(rp, usage, cp)) {
job_iter++;
} else {
- if (defer_sched) {
- mark_as_defer_sched(rp);
- }
job_iter = jobs.erase(job_iter);
}
}
diff --git a/client/cpu_sched.cpp b/client/cpu_sched.cpp
index b54a515..d4b6ef7 100644
--- a/client/cpu_sched.cpp
+++ b/client/cpu_sched.cpp
@@ -159,6 +159,7 @@ struct PROC_RESOURCES {
return false;
}
} else if (rp->avp->avg_ncpus > 1) {
+ if (ncpus_used_mt == 0) return true;
return (ncpus_used_mt + rp->avp->avg_ncpus <= ncpus);
} else {
return (ncpus_used_st < ncpus);
@@ -525,13 +526,6 @@ static RESULT* earliest_deadline_result(int rsc_type) {
}
if (!best_result) return NULL;
- if (log_flags.cpu_sched_debug) {
- msg_printf(best_result->project, MSG_INFO,
- "[cpu_sched_debug] earliest deadline: %.0f %s",
- best_result->report_deadline, best_result->name
- );
- }
-
return best_result;
}
@@ -1147,12 +1141,6 @@ bool CLIENT_STATE::enforce_run_list(vector<RESULT*>& run_list) {
);
}
- for (i=0; i<projects.size(); i++) {
- for (int j=1; j<coprocs.n_rsc; j++) {
- projects[i]->rsc_defer_sched[j] = false;
- }
- }
-
// schedule non-CPU-intensive tasks,
// and look for backed-off GPU jobs
//
@@ -1174,17 +1162,6 @@ bool CLIENT_STATE::enforce_run_list(vector<RESULT*>& run_list) {
//ram_left -= atp->procinfo.working_set_size_smoothed;
swap_left -= atp->procinfo.swap_size;
}
- if (rp->schedule_backoff) {
- if (rp->schedule_backoff > gstate.now) {
- int r = rp->avp->gpu_usage.rsc_type;
- if (r) {
- rp->project->rsc_defer_sched[r] = true;
- }
- } else {
- rp->schedule_backoff = 0;
- request_schedule_cpus("schedule backoff finished");
- }
- }
}
// assign coprocessors to coproc jobs,
@@ -1323,6 +1300,7 @@ bool CLIENT_STATE::enforce_run_list(vector<RESULT*>& run_list) {
bool coproc_quit_pending = false;
for (i=0; i<active_tasks.active_tasks.size(); i++) {
atp = active_tasks.active_tasks[i];
+#if 0
if (log_flags.cpu_sched_debug) {
msg_printf(atp->result->project, MSG_INFO,
"[cpu_sched_debug] %s sched state %d next %d task state %d",
@@ -1330,6 +1308,7 @@ bool CLIENT_STATE::enforce_run_list(vector<RESULT*>& run_list) {
atp->next_scheduler_state, atp->task_state()
);
}
+#endif
int preempt_type = REMOVE_MAYBE_SCHED;
switch (atp->next_scheduler_state) {
case CPU_SCHED_PREEMPTED:
diff --git a/client/cs_notice.cpp b/client/cs_notice.cpp
index a1a8121..f24f44f 100644
--- a/client/cs_notice.cpp
+++ b/client/cs_notice.cpp
@@ -286,8 +286,12 @@ static inline bool string_equal_nodigits(string& s1, string& s2) {
}
static inline bool same_text(NOTICE& n1, NOTICE& n2) {
- if (strcmp(n1.title, n2.title)) return false;
- if (!string_equal_nodigits(n1.description, n2.description)) return false;
+ if (strcmp(n1.title, n2.title)) {
+ return false;
+ }
+ if (!string_equal_nodigits(n1.description, n2.description)) {
+ return false;
+ }
return true;
}
@@ -340,11 +344,24 @@ bool NOTICES::remove_dups(NOTICE& n) {
double min_time = gstate.now - 30*86400;
while (i != notices.end()) {
NOTICE& n2 = *i;
+
+ if (log_flags.notice_debug) {
+ msg_printf(0, MSG_INFO,
+ "[notice] scanning old notice %d: %s",
+ n2.seqno, strlen(n2.title)?n2.title:n2.description.c_str()
+ );
+ }
if (n2.arrival_time < min_time
|| (n2.create_time && n2.create_time < min_time)
) {
i = notices.erase(i);
removed_something = true;
+ if (log_flags.notice_debug) {
+ msg_printf(0, MSG_INFO,
+ "[notice] removing old notice %d: %s",
+ n2.seqno, strlen(n2.title)?n2.title:n2.description.c_str()
+ );
+ }
#if 0
// this check prevents news item edits from showing; skip it
} else if (same_guid(n, n2)) {
@@ -363,10 +380,20 @@ bool NOTICES::remove_dups(NOTICE& n) {
if (n.create_time > n2.create_time + min_diff) {
i = notices.erase(i);
removed_something = true;
+ if (log_flags.notice_debug) {
+ msg_printf(0, MSG_INFO,
+ "[notice] replacing identical older notice %d", n2.seqno
+ );
+ }
} else {
n2.keep = true;
retval = false;
++i;
+ if (log_flags.notice_debug) {
+ msg_printf(0, MSG_INFO,
+ "[notice] keeping identical older notice %d", n2.seqno
+ );
+ }
}
} else {
++i;
@@ -383,6 +410,12 @@ bool NOTICES::remove_dups(NOTICE& n) {
// add a notice.
//
bool NOTICES::append(NOTICE& n) {
+ if (log_flags.notice_debug) {
+ msg_printf(0, MSG_INFO,
+ "[notice] processing notice: %s",
+ strlen(n.title)?n.title:n.description.c_str()
+ );
+ }
if (!remove_dups(n)) {
return false;
}
@@ -393,8 +426,7 @@ bool NOTICES::append(NOTICE& n) {
}
if (log_flags.notice_debug) {
msg_printf(0, MSG_INFO,
- "[notice] appending notice %d: %s",
- n.seqno, strlen(n.title)?n.title:n.description.c_str()
+ "[notice] adding notice %d", n.seqno
);
}
notices.push_front(n);
diff --git a/client/cs_scheduler.cpp b/client/cs_scheduler.cpp
index 9a27525..2dbceac 100644
--- a/client/cs_scheduler.cpp
+++ b/client/cs_scheduler.cpp
@@ -811,6 +811,9 @@ int CLIENT_STATE::handle_scheduler_reply(
} else {
fip = new FILE_INFO;
*fip = sr.file_infos[i];
+ if (fip->sticky_lifetime) {
+ fip->sticky_expire_time = now + fip->sticky_lifetime;
+ }
retval = link_file_info(project, fip);
if (retval) {
msg_printf(project, MSG_INTERNAL_ERROR,
diff --git a/client/gpu_detect.cpp b/client/gpu_detect.cpp
index f17380f..2d73b9c 100644
--- a/client/gpu_detect.cpp
+++ b/client/gpu_detect.cpp
@@ -200,6 +200,17 @@ void COPROCS::correlate_gpus(
"CUDA: NVIDIA GPU %d (not used): %s",
nvidia_gpus[i].device_num, buf
);
+
+#ifdef __APPLE__
+ if ((nvidia_gpus[i].cuda_version >= 6050) &&
+ nvidia_gpus[i].prop.major < 2) {
+ // This will be called only if CUDA recognized and reported the GPU
+ msg_printf(NULL, MSG_USER_ALERT, "NVIDIA GPU %d: %s %s",
+ nvidia_gpus[i].device_num, nvidia_gpus[i].prop.name,
+ _("cannot be used for CUDA or OpenCL computation with CUDA driver 6.5 or later")
+ );
+ }
+#endif
break;
}
descs.push_back(string(buf2));
@@ -235,6 +246,13 @@ void COPROCS::correlate_gpus(
// Create descriptions for OpenCL NVIDIA GPUs
//
for (i=0; i<nvidia_opencls.size(); i++) {
+ if (nvidia_opencls[i].warn_bad_cuda) {
+ // This will be called only if CUDA did _not_ recognize and report the GPU
+ msg_printf(NULL, MSG_USER_ALERT, "NVIDIA GPU %d: %s %s",
+ nvidia_opencls[i].device_num, nvidia_opencls[i].name,
+ _("cannot be used for CUDA or OpenCL computation with CUDA driver 6.5 or later")
+ );
+ }
nvidia_opencls[i].description(buf, sizeof(buf), proc_type_name(PROC_TYPE_NVIDIA_GPU));
descs.push_back(string(buf));
}
@@ -349,6 +367,11 @@ int COPROCS::write_coproc_info_file(vector<string> &warnings) {
mf.printf(" <coprocs>\n");
+ if (nvidia.have_cuda) {
+ mf.printf(" <have_cuda>1</have_cuda>\n");
+ mf.printf(" <cuda_version>%d</cuda_version>\n", nvidia.cuda_version);
+ }
+
for (i=0; i<ati_gpus.size(); ++i) {
ati_gpus[i].write_xml(mf, false);
}
@@ -425,6 +448,11 @@ int COPROCS::read_coproc_info_file(vector<string> &warnings) {
return 0;
}
+ if (xp.parse_bool("have_cuda", nvidia.have_cuda)) continue;
+ if (xp.parse_int("cuda_version", nvidia.cuda_version)) {
+ continue;
+ }
+
if (xp.match_tag("coproc_ati")) {
retval = my_ati_gpu.parse(xp);
if (retval) {
diff --git a/client/gpu_nvidia.cpp b/client/gpu_nvidia.cpp
index 9f20296..cff103b 100644
--- a/client/gpu_nvidia.cpp
+++ b/client/gpu_nvidia.cpp
@@ -351,6 +351,8 @@ void COPROC_NVIDIA::get(
return;
}
+ have_cuda = true;
+
retval = (*__cuDeviceGetCount)(&cuda_ndevs);
if (retval) {
sprintf(buf, "cuDeviceGetCount() returned %d", retval);
@@ -414,7 +416,6 @@ void COPROC_NVIDIA::get(
#else
cc.display_driver_version = nvidia_driver_version();
#endif
- have_cuda = true;
cc.have_cuda = true;
cc.cuda_version = cuda_version;
cc.device_num = j;
@@ -441,6 +442,13 @@ void COPROC_NVIDIA::correlate(
bool first = true;
for (i=0; i<nvidia_gpus.size(); i++) {
if (in_vector(nvidia_gpus[i].device_num, ignore_devs)) continue;
+#ifdef __APPLE__
+ if ((nvidia_gpus[i].cuda_version >= 6050) && nvidia_gpus[i].prop.major < 2) {
+ // Can't use GPUs with compute capability < 2 with CUDA drivers >= 6.5.x
+ nvidia_gpus[i].is_used = COPROC_UNUSED;
+ continue;
+ }
+#endif
if (first) {
*this = nvidia_gpus[i];
first = false;
@@ -460,6 +468,11 @@ void COPROC_NVIDIA::correlate(
nvidia_gpus[i].is_used = COPROC_UNUSED;
} else if (this->have_cuda && !nvidia_gpus[i].have_cuda) {
nvidia_gpus[i].is_used = COPROC_UNUSED;
+#ifdef __APPLE__
+ } else if (nvidia_gpus[i].is_used == COPROC_UNUSED) {
+ // Can't use GPUs with compute capability < 2 with CUDA drivers >= 6.5.x
+ continue;
+#endif
} else if (use_all || !nvidia_compare(nvidia_gpus[i], *this, true)) {
device_nums[count] = nvidia_gpus[i].device_num;
pci_infos[count] = nvidia_gpus[i].pci_info;
diff --git a/client/gpu_opencl.cpp b/client/gpu_opencl.cpp
index 2ba3a14..9eddf7b 100644
--- a/client/gpu_opencl.cpp
+++ b/client/gpu_opencl.cpp
@@ -385,6 +385,7 @@ void COPROCS::get_opencl(
//////////// NVIDIA //////////////
if (is_NVIDIA(prop.vendor)) {
+ bool cuda_match_found = false;
if (nvidia.have_cuda) {
// Mac OpenCL does not recognize all NVIDIA GPUs returned by
// CUDA but we assume that OpenCL and CUDA return devices
@@ -394,6 +395,8 @@ void COPROCS::get_opencl(
// On other systems, assume OpenCL and CUDA return devices
// in the same order.
//
+ int saved_CUDA_index = current_CUDA_index;
+
while (1) {
if (current_CUDA_index >= (int)(nvidia_gpus.size())) {
snprintf(buf, sizeof(buf),
@@ -401,11 +404,22 @@ void COPROCS::get_opencl(
device_index
);
warnings.push_back(buf);
- return; // Should never happen
+ // Newer versions of CUDA driver don't support older NVIDIA GPUs
+ if (nvidia.cuda_version >= 6050) {
+ prop.device_num = (int)(nvidia_opencls.size());
+ current_CUDA_index = saved_CUDA_index;
+ prop.warn_bad_cuda = true;
+ break;
+ } else {
+ // Older CUDA drivers should report all NVIDIA GPUs reported by OpenCL
+ return; // Should never happen
+ }
}
if (!strcmp(prop.name,
nvidia_gpus[devnums_pci_slot_sort[current_CUDA_index]].prop.name)
) {
+ cuda_match_found = true;
+ prop.device_num = devnums_pci_slot_sort[current_CUDA_index];
break; // We have a match
}
// This CUDA GPU is not recognized by OpenCL,
@@ -413,13 +427,12 @@ void COPROCS::get_opencl(
//
++current_CUDA_index;
}
- prop.device_num = devnums_pci_slot_sort[current_CUDA_index];
} else {
prop.device_num = (int)(nvidia_opencls.size());
}
prop.opencl_device_index = device_index;
- if (nvidia.have_cuda) {
+ if (cuda_match_found) {
prop.peak_flops = nvidia_gpus[prop.device_num].peak_flops;
} else {
COPROC_NVIDIA c;
@@ -427,7 +440,7 @@ void COPROCS::get_opencl(
c.set_peak_flops();
prop.peak_flops = c.peak_flops;
}
- if (nvidia_gpus.size()) {
+ if (cuda_match_found) {
// Assumes OpenCL device_num and CUDA device_num now match
//
prop.opencl_available_ram = nvidia_gpus[prop.device_num].available_ram;
@@ -441,7 +454,7 @@ void COPROCS::get_opencl(
}
nvidia_opencls.insert(it, prop);
- ++current_CUDA_index;
+ if (cuda_match_found) ++current_CUDA_index;
}
//////////// AMD / ATI //////////////
@@ -853,6 +866,8 @@ void COPROC::merge_opencl(
unsigned int i, j;
for (i=0; i<opencls.size(); i++) {
+ opencls[i].is_used = COPROC_UNUSED;
+
if (in_vector(opencls[i].device_num, ignore_dev)) {
opencls[i].is_used = COPROC_IGNORED;
continue;
diff --git a/client/hostinfo_unix.cpp b/client/hostinfo_unix.cpp
index c25a63c..8df69b6 100644
--- a/client/hostinfo_unix.cpp
+++ b/client/hostinfo_unix.cpp
@@ -1266,7 +1266,9 @@ int HOST_INFO::get_host_info() {
"get_filesystem_info() failed: %s", boincerror(retval)
);
}
- get_virtualbox_version();
+ if (!cc_config.dont_use_vbox) {
+ get_virtualbox_version();
+ }
///////////// p_vendor, p_model, p_features /////////////////
#if LINUX_LIKE_SYSTEM
diff --git a/client/hostinfo_win.cpp b/client/hostinfo_win.cpp
index 195e963..b5cb29d 100644
--- a/client/hostinfo_win.cpp
+++ b/client/hostinfo_win.cpp
@@ -219,6 +219,15 @@ int get_os_information(
switch (osvi.dwPlatformId) {
case VER_PLATFORM_WIN32_NT:
+ if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 4 ) {
+ if( osvi.wProductType == VER_NT_WORKSTATION ) {
+ strcat(os_name, "Windows 10");
+ } else {
+ strcat(os_name, "Windows Server 2015");
+ }
+ pGPI( 6, 4, 0, 0, &dwType);
+ }
+
if ( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3 ) {
if( osvi.wProductType == VER_NT_WORKSTATION ) {
strcat(os_name, "Windows 8.1");
@@ -1135,7 +1144,9 @@ int HOST_INFO::get_host_info() {
get_os_information(
os_name, sizeof(os_name), os_version, sizeof(os_version)
);
- get_virtualbox_version();
+ if (!cc_config.dont_use_vbox) {
+ get_virtualbox_version();
+ }
get_processor_info(
p_vendor, sizeof(p_vendor),
p_model, sizeof(p_model),
diff --git a/client/log_flags.cpp b/client/log_flags.cpp
index 433c07d..223176e 100644
--- a/client/log_flags.cpp
+++ b/client/log_flags.cpp
@@ -159,6 +159,9 @@ void CC_CONFIG::show() {
if (no_gpus) {
msg_printf(NULL, MSG_INFO, "Config: don't use coprocessors");
}
+ if (dont_use_vbox) {
+ msg_printf(NULL, MSG_INFO, "Config: don't use VirtualBox");
+ }
if (no_info_fetch) {
msg_printf(NULL, MSG_INFO, "Config: don't fetch project list or client version info");
}
@@ -245,7 +248,6 @@ void CC_CONFIG::show() {
// (It's separate so that we can write messages in it)
int CC_CONFIG::parse_options_client(XML_PARSER& xp) {
- char path[MAXPATHLEN];
string s;
int n, retval;
@@ -308,16 +310,10 @@ int CC_CONFIG::parse_options_client(XML_PARSER& xp) {
}
continue;
}
- if (xp.parse_str("data_dir", path, sizeof(path))) {
- if (chdir(path)) {
- perror("chdir");
- exit(1);
- }
- continue;
- }
if (xp.parse_bool("disallow_attach", disallow_attach)) continue;
if (xp.parse_bool("dont_check_file_sizes", dont_check_file_sizes)) continue;
if (xp.parse_bool("dont_contact_ref_site", dont_contact_ref_site)) continue;
+ if (xp.parse_bool("dont_use_vbox", dont_use_vbox)) continue;
if (xp.match_tag("exclude_gpu")) {
EXCLUDE_GPU eg;
retval = eg.parse(xp);
@@ -521,19 +517,6 @@ int read_config_file(bool init, const char* fname) {
if (init) {
coprocs = cc_config.config_coprocs;
- if (strlen(cc_config.data_dir)) {
-#ifdef _WIN32
- _chdir(cc_config.data_dir);
-#else
- if (chdir(cc_config.data_dir)) {
- msg_printf(NULL, MSG_INFO,
- "Couldn't change to directory specified in cc_config.xml: %s",
- cc_config.data_dir
- );
- return ERR_OPENDIR;
- }
-#endif
- }
} else {
select_proxy_info(); // in case added or removed proxy info
}
@@ -723,3 +706,38 @@ bool gpu_excluded(APP* app, COPROC& cp, int ind) {
}
return false;
}
+
+// if the configuration file disallows the use of a GPU type
+// for a project, set a flag to that effect
+//
+void set_no_rsc_config() {
+ for (unsigned int i=0; i<gstate.projects.size(); i++) {
+ PROJECT& p = *gstate.projects[i];
+ for (int j=1; j<coprocs.n_rsc; j++) {
+ bool allowed[MAX_COPROC_INSTANCES];
+ memset(allowed, 0, sizeof(allowed));
+ COPROC& c = coprocs.coprocs[j];
+ for (int k=0; k<c.count; k++) {
+ allowed[c.device_nums[k]] = true;
+ }
+ for (unsigned int k=0; k<cc_config.exclude_gpus.size(); k++) {
+ EXCLUDE_GPU& e = cc_config.exclude_gpus[k];
+ if (strcmp(e.url.c_str(), p.master_url)) continue;
+ if (!e.type.empty() && strcmp(e.type.c_str(), c.type)) continue;
+ if (!e.appname.empty()) continue;
+ if (e.device_num < 0) {
+ memset(allowed, 0, sizeof(allowed));
+ break;
+ }
+ allowed[e.device_num] = false;
+ }
+ p.no_rsc_config[j] = true;
+ for (int k=0; k<c.count; k++) {
+ if (allowed[c.device_nums[k]]) {
+ p.no_rsc_config[j] = false;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/client/log_flags.h b/client/log_flags.h
index 9eeb47a..8b001a0 100644
--- a/client/log_flags.h
+++ b/client/log_flags.h
@@ -1,6 +1,6 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
-// Copyright (C) 2008 University of California
+// Copyright (C) 2014 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
@@ -39,6 +39,6 @@ extern CC_CONFIG cc_config;
extern int read_config_file(bool init, const char* fname=CONFIG_FILE);
extern void process_gpu_exclusions();
extern bool gpu_excluded(APP* app, COPROC& cp, int ind);
-
+extern void set_no_rsc_config();
#endif
diff --git a/client/project.cpp b/client/project.cpp
index a5d9b79..2710146 100644
--- a/client/project.cpp
+++ b/client/project.cpp
@@ -49,7 +49,6 @@ void PROJECT::init() {
no_rsc_config[i] = false;
no_rsc_apps[i] = false;
no_rsc_ams[i] = false;
- rsc_defer_sched[i] = false;
}
strcpy(host_venue, "");
using_venue_specific_prefs = false;
diff --git a/client/project.h b/client/project.h
index b8d1d93..16de165 100644
--- a/client/project.h
+++ b/client/project.h
@@ -71,12 +71,6 @@ struct PROJECT : PROJ_AM {
//
bool no_rsc_ams[MAX_RSC];
- // the following set dynamically
- //
- bool rsc_defer_sched[MAX_RSC];
- // This project has a GPU job for which there's insuff. video RAM.
- // Don't fetch more jobs of this type; they might have same problem
-
char host_venue[256];
// logically, this belongs in the client state file
// rather than the account file.
diff --git a/client/result.h b/client/result.h
index aa39d88..685a36c 100644
--- a/client/result.h
+++ b/client/result.h
@@ -185,7 +185,7 @@ struct RESULT {
// textual description of resources used
double schedule_backoff;
// don't try to schedule until this time
- // (wait for free GPU RAM)
+ // (because the app called boinc_temporary_exit())
char schedule_backoff_reason[256];
};
diff --git a/client/sandbox.cpp b/client/sandbox.cpp
index df215e8..5a31917 100644
--- a/client/sandbox.cpp
+++ b/client/sandbox.cpp
@@ -226,7 +226,7 @@ int set_to_project_group(const char* path) {
int get_project_gid() {
return 0;
}
-int set_to_project_group(const char* path) {
+int set_to_project_group(const char*) {
return 0;
}
#endif // ! _WIN32
diff --git a/client/scheduler_op.cpp b/client/scheduler_op.cpp
index edc39fc..5ad82ec 100644
--- a/client/scheduler_op.cpp
+++ b/client/scheduler_op.cpp
@@ -247,9 +247,9 @@ int SCHEDULER_OP::start_rpc(PROJECT* p) {
if (strlen(buf)) {
msg_printf(p, MSG_INFO, "Requesting new tasks for %s", buf);
} else {
- if (p->pwf.cant_fetch_work_reason) {
+ if (p->pwf.project_reason) {
msg_printf(p, MSG_INFO,
- "Not requesting tasks: %s", cant_fetch_work_string(p, buf)
+ "Not requesting tasks: %s", project_reason_string(p, buf)
);
} else {
msg_printf(p, MSG_INFO, "Not requesting tasks");
diff --git a/client/sim.cpp b/client/sim.cpp
index 1056a64..aad116a 100644
--- a/client/sim.cpp
+++ b/client/sim.cpp
@@ -1454,6 +1454,7 @@ void do_client_simulation() {
}
}
}
+ set_no_rsc_config();
process_gpu_exclusions();
get_app_params();
diff --git a/client/work_fetch.cpp b/client/work_fetch.cpp
index 1fc6078..5d7c33b 100644
--- a/client/work_fetch.cpp
+++ b/client/work_fetch.cpp
@@ -1,6 +1,6 @@
// This file is part of BOINC.
// http://boinc.berkeley.edu
-// Copyright (C) 2008 University of California
+// Copyright (C) 2014 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
@@ -46,49 +46,6 @@ using std::vector;
RSC_WORK_FETCH rsc_work_fetch[MAX_RSC];
WORK_FETCH work_fetch;
-static inline int dont_fetch(PROJECT* p, int rsc_type) {
- if (p->no_rsc_pref[rsc_type]) return DONT_FETCH_PREFS;
- if (p->no_rsc_config[rsc_type]) return DONT_FETCH_CONFIG;
- if (p->no_rsc_apps[rsc_type]) return DONT_FETCH_NO_APPS;
- if (p->no_rsc_ams[rsc_type]) return DONT_FETCH_AMS;
- return 0;
-}
-
-// if the configuration file disallows the use of a GPU type
-// for a project, set a flag to that effect
-//
-void set_no_rsc_config() {
- for (unsigned int i=0; i<gstate.projects.size(); i++) {
- PROJECT& p = *gstate.projects[i];
- for (int j=1; j<coprocs.n_rsc; j++) {
- bool allowed[MAX_COPROC_INSTANCES];
- memset(allowed, 0, sizeof(allowed));
- COPROC& c = coprocs.coprocs[j];
- for (int k=0; k<c.count; k++) {
- allowed[c.device_nums[k]] = true;
- }
- for (unsigned int k=0; k<cc_config.exclude_gpus.size(); k++) {
- EXCLUDE_GPU& e = cc_config.exclude_gpus[k];
- if (strcmp(e.url.c_str(), p.master_url)) continue;
- if (!e.type.empty() && strcmp(e.type.c_str(), c.type)) continue;
- if (!e.appname.empty()) continue;
- if (e.device_num < 0) {
- memset(allowed, 0, sizeof(allowed));
- break;
- }
- allowed[e.device_num] = false;
- }
- p.no_rsc_config[j] = true;
- for (int k=0; k<c.count; k++) {
- if (allowed[c.device_nums[k]]) {
- p.no_rsc_config[j] = false;
- break;
- }
- }
- }
- }
-}
-
// does the (NCI) project have a job that's running or uploading?
// (don't request another job from NCI project if so)
//
@@ -115,14 +72,8 @@ inline bool has_coproc_app(PROJECT* p, int rsc_type) {
/////////////// RSC_PROJECT_WORK_FETCH ///////////////
-bool RSC_PROJECT_WORK_FETCH::compute_may_have_work(PROJECT* p, int rsc_type) {
- if (dont_fetch(p, rsc_type)) return false;
- if (p->rsc_defer_sched[rsc_type]) return false;
- return (backoff_time < gstate.now);
-}
-
void RSC_PROJECT_WORK_FETCH::rr_init(PROJECT* p, int rsc_type) {
- may_have_work = compute_may_have_work(p, rsc_type);
+ rsc_project_reason = compute_rsc_project_reason(p, rsc_type);
fetchable_share = 0;
n_runnable_jobs = 0;
sim_nused = 0;
@@ -146,6 +97,66 @@ void RSC_PROJECT_WORK_FETCH::resource_backoff(PROJECT* p, const char* name) {
}
}
+// checks for whether we should ask this project for work of this type.
+// check for backoff must go last, so that if that's the reason
+// we know that there are no other reasons (for piggyback)
+//
+int RSC_PROJECT_WORK_FETCH::compute_rsc_project_reason(
+ PROJECT *p, int rsc_type
+) {
+ RSC_WORK_FETCH& rwf = rsc_work_fetch[rsc_type];
+ // see whether work fetch for this resource is banned
+ // by prefs, config, project, or acct mgr
+ //
+ if (p->no_rsc_pref[rsc_type]) return DONT_FETCH_PREFS;
+ if (p->no_rsc_config[rsc_type]) return DONT_FETCH_CONFIG;
+ if (p->no_rsc_apps[rsc_type]) return DONT_FETCH_NO_APPS;
+ if (p->no_rsc_ams[rsc_type]) return DONT_FETCH_AMS;
+ if (p->rsc_pwf[rsc_type].has_deferred_job) return DONT_FETCH_DEFER_SCHED;
+
+ // if project has zero resource share,
+ // only fetch work if a device is idle
+ //
+ if (p->resource_share == 0 && rwf.nidle_now == 0 && rwf.sim_excluded_instances==0) {
+ return DONT_FETCH_ZERO_SHARE;
+ }
+
+ // if project has excluded GPUs of this type,
+ // we need to avoid fetching work just because there's an idle instance
+ // or a shortfall;
+ // fetching work might not alleviate either of these,
+ // and we'd end up fetching unbounded work.
+ // At the same time, we want to respect work buf params if possible.
+ //
+ // Current policy:
+ // don't fetch work if remaining time of this project's jobs
+ // exceeds work_buf_min * (#usable instances / #instances)
+ //
+ // TODO: THIS IS FAIRLY CRUDE. Making it smarter would require
+ // computing shortfall etc. on a per-project basis
+ //
+ int nexcl = ncoprocs_excluded;
+ if (rsc_type && nexcl) {
+ int n_not_excluded = rwf.ninstances - nexcl;
+ if (n_runnable_jobs >= n_not_excluded
+ && queue_est > (gstate.work_buf_min() * n_not_excluded)/rwf.ninstances
+ ) {
+ return DONT_FETCH_BUFFER_FULL;
+ }
+ }
+
+ if (anonymous_platform_no_apps) {
+ return DONT_FETCH_NO_APPS;
+ }
+
+ // this must go last
+ //
+ if (backoff_time > gstate.now) {
+ return DONT_FETCH_BACKED_OFF;
+ }
+ return 0;
+}
+
/////////////// RSC_WORK_FETCH ///////////////
void RSC_WORK_FETCH::copy_request(COPROC& c) {
@@ -278,34 +289,27 @@ void RSC_WORK_FETCH::print_state(const char* name) {
shortfall, nidle_now, saturated_time,
busy_time_estimator.get_busy_time()
);
- msg_printf(0, MSG_INFO, "[work_fetch] sim used inst %d sim excl inst %d",
- sim_used_instances, sim_excluded_instances
- );
+// msg_printf(0, MSG_INFO, "[work_fetch] sim used inst %d sim excl inst %d",
+// sim_used_instances, sim_excluded_instances
+// );
for (unsigned int i=0; i<gstate.projects.size(); i++) {
char buf[256];
PROJECT* p = gstate.projects[i];
if (p->non_cpu_intensive) continue;
- RSC_PROJECT_WORK_FETCH& pwf = project_state(p);
- bool no_rsc_pref = p->no_rsc_pref[rsc_type];
- bool no_rsc_config = p->no_rsc_config[rsc_type];
- bool no_rsc_apps = p->no_rsc_apps[rsc_type];
- bool no_rsc_ams = p->no_rsc_ams[rsc_type];
- double bt = pwf.backoff_time>gstate.now?pwf.backoff_time-gstate.now:0;
+ RSC_PROJECT_WORK_FETCH& rpwf = project_state(p);
+ double bt = rpwf.backoff_time>gstate.now?rpwf.backoff_time-gstate.now:0;
if (bt) {
sprintf(buf, " (resource backoff: %.2f, inc %.2f)",
- bt, pwf.backoff_interval
+ bt, rpwf.backoff_interval
);
} else {
strcpy(buf, "");
}
msg_printf(p, MSG_INFO,
- "[work_fetch] fetch share %.3f%s%s%s%s%s",
- pwf.fetchable_share,
- buf,
- no_rsc_pref?" (blocked by prefs)":"",
- no_rsc_apps?" (no apps)":"",
- no_rsc_ams?" (blocked by account manager)":"",
- no_rsc_config?" (blocked by configuration file)":""
+ "[work_fetch] share %.3f %s %s",
+ rpwf.fetchable_share,
+ rsc_project_reason_string(rpwf.rsc_project_reason),
+ buf
);
}
}
@@ -317,7 +321,7 @@ void RSC_WORK_FETCH::clear_request() {
/////////////// PROJECT_WORK_FETCH ///////////////
-int PROJECT_WORK_FETCH::compute_cant_fetch_work_reason(PROJECT* p) {
+int PROJECT_WORK_FETCH::compute_project_reason(PROJECT* p) {
if (p->non_cpu_intensive) return CANT_FETCH_WORK_NON_CPU_INTENSIVE;
if (p->suspended_via_gui) return CANT_FETCH_WORK_SUSPENDED_VIA_GUI;
if (p->master_url_fetch_pending) return CANT_FETCH_WORK_MASTER_URL_FETCH_PENDING;
@@ -326,7 +330,8 @@ int PROJECT_WORK_FETCH::compute_cant_fetch_work_reason(PROJECT* p) {
if (p->some_result_suspended()) return CANT_FETCH_WORK_RESULT_SUSPENDED;
if (p->too_many_uploading_results) return CANT_FETCH_WORK_TOO_MANY_UPLOADS;
- // this goes last
+ // this goes last, so that if this is the reason we know
+ // that there are no other reasons
//
if (p->min_rpc_time > gstate.now) return CANT_FETCH_WORK_MIN_RPC_TIME;
return 0;
@@ -338,97 +343,64 @@ void PROJECT_WORK_FETCH::reset(PROJECT* p) {
}
}
-/////////////// WORK_FETCH ///////////////
+void PROJECT_WORK_FETCH::rr_init(PROJECT* p) {
+ project_reason = compute_project_reason(p);
+ n_runnable_jobs = 0;
+}
-// mark the projects from which we can fetch work
-//
-void WORK_FETCH::compute_cant_fetch_work_reason() {
- for (unsigned int i=0; i<gstate.projects.size(); i++) {
- PROJECT* p = gstate.projects[i];
- p->pwf.cant_fetch_work_reason = p->pwf.compute_cant_fetch_work_reason(p);
+void PROJECT_WORK_FETCH::print_state(PROJECT* p) {
+ char buf[1024], buf2[1024];
+ if (project_reason) {
+ sprintf(buf, "can't request work: %s", project_reason_string(p, buf2));
+ } else {
+ strcpy(buf, "can request work");
}
+ if (p->min_rpc_time > gstate.now) {
+ sprintf(buf2, " (%.2f sec)", p->min_rpc_time - gstate.now);
+ strcat(buf, buf2);
+ }
+ msg_printf(p, MSG_INFO, "[work_fetch] REC %.3f prio %.3f %s",
+ rec,
+ p->sched_priority,
+ buf
+ );
}
+/////////////// WORK_FETCH ///////////////
+
void WORK_FETCH::rr_init() {
- for (int i=0; i<coprocs.n_rsc; i++) {
- rsc_work_fetch[i].rr_init();
- }
- compute_cant_fetch_work_reason();
+ // compute PROJECT::RSC_PROJECT_WORK_FETCH::has_deferred_job
+ //
for (unsigned int i=0; i<gstate.projects.size(); i++) {
PROJECT* p = gstate.projects[i];
- p->pwf.n_runnable_jobs = 0;
for (int j=0; j<coprocs.n_rsc; j++) {
- p->rsc_pwf[j].rr_init(p, j);
+ p->rsc_pwf[j].has_deferred_job = false;
}
}
-}
-
-#if 0
-// if the given project is highest-priority among the projects
-// eligible for the resource, set request fields
-//
-void RSC_WORK_FETCH::supplement(PROJECT* pp) {
- double x = pp->sched_priority;
- for (unsigned i=0; i<gstate.projects.size(); i++) {
- PROJECT* p = gstate.projects[i];
- if (p == pp) continue;
- if (p->pwf.cant_fetch_work_reason) continue;
- if (!project_state(p).may_have_work) continue;
- RSC_PROJECT_WORK_FETCH& rpwf = project_state(p);
- if (rpwf.anon_skip) continue;
- if (p->sched_priority > x) {
- if (log_flags.work_fetch_debug) {
- msg_printf(pp, MSG_INFO,
- "[work_fetch]: not requesting work for %s: %s has higher priority",
- rsc_name_long(rsc_type), p->get_project_name()
- );
+ for (unsigned int i=0; i<gstate.results.size(); i++) {
+ RESULT* rp = gstate.results[i];
+ if (rp->schedule_backoff) {
+ if (rp->schedule_backoff > gstate.now) {
+ int rt = rp->avp->gpu_usage.rsc_type;
+ rp->project->rsc_pwf[rt].has_deferred_job = true;
+ } else {
+ rp->schedule_backoff = 0;
+ gstate.request_schedule_cpus("schedule backoff finished");
}
- return;
}
}
- // didn't find a better project; ask for work
- //
- set_request(pp);
-}
-// we're going to ask the given project for work of the given type.
-// (or -1 if none)
-// Set requests for this type and perhaps other types
-//
-void WORK_FETCH::set_all_requests_hyst(PROJECT* p, int rsc_type) {
for (int i=0; i<coprocs.n_rsc; i++) {
- if (i == rsc_type) {
- rsc_work_fetch[i].set_request(p);
- } else {
- // don't fetch work for a resource if the buffer is above max
- //
- if (rsc_work_fetch[i].saturated_time > gstate.work_buf_total()) {
- continue;
- }
-
- // don't fetch work if backup project and no idle instances
- //
- if (p->resource_share==0 && rsc_work_fetch[i].nidle_now==0) {
- continue;
- }
-
- if (i>0 && !gpus_usable) {
- continue;
- }
- rsc_work_fetch[i].supplement(p);
- }
+ rsc_work_fetch[i].rr_init();
}
-}
-
-void WORK_FETCH::set_all_requests(PROJECT* p) {
- for (int i=0; i<coprocs.n_rsc; i++) {
- if (i==0 || gpus_usable) {
- rsc_work_fetch[i].set_request(p);
+ for (unsigned int i=0; i<gstate.projects.size(); i++) {
+ PROJECT* p = gstate.projects[i];
+ p->pwf.rr_init(p);
+ for (int j=0; j<coprocs.n_rsc; j++) {
+ p->rsc_pwf[j].rr_init(p, j);
}
}
}
-#endif
-
// copy request fields from RSC_WORK_FETCH to COPROCS
//
void WORK_FETCH::copy_requests() {
@@ -458,21 +430,7 @@ void WORK_FETCH::print_state() {
msg_printf(0, MSG_INFO, "[work_fetch] --- project states ---");
for (unsigned int i=0; i<gstate.projects.size(); i++) {
PROJECT* p = gstate.projects[i];
- char buf[1024], buf2[1024];
- if (p->pwf.cant_fetch_work_reason) {
- sprintf(buf, "can't req work: %s", cant_fetch_work_string(p, buf2));
- } else {
- strcpy(buf, "can req work");
- }
- if (p->min_rpc_time > gstate.now) {
- sprintf(buf2, " (backoff: %.2f sec)", p->min_rpc_time - gstate.now);
- strcat(buf, buf2);
- }
- msg_printf(p, MSG_INFO, "[work_fetch] REC %.3f prio %.6f %s",
- p->pwf.rec,
- p->sched_priority,
- buf
- );
+ p->pwf.print_state(p);
}
for (int i=0; i<coprocs.n_rsc; i++) {
rsc_work_fetch[i].print_state(rsc_name_long(i));
@@ -510,7 +468,7 @@ void WORK_FETCH::piggyback_work_request(PROJECT* p) {
setup();
- switch (p->pwf.cant_fetch_work_reason) {
+ switch (p->pwf.project_reason) {
case 0:
case CANT_FETCH_WORK_MIN_RPC_TIME:
break;
@@ -539,8 +497,12 @@ void WORK_FETCH::piggyback_work_request(PROJECT* p) {
rwf.dont_fetch_reason = DONT_FETCH_GPUS_NOT_USABLE;
continue;
}
- rwf.dont_fetch_reason = rwf.cant_fetch(p);
- if (rwf.dont_fetch_reason) {
+ RSC_PROJECT_WORK_FETCH& rpwf = rwf.project_state(p);
+ switch (rpwf.rsc_project_reason) {
+ case 0:
+ case DONT_FETCH_BACKED_OFF:
+ break;
+ default:
WF_DEBUG(msg_printf(p, MSG_INFO, "piggyback: can't fetch %s", rsc_name_long(i));)
continue;
}
@@ -559,12 +521,13 @@ void WORK_FETCH::piggyback_work_request(PROJECT* p) {
for (unsigned int j=0; j<gstate.projects.size(); j++) {
p2 = gstate.projects[j];
if (p2 == p) break;
- if (p2->sched_priority == p->sched_priority) continue;
- if (p2->pwf.cant_fetch_work_reason) {
+ if (p2->sched_priority == p->sched_priority) continue;
+ if (p2->pwf.project_reason) {
WF_DEBUG(msg_printf(p, MSG_INFO, "piggyback: %s can't fetch work", p2->project_name);)
continue;
}
- if (!rwf.cant_fetch(p2) && !rwf.backed_off(p2)) {
+ RSC_PROJECT_WORK_FETCH& rpwf2 = rwf.project_state(p2);
+ if (!rpwf2.rsc_project_reason) {
WF_DEBUG(msg_printf(p, MSG_INFO, "piggyback: better proj %s", p2->project_name);)
break;
}
@@ -582,7 +545,7 @@ void WORK_FETCH::piggyback_work_request(PROJECT* p) {
}
}
if (!requested_work()) {
- p->pwf.cant_fetch_work_reason = CANT_FETCH_WORK_DONT_NEED;
+ p->pwf.project_reason = CANT_FETCH_WORK_DONT_NEED;
}
}
@@ -606,71 +569,6 @@ static bool higher_priority(PROJECT *p1, PROJECT *p2) {
return (p1->sched_priority > p2->sched_priority);
}
-// check resource-level backoff
-//
-bool RSC_WORK_FETCH::backed_off(PROJECT* p) {
- if (project_state(p).backoff_time > gstate.now) {
- WF_DEBUG(msg_printf(p, MSG_INFO, "skip: backoff");)
- return true;
- }
- return false;
-}
-
-// a variety of checks for whether we should ask this project
-// for work of this type
-//
-int RSC_WORK_FETCH::cant_fetch(PROJECT *p) {
- // see whether work fetch for this resource is banned
- // by prefs, config, project, or acct mgr
- //
- int reason = dont_fetch(p, rsc_type);
- if (reason) {
- WF_DEBUG(msg_printf(p, MSG_INFO, "skip: dont_fetch");)
- return reason;
- }
-
- RSC_PROJECT_WORK_FETCH& rpwf = project_state(p);
-
- // if project has zero resource share,
- // only fetch work if a device is idle
- //
- if (p->resource_share == 0 && nidle_now == 0 && sim_excluded_instances==0) {
- WF_DEBUG(msg_printf(p, MSG_INFO, "skip: zero share");)
- return DONT_FETCH_ZERO_SHARE;
- }
-
- // if project has excluded GPUs of this type,
- // we need to avoid fetching work just because there's an idle instance
- // or a shortfall;
- // fetching work might not alleviate either of these,
- // and we'd end up fetching unbounded work.
- // At the same time, we want to respect work buf params if possible.
- //
- // Current policy:
- // don't fetch work if remaining time of this project's jobs
- // exceeds work_buf_min * (#usable instances / #instances)
- //
- // TODO: THIS IS FAIRLY CRUDE. Making it smarter would require
- // computing shortfall etc. on a per-project basis
- //
- int nexcl = rpwf.ncoprocs_excluded;
- if (rsc_type && nexcl) {
- int n_not_excluded = ninstances - nexcl;
- if (rpwf.n_runnable_jobs >= n_not_excluded
- && rpwf.queue_est > (gstate.work_buf_min() * n_not_excluded)/ninstances
- ) {
- WF_DEBUG(msg_printf(p, MSG_INFO, "skip: too much work");)
- return DONT_FETCH_BUFFER_FULL;
- }
- }
-
- if (rpwf.anon_skip) {
- WF_DEBUG(msg_printf(p, MSG_INFO, "skip: anon");)
- return DONT_FETCH_NO_APPS;
- }
- return 0;
-}
-
// return true if there is exclusion starvation
// and this project can use the starved instances
//
@@ -712,8 +610,8 @@ void WORK_FETCH::setup() {
int job_limit = 1000;
for (unsigned int i=0; i<gstate.projects.size(); i++) {
PROJECT* p = gstate.projects[i];
- if (p->pwf.n_runnable_jobs > job_limit && !p->pwf.cant_fetch_work_reason) {
- p->pwf.cant_fetch_work_reason = CANT_FETCH_WORK_TOO_MANY_RUNNABLE;
+ if (p->pwf.n_runnable_jobs > job_limit && !p->pwf.project_reason) {
+ p->pwf.project_reason = CANT_FETCH_WORK_TOO_MANY_RUNNABLE;
}
}
@@ -735,10 +633,6 @@ void WORK_FETCH::setup() {
PROJECT* WORK_FETCH::choose_project() {
PROJECT* p;
- if (log_flags.work_fetch_debug) {
- msg_printf(0, MSG_INFO, "[work_fetch] entering choose_project()");
- }
-
p = non_cpu_intensive_project_needing_work();
if (p) return p;
@@ -754,7 +648,7 @@ PROJECT* WORK_FETCH::choose_project() {
for (unsigned int j=0; j<gstate.projects.size(); j++) {
p = gstate.projects[j];
WF_DEBUG(msg_printf(p, MSG_INFO, "scanning");)
- if (p->pwf.cant_fetch_work_reason) {
+ if (p->pwf.project_reason) {
WF_DEBUG(msg_printf(p, MSG_INFO, "skip: cfwr %d", p->pwf.cant_fetch_work_reason);)
continue;
}
@@ -770,7 +664,8 @@ PROJECT* WORK_FETCH::choose_project() {
for (int i=0; i<coprocs.n_rsc; i++) {
if (i && !gpus_usable) continue;
RSC_WORK_FETCH& rwf = rsc_work_fetch[i];
- if (!rwf.cant_fetch(p) && !rwf.backed_off(p)) {
+ RSC_PROJECT_WORK_FETCH& rpwf = rwf.project_state(p);
+ if (!rpwf.rsc_project_reason) {
if (!rwf.found_project) {
rwf.found_project = p;
}
@@ -821,7 +716,8 @@ PROJECT* WORK_FETCH::choose_project() {
WF_DEBUG(msg_printf(p, MSG_INFO, "%s don't need", rsc_name_long(i));)
continue;
}
- int reason = rwf.cant_fetch(p);
+ RSC_PROJECT_WORK_FETCH& rpwf = rwf.project_state(p);
+ int reason = rpwf.rsc_project_reason;
if (reason) {
WF_DEBUG(msg_printf(p, MSG_INFO, "%s can't fetch", rsc_name_long(i));)
continue;
@@ -879,9 +775,9 @@ void WORK_FETCH::compute_shares() {
for (i=0; i<gstate.projects.size(); i++) {
p = gstate.projects[i];
if (p->non_cpu_intensive) continue;
- if (p->pwf.cant_fetch_work_reason) continue;
+ if (p->pwf.project_reason) continue;
for (int j=0; j<coprocs.n_rsc; j++) {
- if (p->rsc_pwf[j].may_have_work) {
+ if (!p->rsc_pwf[j].rsc_project_reason) {
rsc_work_fetch[j].total_fetchable_share += p->resource_share;
}
}
@@ -889,9 +785,9 @@ void WORK_FETCH::compute_shares() {
for (i=0; i<gstate.projects.size(); i++) {
p = gstate.projects[i];
if (p->non_cpu_intensive) continue;
- if (p->pwf.cant_fetch_work_reason) continue;
+ if (p->pwf.project_reason) continue;
for (int j=0; j<coprocs.n_rsc; j++) {
- if (p->rsc_pwf[j].may_have_work) {
+ if (!p->rsc_pwf[j].rsc_project_reason) {
p->rsc_pwf[j].fetchable_share = rsc_work_fetch[j].total_fetchable_share?p->resource_share/rsc_work_fetch[j].total_fetchable_share:1;
}
}
@@ -1030,12 +926,12 @@ void WORK_FETCH::init() {
PROJECT* p = gstate.projects[i];
if (!p->anonymous_platform) continue;
for (int k=0; k<coprocs.n_rsc; k++) {
- p->rsc_pwf[k].anon_skip = true;
+ p->rsc_pwf[k].anonymous_platform_no_apps = true;
}
for (j=0; j<gstate.app_versions.size(); j++) {
APP_VERSION* avp = gstate.app_versions[j];
if (avp->project != p) continue;
- p->rsc_pwf[avp->gpu_usage.rsc_type].anon_skip = false;
+ p->rsc_pwf[avp->gpu_usage.rsc_type].anonymous_platform_no_apps = false;
}
}
}
@@ -1176,8 +1072,9 @@ void CLIENT_STATE::generate_new_host_cpid() {
}
}
-inline const char* dont_fetch_string(int reason) {
+const char* rsc_project_reason_string(int reason) {
switch (reason) {
+ case 0: return "";
case DONT_FETCH_GPUS_NOT_USABLE: return "GPUs not usable";
case DONT_FETCH_PREFS: return "blocked by project preferences";
case DONT_FETCH_CONFIG: return "client configuration";
@@ -1187,12 +1084,15 @@ inline const char* dont_fetch_string(int reason) {
case DONT_FETCH_ZERO_SHARE: return "zero resource share";
case DONT_FETCH_BUFFER_FULL: return "job cache full";
case DONT_FETCH_NOT_HIGHEST_PRIO: return "not highest priority project";
+ case DONT_FETCH_BACKED_OFF: return "project is backed off";
+ case DONT_FETCH_DEFER_SCHED: return "a job is deferred";
}
- return "";
+ return "unknown project reason";
}
-const char* cant_fetch_work_string(PROJECT* p, char* buf) {
- switch (p->pwf.cant_fetch_work_reason) {
+const char* project_reason_string(PROJECT* p, char* buf) {
+ switch (p->pwf.project_reason) {
+ case 0: return "";
case CANT_FETCH_WORK_NON_CPU_INTENSIVE:
return "non CPU intensive";
case CANT_FETCH_WORK_SUSPENDED_VIA_GUI:
@@ -1216,7 +1116,7 @@ const char* cant_fetch_work_string(PROJECT* p, char* buf) {
case CANT_FETCH_WORK_DONT_NEED:
if (coprocs.n_rsc == 1) {
sprintf(buf, "don't need (%s)",
- dont_fetch_string(rsc_work_fetch[0].dont_fetch_reason)
+ rsc_project_reason_string(rsc_work_fetch[0].dont_fetch_reason)
);
} else {
string x;
@@ -1225,7 +1125,7 @@ const char* cant_fetch_work_string(PROJECT* p, char* buf) {
char buf2[256];
sprintf(buf2, "%s: %s",
rsc_name_long(i),
- dont_fetch_string(rsc_work_fetch[i].dont_fetch_reason)
+ rsc_project_reason_string(rsc_work_fetch[i].dont_fetch_reason)
);
x += buf2;
if (i < coprocs.n_rsc-1) {
@@ -1237,5 +1137,5 @@ const char* cant_fetch_work_string(PROJECT* p, char* buf) {
}
return buf;
}
- return "";
+ return "unknown reason";
}
diff --git a/client/work_fetch.h b/client/work_fetch.h
index a2d0e23..c99e9ba 100644
--- a/client/work_fetch.h
+++ b/client/work_fetch.h
@@ -27,7 +27,7 @@
#define RSC_TYPE_ANY -1
#define RSC_TYPE_CPU 0
-// reasons for not fetching work
+// reasons for not fetching work from a project
//
#define CANT_FETCH_WORK_NON_CPU_INTENSIVE 1
#define CANT_FETCH_WORK_SUSPENDED_VIA_GUI 2
@@ -52,6 +52,8 @@
#define DONT_FETCH_ZERO_SHARE 7
#define DONT_FETCH_BUFFER_FULL 8
#define DONT_FETCH_NOT_HIGHEST_PRIO 9
+#define DONT_FETCH_BACKED_OFF 10
+#define DONT_FETCH_DEFER_SCHED 11
struct PROJECT;
struct RESULT;
@@ -74,7 +76,7 @@ struct RSC_PROJECT_WORK_FETCH {
}
double queue_est;
// an estimate of instance-secs of queued work;
- bool anon_skip;
+ bool anonymous_platform_no_apps;
// set if this project is anonymous platform
// and it has no app version that uses this resource
double fetchable_share;
@@ -95,13 +97,17 @@ struct RSC_PROJECT_WORK_FETCH {
// copy of the above used during schedule_cpus()
std::deque<RESULT*> pending;
std::deque<RESULT*>::iterator pending_iter;
+ bool has_deferred_job;
+ // This project has a coproc job of the given type for which
+ // the job is deferred because of a temporary_exit() call.
+ // Don't fetch more jobs of this type; they might have same problem
RSC_PROJECT_WORK_FETCH() {
backoff_time = 0;
backoff_interval = 0;
secs_this_rec_interval = 0;
queue_est = 0;
- anon_skip = false;
+ anonymous_platform_no_apps = false;
fetchable_share = 0;
n_runnable_jobs = 0;
sim_nused = 0;
@@ -110,6 +116,7 @@ struct RSC_PROJECT_WORK_FETCH {
non_excluded_instances = 0;
deadlines_missed = 0;
deadlines_missed_copy = 0;
+ has_deferred_job = false;
}
inline void reset() {
@@ -117,8 +124,8 @@ struct RSC_PROJECT_WORK_FETCH {
backoff_interval = 0;
}
- bool may_have_work;
- bool compute_may_have_work(PROJECT*, int rsc_type);
+ int rsc_project_reason;
+ int compute_rsc_project_reason(PROJECT*, int rsc_type);
void resource_backoff(PROJECT*, const char*);
void rr_init(PROJECT*, int rsc_type);
void clear_backoff() {
@@ -272,8 +279,8 @@ struct PROJECT_WORK_FETCH {
// temporary copy used during schedule_cpus() and work fetch
double rec_temp_save;
// temporary used during RR simulation
- int cant_fetch_work_reason;
- int compute_cant_fetch_work_reason(PROJECT*);
+ int project_reason;
+ int compute_project_reason(PROJECT*);
int n_runnable_jobs;
bool request_if_idle_and_uploading;
// Set when a job finishes.
@@ -283,6 +290,8 @@ struct PROJECT_WORK_FETCH {
memset(this, 0, sizeof(*this));
}
void reset(PROJECT*);
+ void rr_init(PROJECT*);
+ void print_state(PROJECT*);
};
// global work fetch state
@@ -305,7 +314,6 @@ struct WORK_FETCH {
void set_all_requests_hyst(PROJECT*, int rsc_type);
void print_state();
void init();
- void compute_cant_fetch_work_reason();
void rr_init();
void clear_request();
void compute_shares();
@@ -318,14 +326,13 @@ struct WORK_FETCH {
extern RSC_WORK_FETCH rsc_work_fetch[MAX_RSC];
extern WORK_FETCH work_fetch;
-extern void set_no_rsc_config();
-
extern void project_priority_init(bool for_work_fetch);
extern double project_priority(PROJECT*);
extern void adjust_rec_sched(RESULT*);
extern void adjust_rec_work_fetch(RESULT*);
extern double total_peak_flops();
-extern const char* cant_fetch_work_string(PROJECT* p, char* buf);
+extern const char* project_reason_string(PROJECT* p, char* buf);
+extern const char* rsc_project_reason_string(int);
#endif
diff --git a/clientgui/AccountInfoPage.cpp b/clientgui/AccountInfoPage.cpp
index 1a0ca51..39e2ece 100644
--- a/clientgui/AccountInfoPage.cpp
+++ b/clientgui/AccountInfoPage.cpp
@@ -492,9 +492,11 @@ void CAccountInfoPage::OnPageChanged( wxWizardExEvent& event ) {
}
}
- m_pAccountEmailAddressCtrl->SetValidator(
- CValidateEmailAddress(&m_strAccountEmailAddress)
- );
+ if (!pc.ldap_auth) {
+ m_pAccountEmailAddressCtrl->SetValidator(
+ CValidateEmailAddress(&m_strAccountEmailAddress)
+ );
+ }
m_pAccountUsernameCtrl->SetValidator(
wxTextValidator(wxFILTER_NONE, &m_strAccountUsername)
);
@@ -504,9 +506,15 @@ void CAccountInfoPage::OnPageChanged( wxWizardExEvent& event ) {
m_pAccountUsernameStaticCtrl->Hide();
m_pAccountUsernameCtrl->Hide();
- m_pAccountEmailAddressStaticCtrl->SetLabel(
- _("&Email address:")
- );
+ if (pc.ldap_auth) {
+ m_pAccountEmailAddressStaticCtrl->SetLabel(
+ _("&Email address or LDAP ID:")
+ );
+ } else {
+ m_pAccountEmailAddressStaticCtrl->SetLabel(
+ _("&Email address:")
+ );
+ }
m_pAccountEmailAddressCtrl->SetValue(m_strAccountEmailAddress);
}
diff --git a/clientgui/AdvancedFrame.cpp b/clientgui/AdvancedFrame.cpp
index 9e8a976..f6bcded 100644
--- a/clientgui/AdvancedFrame.cpp
+++ b/clientgui/AdvancedFrame.cpp
@@ -616,7 +616,6 @@ bool CAdvancedFrame::CreateMenu() {
_("Enable or disable various diagnostic messages")
);
-
// Help menu
wxMenu *menuHelp = new wxMenu;
@@ -1542,6 +1541,37 @@ void CAdvancedFrame::OnLaunchNewInstance(wxCommandEvent& WXUNUSED(event)) {
}
+void CAdvancedFrame::OnTest1ClickAttach(wxCommandEvent& WXUNUSED(event)) {
+ wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnTest1ClickAttach - Function Begin"));
+
+ CMainDocument* pDoc = wxGetApp().GetDocument();
+
+ wxASSERT(pDoc);
+ wxASSERT(wxDynamicCast(pDoc, CMainDocument));
+
+ // Stop all timers so that the wizard is the only thing doing anything
+ StopTimers();
+
+ CWizardAttach* pWizard = new CWizardAttach(this);
+
+ pWizard->RunSimpleProjectAttach();
+
+ if (pWizard)
+ pWizard->Destroy();
+
+ DeleteMenu();
+ CreateMenu();
+ pDoc->ForceCacheUpdate();
+ FireRefreshView();
+ ResetReminderTimers();
+
+ // Restart timers to continue normal operations.
+ StartTimers();
+
+ wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnTest1ClickAttach - Function End"));
+}
+
+
void CAdvancedFrame::OnHelp(wxHelpEvent& event) {
wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnHelpBOINCManager - Function Begin"));
diff --git a/clientgui/AdvancedFrame.h b/clientgui/AdvancedFrame.h
index 393e0d7..67b48dd 100644
--- a/clientgui/AdvancedFrame.h
+++ b/clientgui/AdvancedFrame.h
@@ -80,6 +80,7 @@ public:
void OnReadConfig( wxCommandEvent& event );
void OnEventLog( wxCommandEvent& event );
void OnLaunchNewInstance( wxCommandEvent& event );
+ void OnTest1ClickAttach( wxCommandEvent& event );
void OnHelp( wxHelpEvent& event );
void OnHelpBOINC( wxCommandEvent& event );
diff --git a/clientgui/CompletionPage.cpp b/clientgui/CompletionPage.cpp
index 354a6a5..48550b8 100644
--- a/clientgui/CompletionPage.cpp
+++ b/clientgui/CompletionPage.cpp
@@ -285,7 +285,7 @@ void CCompletionPage::OnPageChanged( wxWizardExEvent& event ) {
// Is this supposed to be completely automated?
// If so, then go ahead and close the wizard down now.
- if (pWAP->close_when_completed) {
+ if (pWAP->m_bCloseWhenCompleted) {
pWAP->SimulateNextButton();
}
}
diff --git a/clientgui/Events.h b/clientgui/Events.h
index 0e648f7..3927200 100644
--- a/clientgui/Events.h
+++ b/clientgui/Events.h
@@ -87,6 +87,7 @@
#define ID_EVENTLOG 6058
#define ID_LAUNCHNEWINSTANCE 6059
#define ID_DIAGNOSTICLOGFLAGS 6060
+#define ID_TEST1CLICKATTACH 6061
// Help Menu
#define ID_HELPBOINC 6035 // Locked: Used by manager_links.php
diff --git a/clientgui/MainDocument.cpp b/clientgui/MainDocument.cpp
index dc4bbe9..2c3845e 100644
--- a/clientgui/MainDocument.cpp
+++ b/clientgui/MainDocument.cpp
@@ -2518,11 +2518,7 @@ wxString result_description(RESULT* result, bool show_resources) {
} else if (result->needs_shmem) {
strBuffer += _("Waiting for shared memory");
} else if (result->scheduler_state == CPU_SCHED_SCHEDULED) {
- if (result->edf_scheduled) {
- strBuffer += _("Running, high priority");
- } else {
- strBuffer += _("Running");
- }
+ strBuffer += _("Running");
if (project && project->non_cpu_intensive) {
strBuffer += _(" (non-CPU-intensive)");
}
@@ -2539,15 +2535,14 @@ wxString result_description(RESULT* result, bool show_resources) {
}
if (result->scheduler_wait) {
if (strlen(result->scheduler_wait_reason)) {
- strBuffer += _(" (Scheduler wait: ");
+ strBuffer = _("Postponed: ");
strBuffer += wxString(result->scheduler_wait_reason, wxConvUTF8);
- strBuffer += _(")");
} else {
- strBuffer += _(" (Scheduler wait)");
+ strBuffer = _("Postponed");
}
}
if (result->network_wait) {
- strBuffer += _(" (Waiting for network access)");
+ strBuffer = _("Waiting for network access");
}
break;
case RESULT_COMPUTE_ERROR:
diff --git a/clientgui/Makefile.am b/clientgui/Makefile.am
index 4c1f1f4..3fe999d 100644
--- a/clientgui/Makefile.am
+++ b/clientgui/Makefile.am
@@ -65,6 +65,7 @@ boincmgr_SOURCES = \
ProjectInfoPage.cpp \
ProjectProcessingPage.cpp \
ProjectPropertiesPage.cpp \
+ ProjectWelcomePage.cpp \
ProxyInfoPage.cpp \
ProxyPage.cpp \
sg_BoincSimpleFrame.cpp \
diff --git a/clientgui/ProjectInfoPage.cpp b/clientgui/ProjectInfoPage.cpp
index b8bab22..27bb9c5 100644
--- a/clientgui/ProjectInfoPage.cpp
+++ b/clientgui/ProjectInfoPage.cpp
@@ -218,12 +218,15 @@ void CProjectInfoPage::CreateControls()
itemWizardPage23->SetSizer(itemBoxSizer24);
m_pTitleStaticCtrl = new wxStaticText;
- m_pTitleStaticCtrl->Create( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pTitleStaticCtrl->Create( itemWizardPage23, wxID_STATIC, _("Choose a project"),
+ wxDefaultPosition, wxDefaultSize, 0 );
m_pTitleStaticCtrl->SetFont(wxFont(10, wxSWISS, wxNORMAL, wxBOLD, FALSE, _T("Verdana")));
itemBoxSizer24->Add(m_pTitleStaticCtrl, 0, wxALIGN_LEFT|wxALL, 5);
m_pDescriptionStaticCtrl = new wxStaticText;
- m_pDescriptionStaticCtrl->Create( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pDescriptionStaticCtrl->Create( itemWizardPage23, wxID_STATIC,
+ _("To choose a project, click its name or type its URL below."),
+ wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer24->Add(m_pDescriptionStaticCtrl, 0, wxALIGN_LEFT|wxALL, 5);
itemBoxSizer24->Add(5, 5, 0, wxALIGN_LEFT|wxALL, 5);
@@ -239,7 +242,8 @@ void CProjectInfoPage::CreateControls()
wxBoxSizer* itemBoxSizer7 = new wxBoxSizer(wxVERTICAL);
itemFlexGridSizer6->Add(itemBoxSizer7, 0, wxALIGN_LEFT|wxALIGN_TOP, 0);
- m_pProjectCategoriesStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectCategoriesStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Categories:"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer7->Add(m_pProjectCategoriesStaticCtrl, 0, wxALIGN_LEFT|wxRIGHT|wxBOTTOM, 5);
// We must populate the combo box before our sizers can calculate its width.
@@ -259,7 +263,8 @@ void CProjectInfoPage::CreateControls()
);
itemBoxSizer7->Add(m_pProjectCategoriesCtrl, 0, wxGROW|wxLEFT|wxRIGHT, 5);
- m_pProjectsStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectsStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Projects:"), wxDefaultPosition, wxDefaultSize, 0 );
itemBoxSizer7->Add(m_pProjectsStaticCtrl, 0, wxALIGN_LEFT|wxTOP|wxRIGHT|wxBOTTOM, 5);
wxFlexGridSizer* itemFlexGridSizer11 = new wxFlexGridSizer(1, 0, 0);
@@ -271,7 +276,7 @@ void CProjectInfoPage::CreateControls()
m_pProjectsCtrl = new wxListBox( itemWizardPage23, ID_PROJECTS, wxDefaultPosition, wxSize(-1, ADJUSTFORYDPI(175)), m_pProjectsCtrlStrings, wxLB_SINGLE|wxLB_SORT );
itemFlexGridSizer11->Add(m_pProjectsCtrl, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT, 0);
- m_pProjectDetailsStaticCtrl = new wxStaticBox(itemWizardPage23, wxID_ANY, wxT(""));
+ m_pProjectDetailsStaticCtrl = new wxStaticBox(itemWizardPage23, wxID_ANY, _("Project details"));
wxStaticBoxSizer* itemStaticBoxSizer13 = new wxStaticBoxSizer(m_pProjectDetailsStaticCtrl, wxVERTICAL);
itemFlexGridSizer6->Add(itemStaticBoxSizer13, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
@@ -282,7 +287,8 @@ void CProjectInfoPage::CreateControls()
itemFlexGridSizer16->AddGrowableCol(1);
itemStaticBoxSizer13->Add(itemFlexGridSizer16, 0, wxGROW|wxALL, 0);
- m_pProjectDetailsResearchAreaStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectDetailsResearchAreaStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Research area:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer16->Add(m_pProjectDetailsResearchAreaStaticCtrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxBOTTOM, 2);
m_pProjectDetailsResearchAreaCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
@@ -292,7 +298,8 @@ void CProjectInfoPage::CreateControls()
itemFlexGridSizer19->AddGrowableCol(1);
itemStaticBoxSizer13->Add(itemFlexGridSizer19, 0, wxGROW|wxALL, 0);
- m_pProjectDetailsOrganizationStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectDetailsOrganizationStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Organization:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer19->Add(m_pProjectDetailsOrganizationStaticCtrl, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxBOTTOM, 2);
m_pProjectDetailsOrganizationCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
@@ -302,7 +309,8 @@ void CProjectInfoPage::CreateControls()
itemFlexGridSizer20->AddGrowableCol(1);
itemStaticBoxSizer13->Add(itemFlexGridSizer20, 0, wxGROW|wxALL, 0);
- m_pProjectDetailsURLStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectDetailsURLStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Web site:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer20->Add(m_pProjectDetailsURLStaticCtrl, 0, wxALIGN_LEFT|wxRIGHT|wxBOTTOM, 2);
m_pProjectDetailsURLCtrl = new wxHyperlinkCtrl( itemWizardPage23, wxID_STATIC, wxT("BOINC"), wxT("http://boinc.berkeley.edu/"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHL_CONTEXTMENU|wxHL_ALIGN_LEFT);
@@ -313,7 +321,8 @@ void CProjectInfoPage::CreateControls()
itemFlexGridSizer24->AddGrowableCol(0);
itemStaticBoxSizer13->Add(itemFlexGridSizer24, 0, wxGROW|wxALL, 0);
- m_pProjectDetailsSupportedPlatformsStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectDetailsSupportedPlatformsStaticCtrl = new wxStaticText( itemWizardPage23, wxID_STATIC,
+ _("Supported systems:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer24->Add(m_pProjectDetailsSupportedPlatformsStaticCtrl, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxBOTTOM, 5);
wxBoxSizer* itemBoxSizer26 = new wxBoxSizer(wxHORIZONTAL);
@@ -350,7 +359,8 @@ void CProjectInfoPage::CreateControls()
itemFlexGridSizer33->AddGrowableCol(1);
itemFlexGridSizer4->Add(itemFlexGridSizer33, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 0);
- m_pProjectURLStaticCtrl = new wxStaticText( itemWizardPage23, ID_PROJECTURLSTATICCTRL, wxT(""), wxDefaultPosition, wxDefaultSize, 0 );
+ m_pProjectURLStaticCtrl = new wxStaticText( itemWizardPage23, ID_PROJECTURLSTATICCTRL,
+ _("Project URL:"), wxDefaultPosition, wxDefaultSize, 0 );
itemFlexGridSizer33->Add(m_pProjectURLStaticCtrl, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
m_pProjectURLCtrl = new wxTextCtrl( itemWizardPage23, ID_PROJECTURLCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
@@ -622,47 +632,6 @@ void CProjectInfoPage::OnPageChanged( wxWizardExEvent& event ) {
wxASSERT(m_pProjectURLStaticCtrl);
wxASSERT(m_pProjectURLCtrl);
- m_pTitleStaticCtrl->SetLabel(
- _("Choose a project")
- );
-
- m_pDescriptionStaticCtrl->SetLabel(
- _("To choose a project, click its name or type its URL below.")
- );
-
- m_pProjectCategoriesStaticCtrl->SetLabel(
- _("Categories:")
- );
-
- m_pProjectsStaticCtrl->SetLabel(
- _("Projects:")
- );
-
- m_pProjectDetailsStaticCtrl->SetLabel(
- _("Project details")
- );
-
- m_pProjectDetailsResearchAreaStaticCtrl->SetLabel(
- _("Research area:")
- );
-
- m_pProjectDetailsOrganizationStaticCtrl->SetLabel(
- _("Organization:")
- );
-
- m_pProjectDetailsURLStaticCtrl->SetLabel(
- _("Web site:")
- );
-
- m_pProjectDetailsSupportedPlatformsStaticCtrl->SetLabel(
- _("Supported systems:")
- );
-
- m_pProjectURLStaticCtrl->SetLabel(
- _("Project URL:")
- );
-
-
// Populate the ProjectInfo data structure with the list of projects we want to show and
// any other activity we need to prep the page.
if (!m_bProjectListPopulated) {
diff --git a/clientgui/ProjectWelcomePage.cpp b/clientgui/ProjectWelcomePage.cpp
new file mode 100644
index 0000000..24ae4ef
--- /dev/null
+++ b/clientgui/ProjectWelcomePage.cpp
@@ -0,0 +1,291 @@
+// This file is part of BOINC.
+// http://boinc.berkeley.edu
+// Copyright (C) 2008 University of California
+//
+// BOINC is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// BOINC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
+//
+#if defined(__GNUG__) && !defined(__APPLE__)
+#pragma implementation "ProjectWelcomePage.h"
+#endif
+
+#include "stdwx.h"
+#include "diagnostics.h"
+#include "util.h"
+#include "mfile.h"
+#include "miofile.h"
+#include "parse.h"
+#include "error_numbers.h"
+#include "wizardex.h"
+#include "error_numbers.h"
+#include "BOINCGUIApp.h"
+#include "SkinManager.h"
+#include "MainDocument.h"
+#include "BOINCBaseWizard.h"
+#include "WizardAttach.h"
+#include "ProjectWelcomePage.h"
+
+////@begin XPM images
+////@end XPM images
+
+
+/*!
+ * CProjectWelcomePage type definition
+ */
+
+IMPLEMENT_DYNAMIC_CLASS( CProjectWelcomePage, wxWizardPageEx )
+
+/*!
+ * CProjectWelcomePage event table definition
+ */
+
+BEGIN_EVENT_TABLE( CProjectWelcomePage, wxWizardPageEx )
+
+////@begin CProjectWelcomePage event table entries
+ EVT_WIZARDEX_PAGE_CHANGED( -1, CProjectWelcomePage::OnPageChanged )
+ EVT_WIZARDEX_CANCEL( -1, CProjectWelcomePage::OnCancel )
+////@end CProjectWelcomePage event table entries
+
+END_EVENT_TABLE()
+
+/*!
+ * CProjectWelcomePage constructors
+ */
+
+CProjectWelcomePage::CProjectWelcomePage( )
+{
+}
+
+CProjectWelcomePage::CProjectWelcomePage( CBOINCBaseWizard* parent )
+{
+ Create( parent );
+}
+
+/*!
+ * WizardPage creator
+ */
+
+bool CProjectWelcomePage::Create( CBOINCBaseWizard* parent )
+{
+////@begin CProjectWelcomePage member initialisation
+
+////@end CProjectWelcomePage member initialisation
+
+ ((CWizardAttach*)parent)->IsFirstPass = false;
+
+////@begin CProjectWelcomePage creation
+ wxWizardPageEx::Create( parent, ID_PROJECTWELCOMEPAGE );
+
+ CreateControls();
+ GetSizer()->Fit(this);
+////@end CProjectWelcomePage creation
+
+ return TRUE;
+}
+
+/*!
+ * Control creation for WizardPage
+ */
+
+void CProjectWelcomePage::CreateControls()
+{
+////@begin CWelcomePage content construction
+ CProjectWelcomePage* itemWizardPage2 = this;
+
+ wxBoxSizer* itemBoxSizer3 = new wxBoxSizer(wxVERTICAL);
+ itemWizardPage2->SetSizer(itemBoxSizer3);
+
+ title_ctrl = new wxStaticText;
+ title_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ title_ctrl->SetFont(wxFont(12, wxSWISS, wxNORMAL, wxBOLD, FALSE, _T("Verdana")));
+ itemBoxSizer3->Add(title_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ intro_ctrl = new wxStaticText;
+ intro_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ itemBoxSizer3->Add(intro_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ itemBoxSizer3->Add(5, 5, 0, wxALIGN_LEFT|wxALL, 5);
+
+ wxFlexGridSizer* grid = new wxFlexGridSizer(5, 2, 0, 0);
+ grid->AddGrowableCol(1);
+ grid->SetFlexibleDirection(wxBOTH);
+ itemBoxSizer3->Add(grid, 0, wxEXPAND|wxALL, 5);
+
+ project_name1_ctrl = new wxStaticText;
+ project_name1_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_name1_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ project_name2_ctrl = new wxStaticText;
+ project_name2_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_name2_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ project_inst1_ctrl = new wxStaticText;
+ project_inst1_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_inst1_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ project_inst2_ctrl = new wxStaticText;
+ project_inst2_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_inst2_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ project_desc1_ctrl = new wxStaticText;
+ project_desc1_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_desc1_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ project_desc2_ctrl = new wxStaticText;
+ project_desc2_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_desc2_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ project_url1_ctrl = new wxStaticText;
+ project_url1_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_url1_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ project_url2_ctrl = new wxStaticText;
+ project_url2_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(project_url2_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ user_name1_ctrl = new wxStaticText;
+ user_name1_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(user_name1_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ user_name2_ctrl = new wxStaticText;
+ user_name2_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ grid->Add(user_name2_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ warning_ctrl = new wxStaticText;
+ warning_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ itemBoxSizer3->Add(warning_ctrl, 0, wxALIGN_LEFT|wxALL|wxEXPAND, 5);
+
+ continue_ctrl = new wxStaticText;
+ continue_ctrl->Create( itemWizardPage2, wxID_STATIC, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
+ itemBoxSizer3->Add(continue_ctrl, 0, wxALIGN_LEFT|wxALL, 5);
+
+ itemWizardPage2->SetSizer(itemBoxSizer3);
+
+////@end CWelcomePage content construction
+}
+
+/*
+ * Gets the previous page.
+ */
+
+wxWizardPageEx* CProjectWelcomePage::GetPrev() const
+{
+ return NULL;
+}
+
+/*!
+ * Gets the next page.
+ */
+
+wxWizardPageEx* CProjectWelcomePage::GetNext() const
+{
+ CWizardAttach* pWA = ((CWizardAttach*)GetParent());
+
+ wxASSERT(pWA);
+
+ if (CHECK_CLOSINGINPROGRESS()) {
+ // Cancel Event Detected
+ return PAGE_TRANSITION_NEXT(ID_COMPLETIONERRORPAGE);
+ } else if (pWA->GetProjectAuthenticator().IsEmpty()) {
+ return PAGE_TRANSITION_NEXT(ID_ACCOUNTINFOPAGE);
+ } else {
+ return PAGE_TRANSITION_NEXT(ID_PROJECTPROCESSINGPAGE);
+ }
+ return NULL;
+}
+
+/*!
+ * Should we show tooltips?
+ */
+
+bool CProjectWelcomePage::ShowToolTips()
+{
+ return TRUE;
+}
+
+/*!
+ * Get bitmap resources
+ */
+
+wxBitmap CProjectWelcomePage::GetBitmapResource( const wxString& WXUNUSED(name) )
+{
+ // Bitmap retrieval
+////@begin CWelcomePage bitmap retrieval
+ return wxNullBitmap;
+////@end CWelcomePage bitmap retrieval
+}
+
+/*!
+ * Get icon resources
+ */
+
+wxIcon CProjectWelcomePage::GetIconResource( const wxString& WXUNUSED(name) )
+{
+ // Icon retrieval
+////@begin CWelcomePage icon retrieval
+ return wxNullIcon;
+////@end CWelcomePage icon retrieval
+}
+
+/*!
+ * wxEVT_WIZARD_PAGE_CHANGED event handler for ID_PROJECTWELCOMEPAGE
+ */
+
+void CProjectWelcomePage::OnPageChanged( wxWizardExEvent& event ) {
+ if (event.GetDirection() == false) return;
+ wxLogTrace(wxT("Function Start/End"), wxT("CProjectWelcomePage::OnPageChanged - Function Begin"));
+
+ CWizardAttach* pWA = ((CWizardAttach*)GetParent());
+
+ wxString buf;
+ buf.Printf(_("Welcome to %s."), pWA->GetProjectName().c_str());
+ title_ctrl->SetLabel(buf);
+
+ intro_ctrl->SetLabel(_("You have volunteered to compute for this project:"));
+ project_name1_ctrl->SetLabel(_("Name:"));
+ project_name2_ctrl->SetLabel(pWA->GetProjectName());
+ if (!pWA->project_inst.IsEmpty()) {
+ project_inst1_ctrl->SetLabel(_("Home:"));
+ project_inst2_ctrl->SetLabel(pWA->project_inst);
+ }
+ if (!pWA->project_desc.IsEmpty()) {
+ project_desc1_ctrl->SetLabel(_("Description:"));
+ project_desc2_ctrl->SetLabel(pWA->project_desc);
+ }
+ project_url1_ctrl->SetLabel(_("URL:"));
+ project_url2_ctrl->SetLabel(pWA->GetProjectURL());
+ if (!pWA->user_name.IsEmpty()) {
+ user_name1_ctrl->SetLabel(_("User:"));
+ user_name2_ctrl->SetLabel(pWA->user_name);
+ }
+
+ if (!pWA->known) {
+ warning_ctrl->SetLabel(_("WARNING: This project is not registered with BOINC. Make sure you trust it before continuing."));
+
+ }
+ continue_ctrl->SetLabel(
+ _("To continue, click Next.")
+ );
+
+ Layout();
+ wxLogTrace(wxT("Function Start/End"), wxT("CProjectWelcomePage::OnPageChanged - Function End"));
+}
+
+
+/*!
+ * wxEVT_WIZARD_CANCEL event handler for ID_PROJECTWELCOMEPAGE
+ */
+
+void CProjectWelcomePage::OnCancel( wxWizardExEvent& event ) {
+ PROCESS_CANCELEVENT(event);
+}
diff --git a/clientgui/ProjectWelcomePage.h b/clientgui/ProjectWelcomePage.h
new file mode 100644
index 0000000..2aa24e1
--- /dev/null
+++ b/clientgui/ProjectWelcomePage.h
@@ -0,0 +1,95 @@
+// This file is part of BOINC.
+// http://boinc.berkeley.edu
+// Copyright (C) 2008 University of California
+//
+// BOINC is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// BOINC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
+//
+#ifndef _WIZ_PROJECTWELCOMEPAGE_H_
+#define _WIZ_PROJECTWELCOMEPAGE_H_
+
+#if defined(__GNUG__) && !defined(__APPLE__)
+#pragma interface "ProjectWelcomePage.cpp"
+#endif
+
+/*!
+ * CWelcomePage class declaration
+ */
+
+class CProjectWelcomePage: public wxWizardPageEx
+{
+ DECLARE_DYNAMIC_CLASS( CProjectWelcomePage )
+ DECLARE_EVENT_TABLE()
+
+public:
+ /// Constructors
+ CProjectWelcomePage( );
+
+ CProjectWelcomePage( CBOINCBaseWizard* parent );
+
+ /// Creation
+ bool Create( CBOINCBaseWizard* parent );
+
+ /// Creates the controls and sizers
+ void CreateControls();
+
+////@begin CProjectWelcomePage event handler declarations
+
+ /// wxEVT_WIZARD_PAGE_CHANGED event handler for ID_PROJECTWELCOMEPAGE
+ void OnPageChanged( wxWizardExEvent& event );
+
+ /// wxEVT_WIZARD_CANCEL event handler for ID_PROJECTWELCOMEPAGE
+ void OnCancel( wxWizardExEvent& event );
+
+////@end CProjectWelcomePage event handler declarations
+
+////@begin CProjectWelcomePage member function declarations
+
+ /// Gets the previous page.
+ virtual wxWizardPageEx* GetPrev() const;
+
+ /// Gets the next page.
+ virtual wxWizardPageEx* GetNext() const;
+
+ /// Retrieves bitmap resources
+ wxBitmap GetBitmapResource( const wxString& name );
+
+ /// Retrieves icon resources
+ wxIcon GetIconResource( const wxString& name );
+
+////@end CProjectWelcomePage member function declarations
+
+ /// Should we show tooltips?
+ static bool ShowToolTips();
+
+////@begin CProjectWelcomePage member variables
+ wxStaticText* title_ctrl;
+ wxStaticText* intro_ctrl;
+ wxStaticText* project_name1_ctrl;
+ wxStaticText* project_name2_ctrl;
+ wxStaticText* project_inst1_ctrl;
+ wxStaticText* project_inst2_ctrl;
+ wxStaticText* project_desc1_ctrl;
+ wxStaticText* project_desc2_ctrl;
+ wxStaticText* project_url1_ctrl;
+ wxStaticText* project_url2_ctrl;
+ wxStaticText* user_name1_ctrl;
+ wxStaticText* user_name2_ctrl;
+
+ wxStaticText* warning_ctrl;
+ wxStaticText* continue_ctrl;
+
+////@end CProjectWelcomePage member variables
+};
+
+#endif // _WIZ_WELCOMEPAGE_H_
diff --git a/clientgui/WizardAttach.cpp b/clientgui/WizardAttach.cpp
index 7beaa8a..6adc0df 100644
--- a/clientgui/WizardAttach.cpp
+++ b/clientgui/WizardAttach.cpp
@@ -39,6 +39,7 @@
#include "ProjectInfoPage.h"
#include "ProjectPropertiesPage.h"
#include "ProjectProcessingPage.h"
+#include "ProjectWelcomePage.h"
#include "AccountManagerInfoPage.h"
#include "AccountManagerPropertiesPage.h"
#include "AccountManagerProcessingPage.h"
@@ -96,6 +97,7 @@ bool CWizardAttach::Create( wxWindow* parent, wxWindowID id, const wxString& /*
m_ProjectInfoPage = NULL;
m_ProjectPropertiesPage = NULL;
m_ProjectProcessingPage = NULL;
+ m_ProjectWelcomePage = NULL;
m_AccountManagerInfoPage = NULL;
m_AccountManagerPropertiesPage = NULL;
m_AccountManagerProcessingPage = NULL;
@@ -130,7 +132,7 @@ bool CWizardAttach::Create( wxWindow* parent, wxWindowID id, const wxString& /*
account_out.clear();
account_created_successfully = false;
attached_to_project_successfully = false;
- close_when_completed = false;
+ m_bCloseWhenCompleted = false;
m_strProjectName.Empty();
m_strProjectUrl.Empty();
m_strProjectAuthenticator.Empty();
@@ -206,6 +208,10 @@ void CWizardAttach::CreateControls()
m_ProjectProcessingPage->Create( itemWizard1 );
GetPageAreaSizer()->Add(m_ProjectProcessingPage);
+ m_ProjectWelcomePage = new CProjectWelcomePage;
+ m_ProjectWelcomePage->Create( itemWizard1 );
+ GetPageAreaSizer()->Add(m_ProjectWelcomePage);
+
m_AccountInfoPage = new CAccountInfoPage;
m_AccountInfoPage->Create( itemWizard1 );
GetPageAreaSizer()->Add(m_AccountInfoPage);
@@ -276,6 +282,11 @@ void CWizardAttach::CreateControls()
);
wxLogTrace(
wxT("Function Status"),
+ wxT("CWizardAttach::CreateControls - m_ProjectWelcomePage = id: '%d', location: '%p', height: '%d', width: '%d'"),
+ m_ProjectWelcomePage->GetId(), m_ProjectWelcomePage, m_ProjectWelcomePage->GetBestSize().GetHeight(), m_ProjectWelcomePage->GetBestSize().GetWidth()
+ );
+ wxLogTrace(
+ wxT("Function Status"),
wxT("CWizardAttach::CreateControls - m_AccountManagerInfoPage = id: '%d', location: '%p', height: '%d', width: '%d'"),
m_AccountManagerInfoPage->GetId(), m_AccountManagerInfoPage, m_AccountManagerInfoPage->GetBestSize().GetHeight(), m_AccountManagerInfoPage->GetBestSize().GetWidth()
);
@@ -353,8 +364,7 @@ void CWizardAttach::CreateControls()
* Runs the wizard.
*/
bool CWizardAttach::Run(
- wxString& WXUNUSED(strName), wxString& strURL, wxString& strTeamName,
- bool bCredentialsCached
+ wxString WXUNUSED(strName), wxString strURL, wxString strTeamName, bool bCredentialsCached
) {
m_strTeamName = strTeamName;
@@ -373,7 +383,7 @@ bool CWizardAttach::Run(
if (detect_setup_authenticator(url, authenticator)) {
m_bCredentialsDetected = true;
- close_when_completed = true;
+ m_bCloseWhenCompleted = true;
SetProjectAuthenticator(wxString(authenticator.c_str(), wxConvUTF8));
}
}
@@ -388,6 +398,33 @@ bool CWizardAttach::Run(
}
+/*!
+ * Runs the wizard.
+ */
+bool CWizardAttach::RunSimpleProjectAttach() {
+ std::string name, url, authenticator, institution, description, _known;
+ wxString strName, strURL, strAuthenticator;
+
+ if (detect_simple_account_credentials(name, url, authenticator, institution, description, _known)) {
+ strName = wxURI::Unescape(wxString(name.c_str(), wxConvUTF8));
+ strURL = wxURI::Unescape(wxString(url.c_str(), wxConvUTF8));
+ strAuthenticator = wxURI::Unescape(wxString(authenticator.c_str(), wxConvUTF8));
+
+ SetProjectName(strName);
+ SetProjectURL(strURL);
+ if (authenticator.size()) {
+ SetProjectAuthenticator(strAuthenticator);
+ }
+ project_inst = wxURI::Unescape(wxString(institution.c_str(), wxConvUTF8));
+ project_desc = wxURI::Unescape(wxString(description.c_str(), wxConvUTF8));
+
+ known = _known.length() > 0;
+ }
+
+ return RunWizard(m_ProjectWelcomePage);
+}
+
+
bool CWizardAttach::SyncToAccountManager() {
ACCT_MGR_INFO ami;
CMainDocument* pDoc = wxGetApp().GetDocument();
@@ -505,7 +542,7 @@ bool CWizardAttach::HasNextPage( wxWizardPageEx* page )
bool CWizardAttach::HasPrevPage( wxWizardPageEx* page )
{
- if ((page == m_WelcomePage) || (page == m_CompletionPage) || (page == m_CompletionErrorPage))
+ if ((page == m_WelcomePage) || (page == m_ProjectWelcomePage) || (page == m_CompletionPage) || (page == m_CompletionErrorPage))
return false;
return true;
}
@@ -568,6 +605,9 @@ wxWizardPageEx* CWizardAttach::_PushPageTransition( wxWizardPageEx* pCurrentPage
if (ID_PROJECTPROCESSINGPAGE == ulPageID)
pPage = m_ProjectProcessingPage;
+ if (ID_PROJECTWELCOMEPAGE == ulPageID)
+ pPage = m_ProjectWelcomePage;
+
if (ID_ACCOUNTMANAGERINFOPAGE == ulPageID)
pPage = m_AccountManagerInfoPage;
@@ -652,7 +692,8 @@ void CWizardAttach::_ProcessCancelEvent( wxWizardExEvent& event ) {
bCancelWithoutNextPage |= (page == m_ErrAlreadyExistsPage);
} else {
bCancelWithoutNextPage |= (page == m_WelcomePage);
- }
+ bCancelWithoutNextPage |= (page == m_ProjectWelcomePage);
+ }
if (wxYES != iRetVal) {
event.Veto();
diff --git a/clientgui/WizardAttach.h b/clientgui/WizardAttach.h
index ba0f07a..14ed1b4 100644
--- a/clientgui/WizardAttach.h
+++ b/clientgui/WizardAttach.h
@@ -50,6 +50,7 @@
#define ID_PROJECTINFOPAGE 10200
#define ID_PROJECTPROPERTIESPAGE 10201
#define ID_PROJECTPROCESSINGPAGE 10202
+#define ID_PROJECTWELCOMEPAGE 10203
// Account Manager Wizard Pages
#define ID_ACCOUNTMANAGERINFOPAGE 10300
@@ -149,6 +150,7 @@ class CErrUserDisagreesPage;
class CProjectInfoPage;
class CProjectPropertiesPage;
class CProjectProcessingPage;
+class CProjectWelcomePage;
class CAccountManagerInfoPage;
class CAccountManagerPropertiesPage;
class CAccountManagerProcessingPage;
@@ -220,13 +222,16 @@ public:
/// Runs the wizard.
bool Run(
- wxString& strName,
- wxString& strURL,
- wxString& wxString,
+ wxString strName,
+ wxString strURL,
+ wxString strTeamName,
bool bCredentialsCached = true
);
- // Synchronize to Account Manager
+ /// Runs the wizard.
+ bool RunSimpleProjectAttach();
+
+ /// Synchronize to Account Manager
bool SyncToAccountManager();
/// Retrieves bitmap resources
@@ -234,7 +239,8 @@ public:
/// Retrieves icon resources
wxIcon GetIconResource( const wxString& name );
-////@end CWizardAttachProject member function declarations
+
+ ////@end CWizardAttachProject member function declarations
/// Overrides
virtual bool HasNextPage( wxWizardPageEx* page );
@@ -271,6 +277,7 @@ public:
CProjectInfoPage* m_ProjectInfoPage;
CProjectPropertiesPage* m_ProjectPropertiesPage;
CProjectProcessingPage* m_ProjectProcessingPage;
+ CProjectWelcomePage* m_ProjectWelcomePage;
CAccountManagerInfoPage* m_AccountManagerInfoPage;
CAccountManagerPropertiesPage* m_AccountManagerPropertiesPage;
CAccountManagerProcessingPage* m_AccountManagerProcessingPage;
@@ -302,7 +309,7 @@ public:
ACCOUNT_OUT account_out;
bool account_created_successfully;
bool attached_to_project_successfully;
- bool close_when_completed;
+ bool m_bCloseWhenCompleted;
bool m_bCredentialsCached;
bool m_bCredentialsDetected;
wxString m_strProjectName;
@@ -312,6 +319,10 @@ public:
wxString m_strReturnURL;
bool m_bCookieRequired;
wxString m_strCookieFailureURL;
+ wxString project_inst; // institution
+ wxString project_desc; // description
+ wxString user_name;
+ bool known;
};
#endif // _WIZ_ATTACH_H_
diff --git a/clientgui/browser.cpp b/clientgui/browser.cpp
index 4ee63a8..38b3747 100644
--- a/clientgui/browser.cpp
+++ b/clientgui/browser.cpp
@@ -42,6 +42,7 @@ BOOL WINAPI InternetGetCookieA( LPCSTR lpszUrl, LPCSTR lpszCookieName, LPSTR lps
#include <time.h>
#endif
+#include <sqlite3.h>
#include "error_numbers.h"
#include "mfile.h"
#include "miofile.h"
@@ -593,10 +594,6 @@ bool detect_cookie_mozilla_v3(
int rc;
MOZILLA_COOKIE_SQL cookie;
-#if defined(__APPLE__)
- // sqlite3 is not available on Mac OS 10.3.9
- if (sqlite3_open == NULL) return false;
-#endif
// determine the project hostname using the project url
parse_hostname_mozilla_compatible(project_url, hostname);
@@ -805,10 +802,6 @@ bool detect_cookie_chrome(
int rc;
CHROME_COOKIE_SQL cookie;
-#if defined(__APPLE__)
- // sqlite3 is not available on Mac OS 10.3.9
- if (sqlite3_open == NULL) return false;
-#endif
// determine the project hostname using the project url
parse_hostname_chrome_compatible(project_url, hostname);
@@ -819,7 +812,12 @@ bool detect_cookie_chrome(
rc = sqlite3_open(tmp.c_str(), &db);
if ( rc ) {
sqlite3_close(db);
- return false;
+ tmp = profile_root + "Safe Browsing Cookies";
+ rc = sqlite3_open(tmp.c_str(), &db);
+ if ( rc ) {
+ sqlite3_close(db);
+ return false;
+ }
}
// construct SQL query to extract the desired cookie
@@ -923,7 +921,7 @@ bool detect_cookie_ie_supported(std::string& project_url, std::string& name, std
strCookieName = strCookieFragment.substr(0, uiDelimeterLocation);
strCookieValue = strCookieFragment.substr(uiDelimeterLocation + 1);
- if (name == strCookieName) {
+ if (0 == strcmp(name.c_str(), strCookieName.c_str())) {
// Now we found it! Yea - auto attach!
value = strCookieValue;
bReturnValue = true;
@@ -1011,7 +1009,7 @@ bool detect_cookie_ie_supported_uac(std::string& project_url, std::string& name,
strCookieName = strCookieFragment.substr(0, uiDelimeterLocation);
strCookieValue = strCookieFragment.substr(uiDelimeterLocation + 1);
- if (name_w == strCookieName) {
+ if (0 == wcscmp(name_w.c_str(), strCookieName.c_str())) {
// Now we found it! Yea - auto attach!
value = W2A(strCookieValue);
bReturnValue = true;
@@ -1271,6 +1269,86 @@ END:
//
// walk through the various browsers looking up the
+// various cookies that make up the simple account creation scheme.
+//
+// give preference to the default platform specific browers first before going
+// to the platform independant browsers since most people don't switch from
+// the default.
+//
+bool detect_simple_account_credentials(
+ std::string& project_name, std::string& project_url, std::string& authenticator,
+ std::string& project_institution, std::string& project_description, std::string& known
+) {
+ bool retval = false;
+ std::string strCookieServer("http://boinc.berkeley.edu");
+ std::string strCookieProjectName("attach_project_name");
+ std::string strCookieProjectURL("attach_master_url");
+ std::string strCookieAuthenticator("attach_auth");
+ std::string strCookieProjectInstitution("attach_project_inst");
+ std::string strCookieProjectDescription("attach_project_desc");
+ std::string strCookieKnown("attach_known");
+
+#ifdef _WIN32
+ if ( detect_cookie_ie(strCookieServer, strCookieProjectName, project_name) &&
+ detect_cookie_ie(strCookieServer, strCookieProjectURL, project_url)
+ ){
+ detect_cookie_ie(strCookieServer, strCookieAuthenticator, authenticator);
+ detect_cookie_ie(strCookieServer, strCookieProjectInstitution, project_institution);
+ detect_cookie_ie(strCookieServer, strCookieProjectDescription, project_description);
+ detect_cookie_ie(strCookieServer, strCookieKnown, known);
+ goto END;
+ }
+#endif
+#ifdef __APPLE__
+ if ( detect_cookie_safari(strCookieServer, strCookieProjectName, project_name) &&
+ detect_cookie_safari(strCookieServer, strCookieProjectURL, project_url)
+ ){
+ detect_cookie_safari(strCookieServer, strCookieAuthenticator, authenticator);
+ detect_cookie_safari(strCookieServer, strCookieProjectInstitution, project_institution);
+ detect_cookie_safari(strCookieServer, strCookieProjectDescription, project_description);
+ detect_cookie_safari(strCookieServer, strCookieKnown, known);
+ goto END;
+ }
+#endif
+ if ( detect_cookie_chrome(strCookieServer, strCookieProjectName, project_name) &&
+ detect_cookie_chrome(strCookieServer, strCookieProjectURL, project_url)
+ ){
+ detect_cookie_chrome(strCookieServer, strCookieAuthenticator, authenticator);
+ detect_cookie_chrome(strCookieServer, strCookieProjectInstitution, project_institution);
+ detect_cookie_chrome(strCookieServer, strCookieProjectDescription, project_description);
+ detect_cookie_chrome(strCookieServer, strCookieKnown, known);
+ goto END;
+ }
+ if ( detect_cookie_firefox_3(strCookieServer, strCookieProjectName, project_name) &&
+ detect_cookie_firefox_3(strCookieServer, strCookieProjectURL, project_url)
+ ){
+ detect_cookie_firefox_3(strCookieServer, strCookieAuthenticator, authenticator);
+ detect_cookie_firefox_3(strCookieServer, strCookieProjectInstitution, project_institution);
+ detect_cookie_firefox_3(strCookieServer, strCookieProjectDescription, project_description);
+ detect_cookie_firefox_3(strCookieServer, strCookieKnown, known);
+ goto END;
+ }
+ if ( detect_cookie_firefox_2(strCookieServer, strCookieProjectName, project_name) &&
+ detect_cookie_firefox_2(strCookieServer, strCookieProjectURL, project_url)
+ ){
+ detect_cookie_firefox_2(strCookieServer, strCookieAuthenticator, authenticator);
+ detect_cookie_firefox_2(strCookieServer, strCookieProjectInstitution, project_institution);
+ detect_cookie_firefox_2(strCookieServer, strCookieProjectDescription, project_description);
+ detect_cookie_firefox_2(strCookieServer, strCookieKnown, known);
+ goto END;
+ }
+
+END:
+ if (!project_name.empty() && !project_url.empty()) {
+ retval = true;
+ }
+
+ return retval;
+}
+
+
+//
+// walk through the various browsers looking up the
// account manager cookies until the account manager's 'Login' and 'Password_Hash'
// cookies are found.
//
diff --git a/clientgui/browser.h b/clientgui/browser.h
index dac9ac3..587a589 100644
--- a/clientgui/browser.h
+++ b/clientgui/browser.h
@@ -18,8 +18,6 @@
#ifndef _BROWSER_
#define _BROWSER_
-#include <sqlite3.h>
-
//
// The BOINC client now supports the ability to lookup a users
// authenticator during automatic attachments via a browser
@@ -27,7 +25,17 @@
//
bool detect_setup_authenticator(std::string& project_url, std::string& authenticator);
-bool detect_account_manager_credentials(std::string& project_url, std::string& login, std::string& password_hash, std::string& return_url);
+
+bool detect_simple_account_credentials(
+ std::string& project_name, std::string& project_url, std::string& authenticator,
+ std::string& project_institution, std::string& project_description, std::string& known
+);
+
+bool detect_account_manager_credentials(
+ std::string& project_url, std::string& login, std::string& password_hash,
+ std::string& return_url
+);
+
bool is_authenticator_valid(const std::string authenticator);
// platform specific browsers
@@ -45,19 +53,4 @@ bool detect_cookie_firefox_2(std::string& project_url, std::string& name, std::s
bool detect_cookie_firefox_3(std::string& project_url, std::string& name, std::string& value);
bool detect_cookie_chrome(std::string& project_url, std::string& name, std::string& value);
-#if 0 //defined(__APPLE__)
-#undef sqlite3_free
-#ifdef __cplusplus
-extern "C" {
-#endif
- // sqlite3 is not available on Mac OS 10.3.9
- extern int sqlite3_open(const char *filename, sqlite3 **ppDb) __attribute__((weak_import));
- extern int sqlite3_close(sqlite3 *) __attribute__((weak_import));
- extern int sqlite3_exec(sqlite3*, const char *sql, sqlite3_callback, void *, char **errmsg) __attribute__((weak_import));
- extern void sqlite3_free(void *z) __attribute__((weak_import));
-#ifdef __cplusplus
-}
-#endif
-#endif
-
#endif
diff --git a/configure.ac b/configure.ac
index de4f12e..76ca094 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ dnl not sure exactly what the minimum version is (but 2.13 wont work)
AC_PREREQ(2.58)
dnl Set the BOINC version here. You can also use the set-version script.
-AC_INIT(BOINC, 7.4.23)
+AC_INIT(BOINC, 7.4.27)
AC_CONFIG_MACRO_DIR([m4])
LIBBOINC_VERSION=`echo ${PACKAGE_VERSION} | sed 's/\./:/g'`
AC_SUBST([LIBBOINC_VERSION])
diff --git a/html/user/get_project_config.php b/html/user/get_project_config.php
index 793bf58..0dbfc3c 100644
--- a/html/user/get_project_config.php
+++ b/html/user/get_project_config.php
@@ -107,6 +107,10 @@ if (file_exists($tou_file)) {
}
}
+if (LDAP_HOST) {
+ echo "<ldap_auth/>\n";
+}
+
echo "</project_config>";
?>
diff --git a/html/user/lookup_account.php b/html/user/lookup_account.php
index f86a83a..67e53c6 100644
--- a/html/user/lookup_account.php
+++ b/html/user/lookup_account.php
@@ -22,45 +22,65 @@ require_once("../inc/boinc_db.inc");
require_once("../inc/util.inc");
require_once("../inc/email.inc");
require_once("../inc/xml.inc");
+require_once("../inc/ldap.inc");
xml_header();
$retval = db_init_xml();
if ($retval) xml_error($retval);
-$email_addr = get_str("email_addr");
-$passwd_hash = get_str("passwd_hash", true);
+$ldap_auth = get_str("ldap_auth", true);
-$email_addr = BoincDb::escape_string($email_addr);
-$user = BoincUser::lookup("email_addr='$email_addr'");
-if (!$user) {
- xml_error(ERR_DB_NOT_FOUND);
-}
+if (LDAP_HOST && $ldap_auth) {
+ // LDAP case.
+ //
+ $ldap_uid = get_str("ldap_uid");
+ $passwd = get_str("passwd");
+ list ($ldap_user, $error_msg) = ldap_auth($ldap_uid, $passwd);
+ if ($error_msg) {
+ xml_error(ERR_BAD_USER_NAME, $error_msg);
+ }
+ $x = ldap_email_string($ldap_uid);
+ $user = BoincUser::lookup_email_addr($x);
+ if (!$user) {
+ $user = make_user_ldap($x, $ldap_user->name);
+ if (!$user) {
+ xml_error(-1, "user record creation failed");
+ }
+ }
+} else {
+ // normal (non-LDAP) case
+ $email_addr = get_str("email_addr");
+ $passwd_hash = get_str("passwd_hash", true);
-if (!$passwd_hash) {
- echo "<account_out>
- <success/>
-</account_out>
-";
- exit();
-}
+ $email_addr = BoincDb::escape_string($email_addr);
+ $user = BoincUser::lookup("email_addr='$email_addr'");
+ if (!$user) {
+ xml_error(ERR_DB_NOT_FOUND);
+ }
-$auth_hash = md5($user->authenticator.$user->email_addr);
+ if (!$passwd_hash) {
+ echo "<account_out>\n";
+ echo " <success/>\n";
+ echo "</account_out>\n";
+ exit();
+ }
-// if no password set, set password to account key
-//
-if (!strlen($user->passwd_hash)) {
- $user->passwd_hash = $auth_hash;
- $user->update("passwd_hash='$user->passwd_hash'");
-}
+ $auth_hash = md5($user->authenticator.$user->email_addr);
-// if the given password hash matches (auth+email), accept it
-//
-if ($user->passwd_hash == $passwd_hash || $auth_hash == $passwd_hash) {
- echo "<account_out>\n";
- echo "<authenticator>$user->authenticator</authenticator>\n";
- echo "</account_out>\n";
-} else {
- xml_error(ERR_BAD_PASSWD);
-}
+ // if no password set, set password to account key
+ //
+ if (!strlen($user->passwd_hash)) {
+ $user->passwd_hash = $auth_hash;
+ $user->update("passwd_hash='$user->passwd_hash'");
+ }
+ // if the given password hash matches (auth+email), accept it
+ //
+ if ($user->passwd_hash != $passwd_hash && $auth_hash != $passwd_hash) {
+ xml_error(ERR_BAD_PASSWD);
+ }
+}
+echo "<account_out>\n";
+echo "<authenticator>$user->authenticator</authenticator>\n";
+echo "</account_out>\n";
?>
diff --git a/lib/app_ipc.cpp b/lib/app_ipc.cpp
index 737e45c..1a7a290 100644
--- a/lib/app_ipc.cpp
+++ b/lib/app_ipc.cpp
@@ -35,7 +35,7 @@
#include "app_ipc.h"
-#if !defined(HAVE_STRDUP) && defined(HAVE__STRDUP)
+#if (!defined(HAVE_STRDUP) && defined(HAVE__STRDUP)) || defined(_MSC_VER)
#define strdup _strdup
#endif
diff --git a/lib/cc_config.cpp b/lib/cc_config.cpp
index efe486a..2aa644d 100644
--- a/lib/cc_config.cpp
+++ b/lib/cc_config.cpp
@@ -205,10 +205,10 @@ void CC_CONFIG::defaults() {
client_new_version_text = "";
client_version_check_url = "http://boinc.berkeley.edu/download.php?xml=1";
config_coprocs.clear();
- data_dir[0] = 0;
disallow_attach = false;
dont_check_file_sizes = false;
dont_contact_ref_site = false;
+ dont_use_vbox = false;
exclude_gpus.clear();
exclusive_apps.clear();
exclusive_gpu_apps.clear();
@@ -335,12 +335,10 @@ int CC_CONFIG::parse_options(XML_PARSER& xp) {
config_coprocs.add(c);
continue;
}
- if (xp.parse_str("data_dir", data_dir, sizeof(data_dir))) {
- continue;
- }
if (xp.parse_bool("disallow_attach", disallow_attach)) continue;
if (xp.parse_bool("dont_check_file_sizes", dont_check_file_sizes)) continue;
if (xp.parse_bool("dont_contact_ref_site", dont_contact_ref_site)) continue;
+ if (xp.parse_bool("dont_use_vbox", dont_use_vbox)) continue;
if (xp.match_tag("exclude_gpu")) {
EXCLUDE_GPU eg;
retval = eg.parse(xp);
@@ -539,19 +537,15 @@ int CC_CONFIG::write(MIOFILE& out, LOG_FLAGS& log_flags) {
);
}
- // Older versions of BOINC choke on empty data_dir string
- //
- if (strlen(data_dir)) {
- out.printf(" <data_dir>%s</data_dir>\n", data_dir);
- }
-
out.printf(
" <disallow_attach>%d</disallow_attach>\n"
" <dont_check_file_sizes>%d</dont_check_file_sizes>\n"
- " <dont_contact_ref_site>%d</dont_contact_ref_site>\n",
+ " <dont_contact_ref_site>%d</dont_contact_ref_site>\n"
+ " <dont_use_vbox>%d</dont_use_vbox>\n",
disallow_attach,
dont_check_file_sizes,
- dont_contact_ref_site
+ dont_contact_ref_site,
+ dont_use_vbox
);
for (i=0; i<exclude_gpus.size(); i++) {
diff --git a/lib/cc_config.h b/lib/cc_config.h
index 5b1eb50..be8406c 100644
--- a/lib/cc_config.h
+++ b/lib/cc_config.h
@@ -146,11 +146,10 @@ struct CC_CONFIG {
std::string client_new_version_text;
std::string client_version_check_url;
COPROCS config_coprocs;
- char data_dir[256];
bool disallow_attach;
bool dont_check_file_sizes;
- int max_event_log_lines;
bool dont_contact_ref_site;
+ bool dont_use_vbox;
std::vector<EXCLUDE_GPU> exclude_gpus;
std::vector<std::string> exclusive_apps;
std::vector<std::string> exclusive_gpu_apps;
@@ -164,6 +163,7 @@ struct CC_CONFIG {
int http_transfer_timeout_bps;
int http_transfer_timeout;
std::vector<int> ignore_gpu_instance[NPROC_TYPES];
+ int max_event_log_lines;
int max_file_xfers;
int max_file_xfers_per_project;
int max_stderr_file_size;
diff --git a/lib/coproc.h b/lib/coproc.h
index 2d699df..3db9b22 100644
--- a/lib/coproc.h
+++ b/lib/coproc.h
@@ -89,31 +89,18 @@
#include "cl_boinc.h"
#include "opencl_boinc.h"
-#define DEFER_ON_GPU_AVAIL_RAM 0
-
#define MAX_COPROC_INSTANCES 64
#define MAX_RSC 8
// max # of processing resources types
// arguments to proc_type_name() and proc_type_name_xml().
//
-enum {
- PROC_TYPE_CPU=0,
- PROC_TYPE_NVIDIA_GPU,
- PROC_TYPE_AMD_GPU,
- PROC_TYPE_INTEL_GPU,
- PROC_TYPE_A,
- PROC_TYPE_B,
- PROC_TYPE_C,
- PROC_TYPE_D,
- PROC_TYPE_E,
- PROC_TYPE_F,
- PROC_TYPE_G,
- NPROC_TYPES
-};
-
-extern const char* proc_type_names_xml[NPROC_TYPES];
-extern const char* proc_type_names[NPROC_TYPES];
+#define PROC_TYPE_CPU 0
+#define PROC_TYPE_NVIDIA_GPU 1
+#define PROC_TYPE_AMD_GPU 2
+#define PROC_TYPE_INTEL_GPU 3
+#define PROC_TYPE_MINER_ASIC 4
+#define NPROC_TYPES 5
extern const char* proc_type_name(int);
// user-readable name
@@ -125,13 +112,6 @@ extern int coproc_type_name_to_num(const char* name);
#define GPU_TYPE_NVIDIA proc_type_name_xml(PROC_TYPE_NVIDIA_GPU)
#define GPU_TYPE_ATI proc_type_name_xml(PROC_TYPE_AMD_GPU)
#define GPU_TYPE_INTEL proc_type_name_xml(PROC_TYPE_INTEL_GPU)
-#define COPROC_TYPE_A proc_type_name_xml(PROC_TYPE_A)
-#define COPROC_TYPE_B proc_type_name_xml(PROC_TYPE_B)
-#define COPROC_TYPE_C proc_type_name_xml(PROC_TYPE_C)
-#define COPROC_TYPE_D proc_type_name_xml(PROC_TYPE_D)
-#define COPROC_TYPE_E proc_type_name_xml(PROC_TYPE_E)
-#define COPROC_TYPE_F proc_type_name_xml(PROC_TYPE_F)
-#define COPROC_TYPE_G proc_type_name_xml(PROC_TYPE_G)
// represents a requirement for a coproc.
// This is a parsed version of the <coproc> elements in an <app_version>
@@ -202,10 +182,6 @@ struct COPROC {
bool running_graphics_app[MAX_COPROC_INSTANCES];
// is this GPU running a graphics app (NVIDIA only)
-#if DEFER_ON_GPU_AVAIL_RAM
- double available_ram_temp[MAX_COPROC_INSTANCES];
- // used during job scheduling
-#endif
double last_print_time;
diff --git a/lib/error_numbers.h b/lib/error_numbers.h
index fc7d14e..e4c76c2 100644
--- a/lib/error_numbers.h
+++ b/lib/error_numbers.h
@@ -203,6 +203,7 @@
#define ERR_PROC_PARSE -235
#define ERR_STATFS -236
#define ERR_PIPE -237
+#define ERR_NEED_HTTPS -238
// PLEASE: add a text description of your error to
// the text description function boincerror() in str_util.cpp.
diff --git a/lib/gui_rpc_client.h b/lib/gui_rpc_client.h
index 1ac988c..e9c11b1 100644
--- a/lib/gui_rpc_client.h
+++ b/lib/gui_rpc_client.h
@@ -559,6 +559,8 @@ struct PROJECT_CONFIG {
// before allowing attachment to continue.
std::vector<std::string> platforms;
// platforms supported by project, or empty
+ bool ldap_auth;
+ // project supports LDAP authentication
PROJECT_CONFIG();
~PROJECT_CONFIG();
@@ -572,7 +574,7 @@ struct ACCOUNT_IN {
std::string url;
// URL prefix for web RPCs
std::string email_addr;
- // the account identifier (email address or user name)
+ // the account identifier (email address, user name, or LDAP uid)
std::string user_name;
std::string passwd;
std::string team_name;
diff --git a/lib/gui_rpc_client_ops.cpp b/lib/gui_rpc_client_ops.cpp
index 9528830..63b8c82 100644
--- a/lib/gui_rpc_client_ops.cpp
+++ b/lib/gui_rpc_client_ops.cpp
@@ -2303,9 +2303,16 @@ int RPC_CLIENT::lookup_account(ACCOUNT_IN& ai) {
SET_LOCALE sl;
char buf[1024];
RPC rpc(this);
+ string passwd_hash;
- downcase_string(ai.email_addr);
- string passwd_hash = get_passwd_hash(ai.passwd, ai.email_addr);
+ if (strchr(ai.email_addr.c_str(), '@')) {
+ downcase_string(ai.email_addr);
+ passwd_hash = get_passwd_hash(ai.passwd, ai.email_addr);
+ } else {
+ // LDAP case
+ //
+ passwd_hash = ai.passwd;
+ }
snprintf(buf, sizeof(buf),
"<lookup_account>\n"
" <url>%s</url>\n"
diff --git a/lib/notice.cpp b/lib/notice.cpp
index 5f907e9..f26e591 100644
--- a/lib/notice.cpp
+++ b/lib/notice.cpp
@@ -49,10 +49,7 @@ int NOTICE::parse(XML_PARSER& xp) {
}
if (xp.parse_int("seqno", seqno)) continue;
if (xp.parse_str("title", title, sizeof(title))) continue;
- if (xp.parse_string("description", description)) {
- xml_unescape(description); // 2nd pass
- continue;
- }
+ if (xp.parse_string("description", description)) continue;
if (xp.parse_double("create_time", create_time)) continue;
if (xp.parse_double("arrival_time", arrival_time)) continue;
if (xp.parse_bool("is_private", is_private)) continue;
diff --git a/lib/opencl_boinc.cpp b/lib/opencl_boinc.cpp
index 12a1aaa..4efd376 100644
--- a/lib/opencl_boinc.cpp
+++ b/lib/opencl_boinc.cpp
@@ -84,16 +84,16 @@ void OPENCL_DEVICE_PROP::write_xml(MIOFILE& f, const char* tag, bool temp_file)
);
if (temp_file) {
f.printf(
- " <is_used>%d</is_used>\n"
" <device_num>%d</device_num>\n"
" <peak_flops>%f</peak_flops>\n"
" <opencl_available_ram>%f</opencl_available_ram>\n"
- " <opencl_device_index>%d</opencl_device_index>\n",
- is_used,
+ " <opencl_device_index>%d</opencl_device_index>\n"
+ " <warn_bad_cuda>%d</warn_bad_cuda>\n",
device_num,
peak_flops,
opencl_available_ram,
- opencl_device_index
+ opencl_device_index,
+ warn_bad_cuda
);
}
f.printf(" </%s>\n", tag);
@@ -182,10 +182,6 @@ int OPENCL_DEVICE_PROP::parse(XML_PARSER& xp, const char* end_tag) {
// The following are used only in the
// COPROC_INFO_FILENAME temporary file
- if (xp.parse_int("is_used", n)) {
- is_used = (COPROC_USAGE)n;
- continue;
- }
if (xp.parse_int("device_num", n)) {
device_num = n;
continue;
@@ -196,6 +192,7 @@ int OPENCL_DEVICE_PROP::parse(XML_PARSER& xp, const char* end_tag) {
opencl_device_index = n;
continue;
}
+ if (xp.parse_bool("warn_bad_cuda", warn_bad_cuda)) continue;
}
return ERR_XML_PARSE;
}
diff --git a/lib/opencl_boinc.h b/lib/opencl_boinc.h
index 3041552..aaf490e 100644
--- a/lib/opencl_boinc.h
+++ b/lib/opencl_boinc.h
@@ -64,6 +64,7 @@ struct OPENCL_DEVICE_PROP {
COPROC_USAGE is_used; // temp used in scan process
double opencl_available_ram; // temp used in scan process
int opencl_device_index; // zero-based device number within this OpenCL platform
+ bool warn_bad_cuda; // If true, warn we can't use GPU due to CUDA version
void write_xml(MIOFILE&, const char* tag, bool temp_file=false);
int parse(XML_PARSER&, const char* end_tag);
diff --git a/lib/procinfo_mac.cpp b/lib/procinfo_mac.cpp
index 639a463..e9ddec6 100644
--- a/lib/procinfo_mac.cpp
+++ b/lib/procinfo_mac.cpp
@@ -137,6 +137,11 @@ int procinfo_setup(PROC_MAP& pm) {
p.swap_size = (double)virtual_mem * 1024.;
p.user_time += 60. * (float)hours;
p.is_boinc_app = (p.id == pid || strcasestr(p.command, "boinc"));
+ // Ideally, we should count ScreenSaverEngine.app as a BOINC process
+ // only if BOINC is set as the screensaver. We could set a flag in
+ // the client when the get_screensaver_tasks rpc is called, but that
+ // would not be 100% reliable for several reasons.
+ if (strcasestr(p.command, "screensaverengine")) p.is_boinc_app = true;
p.is_low_priority = (priority <= 12);
switch (iBrandID) {
diff --git a/lib/str_util.cpp b/lib/str_util.cpp
index 041a57b..fc75e53 100644
--- a/lib/str_util.cpp
+++ b/lib/str_util.cpp
@@ -528,6 +528,7 @@ const char* boincerror(int which_error) {
case ERR_ABORTED_ON_EXIT: return "job was aborted on client exit";
case ERR_PROC_PARSE: return "a /proc entry was not parsed correctly";
case ERR_PIPE: return "pipe() failed";
+ case ERR_NEED_HTTPS: return "HTTPS needed";
case 404: return "HTTP file not found";
case 407: return "HTTP proxy authentication failure";
case 416: return "HTTP range request error";
diff --git a/lib/url.cpp b/lib/url.cpp
index 6b093bf..a1a2e35 100644
--- a/lib/url.cpp
+++ b/lib/url.cpp
@@ -290,3 +290,6 @@ void escape_project_url(char *in, char* out) {
}
}
+bool is_https(const char* url) {
+ return (strncmp(url, "https://", 8) == 0);
+}
diff --git a/lib/url.h b/lib/url.h
index 32b715b..c687554 100644
--- a/lib/url.h
+++ b/lib/url.h
@@ -45,5 +45,6 @@ extern void escape_project_url(char *in, char* out);
extern bool valid_master_url(char*);
extern void canonicalize_master_url(char *url, int len);
extern void canonicalize_master_url(std::string&);
+extern bool is_https(const char*);
#endif
diff --git a/py/Boinc/boinc_db.py b/py/Boinc/boinc_db.py
index c70d29e..36efe47 100644
--- a/py/Boinc/boinc_db.py
+++ b/py/Boinc/boinc_db.py
@@ -77,6 +77,12 @@ MODE_BLANKSCREEN = 4
MODE_REREAD_PREFS = 5
MODE_QUIT = 6
NGRAPHICS_MSGS = 7
+PROCESS_PRIORITY_UNSPECIFIED = 0
+PROCESS_PRIORITY_LOWEST = 1
+PROCESS_PRIORITY_LOW = 2
+PROCESS_PRIORITY_NORMAL = 3
+PROCESS_PRIORITY_HIGH = 4
+PROCESS_PRIORITY_HIGHEST = 5
MSG_INFO = 1
MSG_USER_ALERT = 2
MSG_INTERNAL_ERROR = 3
diff --git a/sched/script_validator.cpp b/sched/script_validator.cpp
new file mode 100644
index 0000000..43b80de
--- /dev/null
+++ b/sched/script_validator.cpp
@@ -0,0 +1,128 @@
+// This file is part of BOINC.
+// http://boinc.berkeley.edu
+// Copyright (C) 2014 University of California
+//
+// BOINC is free software; you can redistribute it and/or modify it
+// under the terms of the GNU Lesser General Public License
+// as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// BOINC is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
+
+// A validator that runs scripts to check and compare results
+// cmdline args:
+// --init_script scriptname
+// --compare_script scriptname
+//
+// the init script is called as
+// scriptname f1 ... fn
+// where f1 ... fn are the output files of a job (there may be just one)
+// It returns zero if the files are valid
+//
+// the compare script is called as
+// scriptname f1 ... fn g1 ... gn
+// where f1 ... fn are the output files of one job,
+// and g1 ... gn are the output files are another job.
+// It returns zero if the files are equivalent.
+
+#include <sys/param.h>
+
+#include "validate_util2.h"
+#include "error_numbers.h"
+#include "boinc_db.h"
+#include "sched_util.h"
+#include "validate_util.h"
+#include "validator.h"
+
+using std::string;
+using std::vector;
+
+bool first = true;
+char init_script[MAXPATHLEN], compare_script[MAXPATHLEN];
+
+void parse_cmdline() {
+ strcpy(init_script, "");
+ strcpy(compare_script, "");
+ for (int i=1; i<g_argc; i++) {
+ if (!strcmp(g_argv[i], "--init_script")) {
+ sprintf(init_script, "../bin/%s", g_argv[++i]);
+ } else if (!strcmp(g_argv[i], "--compare_script")) {
+ sprintf(compare_script, "../bin/%s", g_argv[++i]);
+ }
+ }
+ if (!strlen(init_script) && !strlen(compare_script)) {
+ log_messages.printf(MSG_CRITICAL,
+ "script names missing from command line\n"
+ );
+ exit(1);
+ }
+}
+
+int init_result(RESULT& result, void*&) {
+ if (!strlen(init_script)) return 0;
+ vector<string> paths;
+ int retval;
+ retval = get_output_file_paths(result, paths);
+ if (retval) {
+ fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
+ return retval;
+ }
+ char cmd[4096];
+ strcpy(cmd, init_script);
+ for (unsigned int i=0; i<paths.size(); i++) {
+ strcat(cmd, " ");
+ strcat(cmd, paths[i].c_str());
+ }
+ retval = system(cmd);
+ if (retval) {
+ return retval;
+ }
+ return 0;
+}
+
+int compare_results(RESULT& r1, void*, RESULT const& r2, void*, bool& match) {
+ if (!strlen(compare_script)) {
+ match = true;
+ return 0;
+ }
+ vector<string> paths1, paths2;
+ int retval;
+ retval = get_output_file_paths(r1, paths1);
+ if (retval) {
+ fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
+ return retval;
+ }
+ retval = get_output_file_paths(r2, paths2);
+ if (retval) {
+ fprintf(stderr, "get_output_file_paths() returned %d\n", retval);
+ return retval;
+ }
+ char cmd[4096];
+ strcpy(cmd, compare_script);
+ for (unsigned int i=0; i<paths1.size(); i++) {
+ strcat(cmd, " ");
+ strcat(cmd, paths1[i].c_str());
+ }
+ for (unsigned int i=0; i<paths2.size(); i++) {
+ strcat(cmd, " ");
+ strcat(cmd, paths2[i].c_str());
+ }
+ retval = system(cmd);
+ if (retval) {
+ match = false;
+ } else {
+ match = true;
+ }
+ return 0;
+}
+
+int cleanup_result(RESULT const&, void*) {
+ return 0;
+}
+
diff --git a/version.log b/version.log
index fac714a..76ae95b 100644
--- a/version.log
+++ b/version.log
@@ -1 +1 @@
-6.11.1
+7.4.27
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-boinc/boinc.git
More information about the pkg-boinc-commits
mailing list