- client code: my next-to-last checkin was flawed

svn path=/trunk/boinc/; revision=14725
This commit is contained in:
David Anderson 2008-02-12 20:33:05 +00:00
parent e038442f82
commit 35dab13859
16 changed files with 203 additions and 70 deletions

View File

@ -1321,3 +1321,17 @@ David Feb 12 2008
client/
work_fetch.C
David Feb 12 2008
- client code: my next-to-last checkin was flawed
client/
app_start.C
client_state.C,h
sandbox.C
clientgui/
BOINCClientManager.cpp
MainDocument.cpp
lib/
common_defs.h
util.C,h

View File

@ -496,23 +496,11 @@ int ACTIVE_TASK::start(bool first_time) {
cmd_line = exec_path + std::string(" ") + wup->command_line;
relative_to_absolute(slot_dir, slotdirpath);
bool success = false;
get_sandbox_account_token();
for (i=0; i<5; i++) {
if (strlen(gstate.sandbox_account_name)) {
HANDLE hToken;
std::string username = gstate.sandbox_account_name;
std::string password = r_base64_decode(gstate.sandbox_account_password);
if (!LogonUser( username.c_str(), NULL, password.c_str(),
LOGON32_LOGON_SERVICE, LOGON32_PROVIDER_DEFAULT,
&hToken)
) {
windows_error_string(error_msg, sizeof(error_msg));
msg_printf(wup->project, MSG_INTERNAL_ERROR,
"LogonUser failed: %s", error_msg
);
}
if (sandbox_account_token != NULL) {
if (CreateProcessAsUser(
hToken,
sandbox_account_token,
exec_path,
(LPSTR)cmd_line.c_str(),
NULL,

View File

@ -211,7 +211,6 @@ int CLIENT_STATE::init() {
"BOINC is running as a service and as a non-system user."
);
}
read_client_auth_file();
#endif
#ifdef __APPLE__

View File

@ -111,11 +111,7 @@ public:
char attach_project_auth[256];
bool exit_before_upload;
// exit when about to upload a file
#ifdef _WIN32
char sandbox_account_name[256];
char sandbox_account_password[256];
void read_client_auth_file();
#else
#ifndef _WIN32
gid_t boinc_project_gid;
#endif

View File

@ -38,22 +38,7 @@
bool g_use_sandbox = false;
#ifdef _WIN32
void CLIENT_STATE::read_client_auth_file() {
FILE* f;
char buf[256];
f = fopen(CLIENT_AUTH_FILENAME, "r");
if (!f) return;
while (fgets(buf, 256, f)) {
if (parse_str(buf, "<username>", sandbox_account_name, sizeof(sandbox_account_name))) continue;
if (parse_str(buf, "<password>", sandbox_account_password, sizeof(sandbox_account_name))) continue;
}
fclose(f);
}
#else
#ifndef _WIN32
#ifndef _DEBUG
static int lookup_group(char* name, gid_t& gid) {
struct group* gp = getgrnam(name);

View File

@ -239,11 +239,15 @@ bool CBOINCClientManager::StartupBOINCCore() {
argv[4] = NULL;
}
#endif
// Under wxMac-2.8.0, wxExecute starts a separate thread to wait for child's termination.
// That wxProcessTerminationThread uses a huge amount of processor time (about 11% of one
// CPU on 2GHz Intel Dual-Core Mac).
// Under wxMac-2.8.0, wxExecute starts a separate thread
// to wait for child's termination.
// That wxProcessTerminationThread uses a huge amount of processor
// time (about 11% of one CPU on 2GHz Intel Dual-Core Mac).
// m_lBOINCCoreProcessId = ::wxExecute(argv);
run_program("/Library/Application Support/BOINC Data", buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId);
run_program(
"/Library/Application Support/BOINC Data",
buf, argv[3] ? 4 : 3, argv, 0.0, m_lBOINCCoreProcessId
);
#endif
} else {
buf[0] = '\0';

View File

@ -1181,7 +1181,9 @@ int CMainDocument::WorkShowGraphics(RESULT* result)
char* argv[5];
if (previous_gfx_app) {
// If this graphics app is already running, just bring it to the front
// If this graphics app is already running,
// just bring it to the front
//
if (! GetProcessForPID(previous_gfx_app->pid, &gfx_app_psn)) {
SetFrontProcess(&gfx_app_psn);
}
@ -1190,6 +1192,7 @@ int CMainDocument::WorkShowGraphics(RESULT* result)
// For unknown reasons, the graphics application exits with
// "RegisterProcess failed (error = -50)" unless we pass its
// full path twice in the argument list to execv.
//
argv[0] = "switcher";
argv[1] = (char *)result->graphics_exec_path.c_str();
argv[2] = (char *)result->graphics_exec_path.c_str();
@ -1219,6 +1222,7 @@ int CMainDocument::WorkShowGraphics(RESULT* result)
char* argv[2];
// If graphics app is already running, don't launch a second instance
//
if (previous_gfx_app) return 0;
argv[0] = "--graphics";
argv[1] = 0;

View File

@ -1,9 +1,10 @@
alter table bossa_app
add unique(name);
add unique(name),
add unique(short_name);
alter table bossa_job
add unique(name),
add index bj_more_needed(app_id, more_needed);
add index bj_conf_needed(app_id, conf_needed);
alter table bossa_job_inst
add index bji_job(job_id),

View File

@ -2,6 +2,7 @@ create table bossa_app (
id integer not null auto_increment,
create_time integer not null,
name varchar(255) not null,
short_name varchar(255) not null,
description varchar(255) not null,
long_jobs tinyint not null,
display_script varchar(255) not null,
@ -25,7 +26,8 @@ create table bossa_job (
time_estimate integer not null,
time_limit integer not null,
transition_time double not null,
nneeded integer not null,
conf_needed double not null,
canonical_inst_id integer not null,
primary key(id)
) engine=InnoDB;
@ -35,12 +37,15 @@ create table bossa_job_inst (
job_id integer not null,
user_id integer not null,
finish_time integer not null,
validate_state integer not null,
-- 0 init, 1 valid, 2 invalid
info text,
primary key(id)
) engine=InnoDB;
create table bossa_app_user (
app_id integer not null,
create table bossa_user (
user_id integer not null,
info text
-- Info about skill.
-- May depend on app; may be scalar or something else
);

View File

@ -1,6 +1,10 @@
<?
$project_news = array(
array("Feb 12, 2008",
"Where is BOINC headed? Marcin Cieslak's vision:
<a href=http://boinc.berkeley.edu/cieslak.pdf>BOINC on JXTA</a>."
),
array("Feb 11, 2008",
"Bulgarian BOINC users:
find forums and information in your language at

View File

@ -3,7 +3,7 @@
// two results are compatible if neither found an ellipse,
// or they both did and centers are within 20 pixels
//
function compare($r1, $r2) {
function ellipse_compare($r1, $r2) {
if ($r1->have_ellipse) {
if ($r2->have_ellipse) {
$dx = ($r1->cx - $r2->cx);
@ -18,7 +18,7 @@ function compare($r1, $r2) {
// handle a completed job with the given consensus set
//
function handle_consensus($bj, $c) {
function ellipse_handle($bj, $c) {
$res = $c[0];
if ($res->have_ellipse) {
$res->cx = 0;

View File

@ -5,9 +5,11 @@ require_once("../inc/util_ops.inc");
function show_bapp($app) {
echo "<tr>
<td>Name: $app->name<br>Description: $app->description<br>Created: ".date_str($app->create_time)."</td>
<td>$app->display_script</td>
<td>$app->backend_script</td>
<td>Name: $app->name<br>
Short name: $app->short_name<br>
Description: $app->description<br>
Created: ".date_str($app->create_time)."
</td>
<td>
";
if ($app->hidden) {
@ -35,12 +37,11 @@ function add_app_form() {
start_table();
row1("Add app");
row2("Name<span class=note><br>Visible to users</span>", "<input name=app_name>");
row2("Short name<span class=note><br>Used in file and function names - no spaces or special characters</span>", "<input name=short_name>");
row2("Description<span class=note><br>Visible to users</span>", "<textarea name=description cols=60></textarea>");
row2("Display script filename", "<input name=display_script>");
row2("Backend script filename", "<input name=backend_script>");
row2("Min confidence sum for consensus", "<input name=min_conf_sum>");
row2("Min confidence fraction for consensus", "<input name=min_conf_frac>");
row2("Max instances", "<input name=max_instances>");
row2("Min confidence sum for consensus", "<input name=min_conf_sum value=2>");
row2("Min confidence fraction for consensus", "<input name=min_conf_frac value=\"0.5\">");
row2("Max job instances", "<input name=max_instances value=5>");
row2("", "<input type=submit name=submit value=\"Create app\">");
end_table();
echo "</form>";

View File

@ -12,6 +12,61 @@ function lookup_app($id) {
return null;
}
// return the confidence of the instances that agree with the given one
//
function agree_conf($instances, $inst) {
$sum = $inst->conf;
foreach ($instances as $i) {
if ($i->id == $inst->id) continue;
if (compatible($i, $inst)) {
$sum += $i->conf;
}
}
return $sum;
}
// return the total confidence
//
function total_confidence($instances) {
$sum = 0;
foreach ($instances as $i) {
if (!$i->finished_time) continue;
$sum += $i->conf;
}
}
// See if there's a canonical instance.
// If there's not, return the confidence of the largest compatible set
//
function find_canonical($instances, $total_conf, &$max_conf) {
$best = null;
$best_conf = 0;
foreach ($instances as $inst) {
$ac = agree_conf($instances, $inst);
if ($ac > $best_conf) {
$best_conf = $ac;
$best = $inst;
}
}
if (!$best) return;
$max_conf = $best_conf;
if ($best_conf < $app->min_conf_sum) return;
if ($best_conf/$total_conf < $app->min_conf_frac) return;
return $best;
}
function get_confidence(&$instances) {
foreach ($instances as $inst) {
$user = BoincUser::lookup_id($inst->user_id);
BossaUser::lookup($user);
$inst->conf = 1;
}
}
// this gets invoked when
// 1) an instance has been completed
// 2) an instance has timed out
//
function handle_job($job) {
$app = lookup_app($job->app_id);
if (!$app) {
@ -19,6 +74,32 @@ function handle_job($job) {
return;
}
$instances = BossaJobInst::enum("job_id=$job->id");
if ($job->canonical_inst_id) {
// Already have a canonical instance.
// Are there new instances to validate?
//
$canonical_inst = find_canonical($job, $instances);
foreach ($instances as $inst) {
switch ($inst->validate_state) {
case VALIDATE_STATE_INIT:
if (compatible($inst, $canonical_inst)) {
$inst->validate_state = VALIDATE_STATE_VALID;
} else {
$inst->validate_state = VALIDATE_STATE_INVALID;
}
$inst->update("validate_state=$inst->validate_state");
}
}
} else {
// No canonical instance yet.
// If we have enough total confidence, check for consensus
//
get_confidences($instances);
$total_conf = total_confidence(instances);
if ($total_conf >= $app->min_conf_sum) {
$inst = find_canonical($instances, $total_conf, $max_conf);
}
}
}
function do_pass() {
@ -32,6 +113,10 @@ function do_pass() {
function main() {
global $apps;
$apps = BossaApp::enum();
foreach ($apps as $app) {
$bs = "../lib/".$app->short_name."_backend.inc";
require_once($bs);
}
while (1) {
do_pass();
}

View File

@ -187,6 +187,7 @@ struct VERSION_INFO {
#define REG_BLANK_NAME "Blank"
#define REG_BLANK_TIME "Blank Time"
#define REG_STARTUP_NAME "BOINC"
#define CLIENT_AUTH_FILENAME "client_auth.xml"
#else
#define LOCK_FILE_NAME "lockfile"
#endif

View File

@ -279,13 +279,41 @@ void update_average(
avg_time = now;
}
#ifdef _WIN32
void get_sandbox_account_token() {
FILE* f;
char buf[256], username[256], password[256];
static bool first=true;
if (!first) return;
first = true;
f = fopen(CLIENT_AUTH_FILENAME, "r");
if (!f) return;
while (fgets(buf, 256, f)) {
if (parse_str(buf, "<username>", username, sizeof(username))) continue;
if (parse_str(buf, "<password>", password, sizeof(password))) continue;
}
fclose(f);
std::string password_str = r_base64_decode(ca.boinc_project.password);
retval = LogonUser(
username,
NULL,
password_str.c_str(),
LOGON32_LOGON_SERVICE,
LOGON32_PROVIDER_DEFAULT,
&sandbox_account_token
);
if (!retval) sandbox_account_token = NULL;
}
#endif
// chdir into the given directory, and run a program there.
// If nsecs is nonzero, make sure it's still running after that many seconds.
//
// argv is set up Unix-style, i.e. argv[0] is the program name
//
#ifdef _WIN32
#ifdef _WIN32
int run_program(
const char* dir, const char* file, int argc, char *const argv[], double nsecs, HANDLE& id
) {
@ -307,18 +335,35 @@ int run_program(
}
}
retval = CreateProcess(
file,
cmdline,
NULL,
NULL,
FALSE,
0,
NULL,
dir,
&startup_info,
&process_info
);
get_sandbox_account_token();
if (sandbox_account_token != NULL) {
retval = CreateProcessAsUser(
sandbox_account_token,
file,
cmdline,
NULL,
NULL,
FALSE,
0,
NULL,
dir,
&startup_info,
&process_info
);
} else {
retval = CreateProcess(
file,
cmdline,
NULL,
NULL,
FALSE,
0,
NULL,
dir,
&startup_info,
&process_info
);
}
if (!retval) {
return -1; // CreateProcess returns 1 if successful, false if it failed.

View File

@ -72,6 +72,7 @@ extern int boinc_calling_thread_cpu_time(double&);
extern void mysql_timestamp(double, char*);
#ifdef _WIN32
extern HANDLE sandbox_account_token = NULL;
extern int run_program(
const char* path, const char* cdir, int argc, char *const argv[], double, HANDLE&
);