2008-08-06 18:36:30 +00:00
|
|
|
// This file is part of BOINC.
|
2005-01-20 23:22:22 +00:00
|
|
|
// http://boinc.berkeley.edu
|
2008-08-06 18:36:30 +00:00
|
|
|
// Copyright (C) 2008 University of California
|
2003-06-11 23:36:50 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// 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.
|
2003-06-11 23:36:50 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// BOINC is distributed in the hope that it will be useful,
|
2005-01-20 23:22:22 +00:00
|
|
|
// 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.
|
2002-04-30 22:22:54 +00:00
|
|
|
//
|
2008-08-06 18:36:30 +00:00
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with BOINC. If not, see <http://www.gnu.org/licenses/>.
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2002-12-03 18:57:40 +00:00
|
|
|
// Handle a scheduling server RPC
|
|
|
|
|
2005-11-21 18:34:44 +00:00
|
|
|
#include "config.h"
|
2009-01-13 23:06:02 +00:00
|
|
|
#ifdef _USING_FCGI_
|
|
|
|
#include "boinc_fcgi.h"
|
|
|
|
#else
|
2004-08-03 21:51:30 +00:00
|
|
|
#include <cstdio>
|
2009-01-13 23:06:02 +00:00
|
|
|
#endif
|
|
|
|
#include <cassert>
|
2008-02-27 23:26:38 +00:00
|
|
|
#include <cstdlib>
|
2002-09-26 23:12:13 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2008-02-27 23:26:38 +00:00
|
|
|
#include <cstring>
|
2004-08-03 21:51:30 +00:00
|
|
|
#include <ctime>
|
|
|
|
#include <cmath>
|
2002-09-26 23:12:13 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/wait.h>
|
2005-05-17 05:55:24 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
2005-08-16 23:47:51 +00:00
|
|
|
#include <sys/stat.h>
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2003-04-07 19:06:00 +00:00
|
|
|
#include "boinc_db.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "backend_lib.h"
|
2003-10-21 04:06:55 +00:00
|
|
|
#include "error_numbers.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "parse.h"
|
2007-02-21 16:26:51 +00:00
|
|
|
#include "str_util.h"
|
2009-06-16 20:54:44 +00:00
|
|
|
#include "str_replace.h"
|
2003-04-03 18:35:40 +00:00
|
|
|
#include "util.h"
|
2005-05-17 21:08:48 +00:00
|
|
|
#include "filesys.h"
|
|
|
|
|
2009-08-10 04:49:02 +00:00
|
|
|
#include "credit.h"
|
|
|
|
#include "sched_main.h"
|
|
|
|
#include "sched_types.h"
|
2003-06-11 23:36:40 +00:00
|
|
|
#include "sched_util.h"
|
2002-04-30 22:22:54 +00:00
|
|
|
#include "handle_request.h"
|
2004-04-08 08:15:23 +00:00
|
|
|
#include "sched_msgs.h"
|
2005-08-04 03:50:04 +00:00
|
|
|
#include "sched_resend.h"
|
2004-04-04 01:59:47 +00:00
|
|
|
#include "sched_send.h"
|
2004-08-05 22:14:23 +00:00
|
|
|
#include "sched_config.h"
|
2005-05-17 21:08:48 +00:00
|
|
|
#include "sched_locality.h"
|
2008-02-21 00:47:50 +00:00
|
|
|
#include "sched_result.h"
|
2009-07-29 18:55:50 +00:00
|
|
|
#include "sched_customize.h"
|
2008-01-13 00:12:14 +00:00
|
|
|
#include "time_stats_log.h"
|
2003-08-09 00:11:32 +00:00
|
|
|
|
2004-07-03 21:38:22 +00:00
|
|
|
|
2008-01-18 20:29:53 +00:00
|
|
|
// find the user's most recently-created host with given various characteristics
|
|
|
|
//
|
|
|
|
static bool find_host_by_other(DB_USER& user, HOST req_host, DB_HOST& host) {
|
|
|
|
char buf[2048];
|
|
|
|
char dn[512], ip[512], os[512], pm[512];
|
|
|
|
|
2009-05-06 21:52:50 +00:00
|
|
|
#ifdef EINSTEIN_AT_HOME
|
|
|
|
// This is to prevent GRID hosts that manipulate their hostids from flooding E@H's DB with slow queries
|
|
|
|
if ((user.id == 282952) || (user.id == 243543))
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
|
2008-01-18 20:29:53 +00:00
|
|
|
// Only check if the fields are populated
|
|
|
|
if (strlen(req_host.domain_name) && strlen(req_host.last_ip_addr) && strlen(req_host.os_name) && strlen(req_host.p_model)) {
|
|
|
|
strcpy(dn, req_host.domain_name);
|
|
|
|
escape_string(dn, 512);
|
|
|
|
strcpy(ip, req_host.last_ip_addr);
|
|
|
|
escape_string(ip, 512);
|
|
|
|
strcpy(os, req_host.os_name);
|
|
|
|
escape_string(os, 512);
|
|
|
|
strcpy(pm, req_host.p_model);
|
|
|
|
escape_string(pm, 512);
|
|
|
|
|
|
|
|
sprintf(buf,
|
2009-05-06 21:52:50 +00:00
|
|
|
"where userid=%d and id>%d and domain_name='%s' and last_ip_addr = '%s' and os_name = '%s' and p_model = '%s'"
|
|
|
|
" and m_nbytes = %lf order by id desc", user.id, req_host.id, dn, ip, os, pm, req_host.m_nbytes
|
2008-01-18 20:29:53 +00:00
|
|
|
);
|
|
|
|
if (!host.enumerate(buf)) {
|
|
|
|
host.end_enumerate();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-01-14 16:32:34 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
static void send_error_message(const char* msg, int delay) {
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(msg, "low");
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(delay);
|
|
|
|
g_reply->nucleus_only = true;
|
2007-07-06 16:37:00 +00:00
|
|
|
}
|
|
|
|
|
2005-06-03 21:39:38 +00:00
|
|
|
// Try to lock a file with name based on host ID,
|
|
|
|
// to prevent 2 schedulers from running at same time for same host.
|
|
|
|
// Return:
|
|
|
|
// 0 if successful
|
|
|
|
// In this case store file descriptor in reply struct so we can unlock later
|
|
|
|
// In other cases store -1 in reply struct
|
|
|
|
// PID (>0) if another process has lock
|
|
|
|
// -1 if error (e.g. can't create file)
|
2005-05-17 05:55:24 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
int lock_sched() {
|
2005-05-24 04:32:36 +00:00
|
|
|
char filename[256];
|
2005-05-17 05:55:24 +00:00
|
|
|
char pid_string[16];
|
|
|
|
int fd, pid, count;
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->lockfile_fd=-1;
|
2005-05-17 05:55:24 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
sprintf(filename, "%s/CGI_%07d", config.sched_lockfile_dir, g_reply->host.id);
|
2005-05-17 05:55:24 +00:00
|
|
|
|
2005-05-24 04:32:36 +00:00
|
|
|
fd = open(filename, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
|
|
|
|
if (fd < 0) return -1;
|
2005-05-17 05:55:24 +00:00
|
|
|
|
2005-05-24 04:32:36 +00:00
|
|
|
// if we can't get an advisory write lock on the file,
|
|
|
|
// return the PID of the process that DOES hold the lock.
|
2005-06-03 21:39:38 +00:00
|
|
|
// (or -1 if failure)
|
2005-05-24 04:32:36 +00:00
|
|
|
//
|
2005-06-03 21:39:38 +00:00
|
|
|
pid = mylockf(fd);
|
|
|
|
if (pid) {
|
|
|
|
close(fd);
|
|
|
|
return pid;
|
|
|
|
}
|
2005-05-17 05:55:24 +00:00
|
|
|
|
|
|
|
// write PID into the CGI_<HOSTID> file and flush to disk
|
2005-05-24 04:32:36 +00:00
|
|
|
//
|
2005-06-03 21:39:38 +00:00
|
|
|
count = sprintf(pid_string, "%d\n", getpid());
|
2008-02-05 21:26:43 +00:00
|
|
|
write(fd, pid_string, count);
|
2005-05-17 05:55:24 +00:00
|
|
|
fsync(fd);
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->lockfile_fd = fd;
|
2005-05-17 05:55:24 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-06-03 21:39:38 +00:00
|
|
|
// unlock and delete per-host lockfile
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
void unlock_sched() {
|
2005-06-03 21:39:38 +00:00
|
|
|
char filename[256];
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_reply->lockfile_fd < 0) return;
|
|
|
|
sprintf(filename, "%s/CGI_%07d", config.sched_lockfile_dir, g_reply->host.id);
|
2005-06-03 21:39:38 +00:00
|
|
|
unlink(filename);
|
2008-12-19 18:14:02 +00:00
|
|
|
close(g_reply->lockfile_fd);
|
2005-06-03 21:39:38 +00:00
|
|
|
}
|
|
|
|
|
2008-03-07 21:13:01 +00:00
|
|
|
|
2006-03-12 06:20:28 +00:00
|
|
|
// find the user's most recently-created host with given host CPID
|
2006-03-11 00:17:46 +00:00
|
|
|
//
|
2006-03-12 06:33:38 +00:00
|
|
|
static bool find_host_by_cpid(DB_USER& user, char* host_cpid, DB_HOST& host) {
|
2006-03-11 00:17:46 +00:00
|
|
|
char buf[256], buf2[256];
|
|
|
|
sprintf(buf, "%s%s", host_cpid, user.email_addr);
|
|
|
|
md5_block((const unsigned char*)buf, strlen(buf), buf2);
|
|
|
|
|
|
|
|
sprintf(buf,
|
|
|
|
"where userid=%d and host_cpid='%s' order by id desc", user.id, buf2
|
|
|
|
);
|
|
|
|
if (!host.enumerate(buf)) {
|
|
|
|
host.end_enumerate();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-06-06 18:45:40 +00:00
|
|
|
// Called when there's evidence that the host has detached.
|
|
|
|
// Mark in-progress results for the given host
|
2006-07-06 17:30:03 +00:00
|
|
|
// as server state OVER, outcome CLIENT_DETACHED.
|
2006-06-06 18:45:40 +00:00
|
|
|
// This serves two purposes:
|
|
|
|
// 1) make sure we don't resend these results to the host
|
|
|
|
// (they may be the reason the user detached)
|
|
|
|
// 2) trigger the generation of new results for these WUs
|
2006-03-12 06:20:28 +00:00
|
|
|
//
|
2006-06-06 18:45:40 +00:00
|
|
|
static void mark_results_over(DB_HOST& host) {
|
2006-03-12 06:20:28 +00:00
|
|
|
char buf[256], buf2[256];
|
|
|
|
DB_RESULT result;
|
|
|
|
sprintf(buf, "where hostid=%d and server_state=%d",
|
|
|
|
host.id,
|
|
|
|
RESULT_SERVER_STATE_IN_PROGRESS
|
|
|
|
);
|
|
|
|
while (!result.enumerate(buf)) {
|
|
|
|
sprintf(buf2,
|
- server code: at some point I made a global var "SCHED_CONFIG config",
mostly so that the parse function could assume
that everything was initially zero.
However, various back-end functions pass around SCHED_CONFIG&
as an argument (also named "config").
This creates a shadow, which is always bad.
Worse is the possibility that some projects have back-end programs
that have a SCHED_CONFIG variable that's automatic,
and therefore isn't zero initially,
and therefore isn't parsing correctly.
To fix this, I changed the 2 vectors in SCHED_CONFIG into pointers,
and have the parse routine zero the structure.
I was tempted to remove the SCHED_CONFIG& args to back-end functions,
but this would have broken some projects' code.
I did, however, change the name from config to config_loc
to avoid shadowing.
Also fixed various other compiler warnings.
svn path=/trunk/boinc/; revision=15541
2008-07-02 17:24:53 +00:00
|
|
|
"server_state=%d, outcome=%d, received_time = %ld",
|
2006-03-12 06:20:28 +00:00
|
|
|
RESULT_SERVER_STATE_OVER,
|
2008-03-07 21:13:01 +00:00
|
|
|
RESULT_OUTCOME_CLIENT_DETACHED,
|
|
|
|
time(0)
|
2006-03-12 06:20:28 +00:00
|
|
|
);
|
|
|
|
result.update_field(buf2);
|
|
|
|
|
|
|
|
// and trigger WU transition
|
|
|
|
//
|
|
|
|
DB_WORKUNIT wu;
|
|
|
|
wu.id = result.workunitid;
|
2006-05-02 22:33:00 +00:00
|
|
|
sprintf(buf2, "transition_time=%d", (int)time(0));
|
2006-03-12 06:20:28 +00:00
|
|
|
wu.update_field(buf2);
|
2006-05-24 08:31:49 +00:00
|
|
|
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2006-06-03 14:59:22 +00:00
|
|
|
"[HOST#%d] [RESULT#%d] [WU#%d] changed CPID: marking in-progress result %s as client error!\n",
|
2006-05-24 08:31:49 +00:00
|
|
|
host.id, result.id, result.workunitid, result.name
|
|
|
|
);
|
2006-03-12 06:20:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-17 21:08:48 +00:00
|
|
|
// Based on the info in the request message,
|
|
|
|
// look up the host and its user, and make sure the authenticator matches.
|
|
|
|
// Some special cases:
|
|
|
|
// 1) If no host ID is supplied, or if RPC seqno mismatch,
|
|
|
|
// create a new host record
|
2008-12-19 18:14:02 +00:00
|
|
|
// 2) If the host record specified by g_request->hostid is a "zombie"
|
2005-05-17 21:08:48 +00:00
|
|
|
// (i.e. it was merged with another host via the web site)
|
|
|
|
// then follow links to find the proper host
|
2002-04-30 22:22:54 +00:00
|
|
|
//
|
2004-09-27 19:44:40 +00:00
|
|
|
// POSTCONDITION:
|
2006-03-11 00:17:46 +00:00
|
|
|
// If this function returns zero, then:
|
2004-09-27 19:44:40 +00:00
|
|
|
// - reply.host contains a valid host record (possibly new)
|
|
|
|
// - reply.user contains a valid user record
|
2005-02-13 19:04:20 +00:00
|
|
|
// - if user belongs to a team, reply.team contains team record
|
2004-09-27 19:44:40 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
int authenticate_user() {
|
2002-04-30 22:22:54 +00:00
|
|
|
int retval;
|
2008-02-05 21:26:43 +00:00
|
|
|
char buf[256];
|
2003-06-04 17:21:26 +00:00
|
|
|
DB_HOST host;
|
|
|
|
DB_USER user;
|
|
|
|
DB_TEAM team;
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->hostid) {
|
|
|
|
retval = host.lookup_id(g_request->hostid);
|
2005-04-12 21:54:40 +00:00
|
|
|
while (!retval && host.userid==0) {
|
2005-04-07 20:46:25 +00:00
|
|
|
// if host record is zombie, follow link to new host
|
|
|
|
//
|
|
|
|
retval = host.lookup_id(host.rpc_seqno);
|
|
|
|
if (!retval) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->hostid = host.id;
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2005-04-07 20:46:25 +00:00
|
|
|
"[HOST#%d] forwarding to new host ID %d\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->hostid, host.id
|
2005-04-07 20:46:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
if (retval) {
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message("Can't find host record", "low");
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2003-06-14 17:46:08 +00:00
|
|
|
"[HOST#%d?] can't find host\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->hostid
|
2003-06-14 17:46:08 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->hostid = 0;
|
2004-01-08 00:40:53 +00:00
|
|
|
goto lookup_user_and_make_new_host;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2005-04-07 20:46:25 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host = host;
|
2003-06-04 17:21:26 +00:00
|
|
|
|
2007-12-07 23:23:25 +00:00
|
|
|
// look up user based on the ID in host record,
|
|
|
|
// and see if the authenticator matches (regular or weak)
|
|
|
|
//
|
2009-08-18 20:44:12 +00:00
|
|
|
g_request->using_weak_auth = false;
|
2007-12-07 23:23:25 +00:00
|
|
|
sprintf(buf, "where id=%d", host.userid);
|
2004-12-20 21:37:20 +00:00
|
|
|
retval = user.lookup(buf);
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!retval && !strcmp(user.authenticator, g_request->authenticator)) {
|
2007-12-07 23:23:25 +00:00
|
|
|
// req auth matches user auth - go on
|
|
|
|
} else {
|
|
|
|
if (!retval) {
|
|
|
|
// user for host.userid exists - check weak auth
|
2008-01-14 19:59:16 +00:00
|
|
|
//
|
2008-01-14 16:32:34 +00:00
|
|
|
get_weak_auth(user, buf);
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!strcmp(buf, g_request->authenticator)) {
|
2009-08-18 20:44:12 +00:00
|
|
|
g_request->using_weak_auth = true;
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
2008-02-05 21:26:43 +00:00
|
|
|
"[HOST#%d] accepting weak authenticator\n",
|
|
|
|
host.id
|
2007-12-07 23:23:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2009-08-18 20:44:12 +00:00
|
|
|
if (!g_request->using_weak_auth) {
|
2007-12-07 23:23:25 +00:00
|
|
|
// weak auth failed - look up user based on authenticator
|
2008-01-14 19:59:16 +00:00
|
|
|
//
|
2007-12-07 23:23:25 +00:00
|
|
|
strlcpy(
|
2008-12-19 18:14:02 +00:00
|
|
|
user.authenticator, g_request->authenticator, sizeof(user.authenticator)
|
2007-12-07 23:23:25 +00:00
|
|
|
);
|
|
|
|
sprintf(buf, "where authenticator='%s'", user.authenticator);
|
|
|
|
retval = user.lookup(buf);
|
|
|
|
if (retval) {
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"Invalid or missing account key. To fix, detach and reattach to this project.",
|
|
|
|
"high"
|
2007-12-07 23:23:25 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_MISSING_KEY);
|
|
|
|
g_reply->nucleus_only = true;
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2007-12-07 23:23:25 +00:00
|
|
|
"[HOST#%d] [USER#%d] Bad authenticator '%s'\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
host.id, user.id, g_request->authenticator
|
2007-12-07 23:23:25 +00:00
|
|
|
);
|
|
|
|
return ERR_AUTHENTICATOR;
|
|
|
|
}
|
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2005-02-13 19:04:20 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->user = user;
|
2004-12-20 21:37:20 +00:00
|
|
|
|
|
|
|
if (host.userid != user.id) {
|
|
|
|
// If the request's host ID isn't consistent with the authenticator,
|
|
|
|
// create a new host record.
|
|
|
|
//
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2004-12-20 21:37:20 +00:00
|
|
|
"[HOST#%d] [USER#%d] inconsistent host ID; creating new host\n",
|
|
|
|
host.id, user.id
|
|
|
|
);
|
|
|
|
goto make_new_host;
|
|
|
|
}
|
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
|
|
|
|
// If the seqno from the host is less than what we expect,
|
|
|
|
// the user must have copied the state file to a different host.
|
|
|
|
// Make a new host record.
|
2004-05-03 02:18:35 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!batch && g_request->rpc_seqno < g_reply->host.rpc_seqno) {
|
|
|
|
g_request->hostid = 0;
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2004-01-08 00:09:26 +00:00
|
|
|
"[HOST#%d] [USER#%d] RPC seqno %d less than expected %d; creating new host\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.id, user.id, g_request->rpc_seqno, g_reply->host.rpc_seqno
|
2004-01-08 00:09:26 +00:00
|
|
|
);
|
2004-01-08 00:40:53 +00:00
|
|
|
goto make_new_host;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
} else {
|
2006-03-11 00:17:46 +00:00
|
|
|
// Here no hostid was given, or the ID was bad.
|
|
|
|
// Look up the user, then create a new host record
|
2003-06-04 17:21:26 +00:00
|
|
|
//
|
2004-01-08 00:40:53 +00:00
|
|
|
lookup_user_and_make_new_host:
|
2008-01-14 16:32:34 +00:00
|
|
|
// if authenticator contains _, it's a weak auth
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strchr(g_request->authenticator, '_')) {
|
|
|
|
int userid = atoi(g_request->authenticator);
|
2008-01-14 16:32:34 +00:00
|
|
|
retval = user.lookup_id(userid);
|
2008-01-14 19:59:16 +00:00
|
|
|
if (!retval) {
|
|
|
|
get_weak_auth(user, buf);
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strcmp(buf, g_request->authenticator)) {
|
2008-01-14 19:59:16 +00:00
|
|
|
retval = ERR_AUTHENTICATOR;
|
|
|
|
}
|
|
|
|
}
|
2008-01-14 16:32:34 +00:00
|
|
|
} else {
|
|
|
|
strlcpy(
|
2008-12-19 18:14:02 +00:00
|
|
|
user.authenticator, g_request->authenticator,
|
2008-01-14 16:32:34 +00:00
|
|
|
sizeof(user.authenticator)
|
|
|
|
);
|
|
|
|
sprintf(buf, "where authenticator='%s'", user.authenticator);
|
|
|
|
retval = user.lookup(buf);
|
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
if (retval) {
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"Invalid or missing account key. To fix, detach and reattach to this project .",
|
|
|
|
"low"
|
2003-03-02 19:24:09 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_MISSING_KEY);
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2008-01-14 19:59:16 +00:00
|
|
|
"[HOST#<none>] Bad authenticator '%s': %d\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->authenticator, retval
|
2003-06-14 17:46:08 +00:00
|
|
|
);
|
2003-10-21 04:06:55 +00:00
|
|
|
return ERR_AUTHENTICATOR;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->user = user;
|
2006-03-11 00:17:46 +00:00
|
|
|
|
|
|
|
// If host CPID is present,
|
|
|
|
// scan backwards through this user's hosts,
|
|
|
|
// looking for one with the same host CPID.
|
|
|
|
// If we find one, it means the user detached and reattached.
|
2006-03-12 06:20:28 +00:00
|
|
|
// Use the existing host record,
|
2006-07-06 17:30:03 +00:00
|
|
|
// and mark in-progress results as over.
|
2006-03-11 00:17:46 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strlen(g_request->host.host_cpid)) {
|
|
|
|
if (find_host_by_cpid(user, g_request->host.host_cpid, host)) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2006-06-03 14:59:22 +00:00
|
|
|
"[HOST#%d] [USER#%d] User has another host with same CPID.\n",
|
2006-05-24 09:22:34 +00:00
|
|
|
host.id, host.userid
|
2006-05-24 08:31:49 +00:00
|
|
|
);
|
2009-07-28 19:19:14 +00:00
|
|
|
if (!config.multiple_clients_per_host
|
|
|
|
&& (g_request->other_results.size() == 0)
|
|
|
|
) {
|
2008-11-07 04:13:08 +00:00
|
|
|
mark_results_over(host);
|
|
|
|
}
|
2006-03-11 00:17:46 +00:00
|
|
|
goto got_host;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-08 00:40:53 +00:00
|
|
|
make_new_host:
|
2007-11-22 01:52:27 +00:00
|
|
|
// One final attempt to locate an existing host record:
|
|
|
|
// scan backwards through this user's hosts,
|
|
|
|
// looking for one with the same host name,
|
|
|
|
// IP address, processor and amount of RAM.
|
|
|
|
// If found, use the existing host record,
|
|
|
|
// and mark in-progress results as over.
|
|
|
|
//
|
2008-09-04 08:33:21 +00:00
|
|
|
// NOTE: if the project allows multiple clients per host
|
|
|
|
// (e.g. those that run on grids), skip this.
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!config.multiple_clients_per_host && find_host_by_other(user, g_request->host, host)) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2008-01-18 20:29:53 +00:00
|
|
|
"[HOST#%d] [USER#%d] Found similar existing host for this user - assigned.\n",
|
|
|
|
host.id, host.userid
|
|
|
|
);
|
2008-11-26 21:49:36 +00:00
|
|
|
mark_results_over(host);
|
2007-11-22 01:52:27 +00:00
|
|
|
goto got_host;
|
|
|
|
}
|
2006-03-11 00:17:46 +00:00
|
|
|
// either of the above cases,
|
|
|
|
// or host ID didn't match user ID,
|
|
|
|
// or RPC seqno was too low.
|
|
|
|
//
|
|
|
|
// Create a new host.
|
2008-12-19 18:14:02 +00:00
|
|
|
// g_reply->user is filled in and valid at this point
|
2002-08-28 21:50:51 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
host = g_request->host;
|
2003-06-04 17:21:26 +00:00
|
|
|
host.id = 0;
|
|
|
|
host.create_time = time(0);
|
2008-12-19 18:14:02 +00:00
|
|
|
host.userid = g_reply->user.id;
|
2003-06-04 17:21:26 +00:00
|
|
|
host.rpc_seqno = 0;
|
2006-01-13 01:07:05 +00:00
|
|
|
host.expavg_time = time(0);
|
2007-04-24 23:21:42 +00:00
|
|
|
host.error_rate = 0.1;
|
2008-12-19 18:14:02 +00:00
|
|
|
strcpy(host.venue, g_reply->user.venue);
|
2004-01-19 01:12:53 +00:00
|
|
|
host.fix_nans();
|
2003-06-04 17:21:26 +00:00
|
|
|
retval = host.insert();
|
2002-04-30 22:22:54 +00:00
|
|
|
if (retval) {
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"Couldn't create host record in database", "low"
|
2009-02-26 03:03:35 +00:00
|
|
|
);
|
2003-09-05 21:26:21 +00:00
|
|
|
boinc_db.print_error("host.insert()");
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL, "host.insert() failed\n");
|
2003-10-21 04:06:55 +00:00
|
|
|
return retval;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2003-09-05 21:26:21 +00:00
|
|
|
host.id = boinc_db.insert_id();
|
2003-06-04 17:21:26 +00:00
|
|
|
|
2006-03-11 00:17:46 +00:00
|
|
|
got_host:
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host = host;
|
|
|
|
g_reply->hostid = g_reply->host.id;
|
2007-04-05 17:02:01 +00:00
|
|
|
// this tells client to updates its host ID
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->rpc_seqno = 0;
|
2006-03-03 20:25:31 +00:00
|
|
|
// this value eventually gets written to host DB record;
|
|
|
|
// for new hosts it must be zero.
|
|
|
|
// This kludge forces this.
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2004-05-03 02:18:35 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
// have user record in g_reply->user at this point
|
2004-05-03 02:18:35 +00:00
|
|
|
//
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_reply->user.teamid) {
|
|
|
|
retval = team.lookup_id(g_reply->user.teamid);
|
|
|
|
if (!retval) g_reply->team = team;
|
2003-02-24 21:31:36 +00:00
|
|
|
}
|
2004-05-03 02:18:35 +00:00
|
|
|
|
|
|
|
// compute email hash
|
|
|
|
//
|
|
|
|
md5_block(
|
2008-12-19 18:14:02 +00:00
|
|
|
(unsigned char*)g_reply->user.email_addr,
|
|
|
|
strlen(g_reply->user.email_addr),
|
|
|
|
g_reply->email_hash
|
2004-05-03 02:18:35 +00:00
|
|
|
);
|
|
|
|
|
2006-03-11 00:17:46 +00:00
|
|
|
// if new user CPID, update user record
|
2004-05-03 02:18:35 +00:00
|
|
|
//
|
2009-08-18 20:44:12 +00:00
|
|
|
if (!g_request->using_weak_auth && strlen(g_request->cross_project_id)) {
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strcmp(g_request->cross_project_id, g_reply->user.cross_project_id)) {
|
|
|
|
user.id = g_reply->user.id;
|
|
|
|
escape_string(g_request->cross_project_id, sizeof(g_request->cross_project_id));
|
|
|
|
sprintf(buf, "cross_project_id='%s'", g_request->cross_project_id);
|
|
|
|
unescape_string(g_request->cross_project_id, sizeof(g_request->cross_project_id));
|
2005-04-29 06:55:44 +00:00
|
|
|
user.update_field(buf);
|
2004-05-03 02:18:35 +00:00
|
|
|
}
|
|
|
|
}
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-05-27 18:13:00 +00:00
|
|
|
// modify host struct based on request.
|
2002-04-30 22:22:54 +00:00
|
|
|
// Copy all fields that are determined by the client.
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
static int modify_host_struct(HOST& host) {
|
|
|
|
host.timezone = g_request->host.timezone;
|
|
|
|
strncpy(host.domain_name, g_request->host.domain_name, sizeof(host.domain_name));
|
2009-09-02 15:18:15 +00:00
|
|
|
char buf[256], buf2[256];
|
|
|
|
sprintf(buf, "[BOINC|%d.%d.%d]",
|
|
|
|
g_request->core_client_major_version,
|
|
|
|
g_request->core_client_minor_version,
|
|
|
|
g_request->core_client_release
|
|
|
|
);
|
|
|
|
g_request->coprocs.summary_string(buf2, sizeof(buf2));
|
|
|
|
strlcpy(host.serialnum, buf, sizeof(host.serialnum));
|
|
|
|
strlcat(host.serialnum, buf2, sizeof(host.serialnum));
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strcmp(host.last_ip_addr, g_request->host.last_ip_addr)) {
|
|
|
|
strncpy(host.last_ip_addr, g_request->host.last_ip_addr, sizeof(host.last_ip_addr));
|
2002-04-30 22:22:54 +00:00
|
|
|
} else {
|
|
|
|
host.nsame_ip_addr++;
|
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
host.on_frac = g_request->host.on_frac;
|
|
|
|
host.connected_frac = g_request->host.connected_frac;
|
|
|
|
host.active_frac = g_request->host.active_frac;
|
|
|
|
host.duration_correction_factor = g_request->host.duration_correction_factor;
|
|
|
|
host.p_ncpus = g_request->host.p_ncpus;
|
|
|
|
strncpy(host.p_vendor, g_request->host.p_vendor, sizeof(host.p_vendor));
|
2003-03-02 19:24:09 +00:00
|
|
|
// unlikely this will change
|
2008-12-19 18:14:02 +00:00
|
|
|
strncpy(host.p_model, g_request->host.p_model, sizeof(host.p_model));
|
|
|
|
host.p_fpops = g_request->host.p_fpops;
|
|
|
|
host.p_iops = g_request->host.p_iops;
|
|
|
|
host.p_membw = g_request->host.p_membw;
|
|
|
|
strncpy(host.os_name, g_request->host.os_name, sizeof(host.os_name));
|
|
|
|
strncpy(host.os_version, g_request->host.os_version, sizeof(host.os_version));
|
|
|
|
host.m_nbytes = g_request->host.m_nbytes;
|
|
|
|
host.m_cache = g_request->host.m_cache;
|
|
|
|
host.m_swap = g_request->host.m_swap;
|
|
|
|
host.d_total = g_request->host.d_total;
|
|
|
|
host.d_free = g_request->host.d_free;
|
|
|
|
host.d_boinc_used_total = g_request->host.d_boinc_used_total;
|
|
|
|
host.d_boinc_used_project = g_request->host.d_boinc_used_project;
|
|
|
|
host.n_bwup = g_request->host.n_bwup;
|
|
|
|
host.n_bwdown = g_request->host.n_bwdown;
|
|
|
|
if (strlen(g_request->host.host_cpid)) {
|
|
|
|
strcpy(host.host_cpid, g_request->host.host_cpid);
|
2005-05-03 21:50:51 +00:00
|
|
|
}
|
2004-01-19 01:12:53 +00:00
|
|
|
host.fix_nans();
|
2002-09-26 05:57:10 +00:00
|
|
|
|
2005-02-16 23:17:43 +00:00
|
|
|
compute_credit_rating(host);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->host.claimed_credit_per_cpu_sec = host.claimed_credit_per_cpu_sec;
|
2004-05-27 18:13:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2002-09-26 05:57:10 +00:00
|
|
|
|
2006-03-03 20:25:31 +00:00
|
|
|
// update the DB record to the values in "xhost"
|
|
|
|
// "initial_host" stores the current DB values;
|
|
|
|
// update only those fields that have changed
|
|
|
|
//
|
2005-05-03 21:50:51 +00:00
|
|
|
static int update_host_record(HOST& initial_host, HOST& xhost, USER& user) {
|
2004-05-27 18:13:00 +00:00
|
|
|
DB_HOST host;
|
|
|
|
int retval;
|
2005-01-20 18:50:49 +00:00
|
|
|
char buf[1024];
|
2004-05-27 18:13:00 +00:00
|
|
|
|
|
|
|
host = xhost;
|
2005-11-10 06:06:11 +00:00
|
|
|
|
|
|
|
// hash the CPID reported by the host with the user's email address.
|
|
|
|
// This prevents one user from spoofing another one's host.
|
|
|
|
//
|
2005-01-20 18:50:49 +00:00
|
|
|
if (strlen(host.host_cpid)) {
|
|
|
|
sprintf(buf, "%s%s", host.host_cpid, user.email_addr);
|
|
|
|
md5_block((const unsigned char*)buf, strlen(buf), host.host_cpid);
|
|
|
|
}
|
2005-01-21 07:54:15 +00:00
|
|
|
|
|
|
|
char* p = getenv("REMOTE_ADDR");
|
|
|
|
if (p) {
|
|
|
|
strlcpy(host.external_ip_addr, p, sizeof(host.external_ip_addr));
|
|
|
|
}
|
2005-05-03 21:50:51 +00:00
|
|
|
retval = host.update_diff(initial_host);
|
2002-04-30 22:22:54 +00:00
|
|
|
if (retval) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL, "host.update() failed: %d\n", retval);
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-03-05 22:12:21 +00:00
|
|
|
inline const char* reason_str(int n) {
|
|
|
|
switch (n) {
|
|
|
|
case ABORT_REASON_NOT_FOUND: return "result not in request";
|
|
|
|
case ABORT_REASON_WU_CANCELLED: return "WU cancelled";
|
|
|
|
case ABORT_REASON_ASSIMILATED: return "WU assimilated";
|
|
|
|
case ABORT_REASON_TIMED_OUT: return "result timed out";
|
|
|
|
}
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2007-11-30 23:02:55 +00:00
|
|
|
// Figure out which of the results the host currently has
|
2007-05-04 17:59:50 +00:00
|
|
|
// should be aborted outright, or aborted if not started yet
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
int send_result_abort() {
|
2007-05-04 17:59:50 +00:00
|
|
|
int aborts_sent = 0;
|
|
|
|
int retval = 0;
|
2007-04-05 17:02:01 +00:00
|
|
|
DB_IN_PROGRESS_RESULT result;
|
|
|
|
std::string result_names;
|
2007-04-16 22:22:15 +00:00
|
|
|
unsigned int i;
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->other_results.size() == 0) {
|
2007-05-04 17:59:50 +00:00
|
|
|
return 0;
|
2007-04-05 17:02:01 +00:00
|
|
|
}
|
|
|
|
|
2008-02-26 17:24:29 +00:00
|
|
|
// build list of result names
|
2007-04-30 22:20:33 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
for (i=0; i<g_request->other_results.size(); i++) {
|
|
|
|
OTHER_RESULT& orp=g_request->other_results[i];
|
2007-04-05 17:02:01 +00:00
|
|
|
orp.abort = true;
|
2009-12-24 20:40:27 +00:00
|
|
|
// if the host has a result not in the DB, abort it
|
2007-04-05 17:02:01 +00:00
|
|
|
orp.abort_if_not_started = false;
|
2008-02-26 17:24:29 +00:00
|
|
|
orp.reason = ABORT_REASON_NOT_FOUND;
|
2007-05-04 17:59:50 +00:00
|
|
|
if (i > 0) result_names.append(", ");
|
2007-04-05 17:02:01 +00:00
|
|
|
result_names.append("'");
|
2009-12-21 00:58:58 +00:00
|
|
|
char buf[1024];
|
|
|
|
strcpy(buf, orp.name);
|
|
|
|
escape_string(buf, 1024);
|
|
|
|
result_names.append(buf);
|
2007-04-05 17:02:01 +00:00
|
|
|
result_names.append("'");
|
|
|
|
}
|
2007-04-30 22:20:33 +00:00
|
|
|
|
2008-02-26 17:24:29 +00:00
|
|
|
// look up selected fields from the results and their WUs,
|
|
|
|
// and decide if they should be aborted
|
2007-04-30 22:20:33 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
while (!(retval = result.enumerate(g_reply->host.id, result_names.c_str()))) {
|
|
|
|
for (i=0; i<g_request->other_results.size(); i++) {
|
|
|
|
OTHER_RESULT& orp = g_request->other_results[i];
|
2009-06-01 22:15:14 +00:00
|
|
|
if (!strcmp(orp.name, result.result_name)) {
|
2008-02-26 17:24:29 +00:00
|
|
|
if (result.error_mask&WU_ERROR_CANCELLED ) {
|
|
|
|
// if the WU has been canceled, abort the result
|
|
|
|
//
|
|
|
|
orp.abort = true;
|
|
|
|
orp.abort_if_not_started = false;
|
|
|
|
orp.reason = ABORT_REASON_WU_CANCELLED;
|
2009-12-24 20:40:27 +00:00
|
|
|
} else if (result.assimilate_state == ASSIMILATE_DONE) {
|
2008-02-26 17:24:29 +00:00
|
|
|
// if the WU has been assimilated, abort if not started
|
|
|
|
//
|
2007-05-04 17:59:50 +00:00
|
|
|
orp.abort = false;
|
|
|
|
orp.abort_if_not_started = true;
|
2008-02-26 17:24:29 +00:00
|
|
|
orp.reason = ABORT_REASON_ASSIMILATED;
|
2007-07-20 18:47:52 +00:00
|
|
|
} else if (result.server_state == RESULT_SERVER_STATE_OVER
|
|
|
|
&& result.outcome == RESULT_OUTCOME_NO_REPLY
|
|
|
|
) {
|
2008-02-26 17:24:29 +00:00
|
|
|
// if timed out, abort if not started
|
|
|
|
//
|
|
|
|
orp.abort = false;
|
2007-05-04 17:59:50 +00:00
|
|
|
orp.abort_if_not_started = true;
|
2008-02-26 17:24:29 +00:00
|
|
|
orp.reason = ABORT_REASON_TIMED_OUT;
|
2007-05-04 17:59:50 +00:00
|
|
|
} else {
|
|
|
|
// all is good with the result - let it process
|
2008-02-26 17:24:29 +00:00
|
|
|
orp.abort = false;
|
|
|
|
orp.abort_if_not_started = false;
|
2007-05-04 17:59:50 +00:00
|
|
|
}
|
|
|
|
break;
|
2007-04-05 17:02:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-26 17:24:29 +00:00
|
|
|
|
2007-05-04 17:59:50 +00:00
|
|
|
// If enumeration returned an error, don't send any aborts
|
|
|
|
//
|
|
|
|
if (retval && (retval != ERR_DB_NOT_FOUND)) {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2007-04-05 17:02:01 +00:00
|
|
|
// loop through the results and send the appropriate message (if any)
|
2007-04-30 22:20:33 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
for (i=0; i<g_request->other_results.size(); i++) {
|
|
|
|
OTHER_RESULT& orp = g_request->other_results[i];
|
2007-05-04 17:59:50 +00:00
|
|
|
if (orp.abort) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->result_aborts.push_back(orp.name);
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2009-03-05 22:12:21 +00:00
|
|
|
"[HOST#%d]: Send result_abort for result %s; reason: %s\n",
|
2009-06-01 22:15:14 +00:00
|
|
|
g_reply->host.id, orp.name, reason_str(orp.reason)
|
2009-12-24 20:40:27 +00:00
|
|
|
);
|
|
|
|
// send user message
|
2007-04-05 17:02:01 +00:00
|
|
|
char buf[256];
|
2009-06-01 22:15:14 +00:00
|
|
|
sprintf(buf, "Result %s is no longer usable", orp.name);
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(buf, "high");
|
2007-04-30 22:20:33 +00:00
|
|
|
} else if (orp.abort_if_not_started) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->result_abort_if_not_starteds.push_back(orp.name);
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2008-02-26 17:24:29 +00:00
|
|
|
"[HOST#%d]: Send result_abort_if_unstarted for result %s; reason %d\n",
|
2009-06-01 22:15:14 +00:00
|
|
|
g_reply->host.id, orp.name, orp.reason
|
2009-12-24 20:40:27 +00:00
|
|
|
);
|
2007-05-04 17:59:50 +00:00
|
|
|
}
|
2007-04-05 17:02:01 +00:00
|
|
|
}
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2007-05-04 17:59:50 +00:00
|
|
|
return aborts_sent;
|
2007-04-05 17:02:01 +00:00
|
|
|
}
|
|
|
|
|
2006-10-06 18:52:50 +00:00
|
|
|
// 1) Decide which global prefs to use for sched decisions: either
|
|
|
|
// - <working_global_prefs> from request msg
|
|
|
|
// - <global_prefs> from request message
|
|
|
|
// - prefs from user DB record
|
2008-12-19 18:14:02 +00:00
|
|
|
// and parse them into g_request->global_prefs.
|
2006-10-06 18:52:50 +00:00
|
|
|
// 2) update prefs in user record if needed
|
|
|
|
// 2) send global prefs in reply msg if needed
|
2002-04-30 22:22:54 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
int handle_global_prefs() {
|
2008-03-31 16:19:45 +00:00
|
|
|
char buf[BLOB_SIZE];
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->send_global_prefs = false;
|
|
|
|
bool have_working_prefs = (strlen(g_request->working_global_prefs_xml)>0);
|
|
|
|
bool have_master_prefs = (strlen(g_request->global_prefs_xml)>0);
|
|
|
|
bool have_db_prefs = (strlen(g_reply->user.global_prefs)>0);
|
2006-10-06 18:52:50 +00:00
|
|
|
bool same_account = !strcmp(
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs_source_email_hash, g_reply->email_hash
|
2006-10-06 18:52:50 +00:00
|
|
|
);
|
2008-02-03 21:46:30 +00:00
|
|
|
double master_mod_time=0, db_mod_time=0;
|
2006-10-06 18:52:50 +00:00
|
|
|
if (have_master_prefs) {
|
2008-12-19 18:14:02 +00:00
|
|
|
parse_double(g_request->global_prefs_xml, "<mod_time>", master_mod_time);
|
2008-02-03 21:46:30 +00:00
|
|
|
if (master_mod_time > dtime()) master_mod_time = dtime();
|
2006-10-06 18:52:50 +00:00
|
|
|
}
|
|
|
|
if (have_db_prefs) {
|
2008-12-19 18:14:02 +00:00
|
|
|
parse_double(g_reply->user.global_prefs, "<mod_time>", db_mod_time);
|
2008-02-03 21:46:30 +00:00
|
|
|
if (db_mod_time > dtime()) db_mod_time = dtime();
|
2006-10-06 18:52:50 +00:00
|
|
|
}
|
2004-03-23 03:59:32 +00:00
|
|
|
|
2008-08-05 21:43:52 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"have_master:%d have_working: %d have_db: %d\n",
|
|
|
|
have_master_prefs, have_working_prefs, have_db_prefs
|
|
|
|
);
|
|
|
|
}
|
2006-11-14 17:30:59 +00:00
|
|
|
|
|
|
|
// decide which prefs to use for sched decisions,
|
2008-12-19 18:14:02 +00:00
|
|
|
// and parse them into g_request->global_prefs
|
2006-10-06 18:52:50 +00:00
|
|
|
//
|
|
|
|
if (have_working_prefs) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs.parse(g_request->working_global_prefs_xml, "");
|
2008-04-23 23:34:26 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "using working prefs\n");
|
|
|
|
}
|
2006-10-06 18:52:50 +00:00
|
|
|
} else {
|
|
|
|
if (have_master_prefs) {
|
|
|
|
if (have_db_prefs && db_mod_time > master_mod_time) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs.parse(g_reply->user.global_prefs, g_reply->host.venue);
|
2008-04-23 23:34:26 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "using db prefs - more recent\n");
|
|
|
|
}
|
2004-05-03 02:18:35 +00:00
|
|
|
} else {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs.parse(g_request->global_prefs_xml, g_reply->host.venue);
|
2008-04-23 23:34:26 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "using master prefs\n");
|
|
|
|
}
|
2002-09-29 00:32:11 +00:00
|
|
|
}
|
2004-05-03 02:18:35 +00:00
|
|
|
} else {
|
2006-10-06 18:52:50 +00:00
|
|
|
if (have_db_prefs) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs.parse(g_reply->user.global_prefs, g_reply->host.venue);
|
2008-04-23 23:34:26 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "using db prefs\n");
|
|
|
|
}
|
2006-10-06 18:52:50 +00:00
|
|
|
} else {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->global_prefs.defaults();
|
2008-04-23 23:34:26 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "using default prefs\n");
|
|
|
|
}
|
2006-10-06 18:52:50 +00:00
|
|
|
}
|
2004-05-03 02:18:35 +00:00
|
|
|
}
|
2006-10-06 18:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// decide whether to update DB
|
|
|
|
//
|
2009-08-18 20:44:12 +00:00
|
|
|
if (!g_request->using_weak_auth && have_master_prefs) {
|
2006-10-06 18:52:50 +00:00
|
|
|
bool update_user_record = false;
|
|
|
|
if (have_db_prefs) {
|
2006-10-12 18:47:21 +00:00
|
|
|
if (master_mod_time > db_mod_time && same_account) {
|
2006-10-06 18:52:50 +00:00
|
|
|
update_user_record = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (same_account) update_user_record = true;
|
|
|
|
}
|
|
|
|
if (update_user_record) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_DEBUG, "updating db prefs\n");
|
2008-12-19 18:14:02 +00:00
|
|
|
strcpy(g_reply->user.global_prefs, g_request->global_prefs_xml);
|
2005-04-29 06:55:44 +00:00
|
|
|
DB_USER user;
|
2008-12-19 18:14:02 +00:00
|
|
|
user.id = g_reply->user.id;
|
|
|
|
escape_string(g_request->global_prefs_xml, sizeof(g_request->global_prefs_xml));
|
|
|
|
sprintf(buf, "global_prefs='%s'", g_request->global_prefs_xml);
|
|
|
|
unescape_string(g_request->global_prefs_xml, sizeof(g_request->global_prefs_xml));
|
2005-05-01 04:35:22 +00:00
|
|
|
int retval = user.update_field(buf);
|
|
|
|
if (retval) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2005-05-01 04:35:22 +00:00
|
|
|
"user.update_field() failed: %d\n", retval
|
|
|
|
);
|
|
|
|
}
|
2002-09-29 00:32:11 +00:00
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2006-10-06 18:52:50 +00:00
|
|
|
|
|
|
|
// decide whether to send DB prefs in reply msg
|
|
|
|
//
|
2008-08-05 21:43:52 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"have db %d; dbmod %f; global mod %f\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
have_db_prefs, db_mod_time, g_request->global_prefs.mod_time
|
2008-08-05 21:43:52 +00:00
|
|
|
);
|
|
|
|
}
|
2006-11-14 17:30:59 +00:00
|
|
|
if (have_db_prefs && db_mod_time > master_mod_time) {
|
2008-08-05 21:43:52 +00:00
|
|
|
if (config.debug_prefs) {
|
|
|
|
log_messages.printf(MSG_DEBUG, "sending db prefs in reply\n");
|
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->send_global_prefs = true;
|
2006-10-06 18:52:50 +00:00
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-09-22 23:27:14 +00:00
|
|
|
// if the client has an old code sign public key,
|
2002-07-07 20:39:24 +00:00
|
|
|
// send it the new one, with a signature based on the old one.
|
|
|
|
// If they don't have a code sign key, send them one
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
bool send_code_sign_key(char* code_sign_key) {
|
2002-07-07 20:39:24 +00:00
|
|
|
char* oldkey, *signature;
|
|
|
|
int i, retval;
|
|
|
|
char path[256];
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
if (strlen(g_request->code_sign_key)) {
|
|
|
|
if (strcmp(g_request->code_sign_key, code_sign_key)) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL, "received old code sign key\n");
|
2003-04-03 18:35:40 +00:00
|
|
|
|
2002-07-07 20:39:24 +00:00
|
|
|
// look for a signature file
|
|
|
|
//
|
|
|
|
for (i=0; ; i++) {
|
2002-10-04 20:35:56 +00:00
|
|
|
sprintf(path, "%s/old_key_%d", config.key_dir, i);
|
2002-07-07 20:39:24 +00:00
|
|
|
retval = read_file_malloc(path, oldkey);
|
|
|
|
if (retval) {
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"You may have an outdated code signing key. "
|
|
|
|
"This may prevent you from accepting new executables. "
|
|
|
|
"If the problem persists, detach/attach the project. ",
|
|
|
|
"high"
|
2002-07-07 20:39:24 +00:00
|
|
|
);
|
2008-05-21 22:33:21 +00:00
|
|
|
return false;
|
2002-07-07 20:39:24 +00:00
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!strcmp(oldkey, g_request->code_sign_key)) {
|
2002-10-04 20:35:56 +00:00
|
|
|
sprintf(path, "%s/signature_%d", config.key_dir, i);
|
2002-07-07 20:39:24 +00:00
|
|
|
retval = read_file_malloc(path, signature);
|
|
|
|
if (retval) {
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"You may have an outdated code signing key. "
|
|
|
|
"This may prevent you from accepting new executables. "
|
|
|
|
"If the problem persists, detach/attach the project. ",
|
|
|
|
"high"
|
2002-07-07 20:39:24 +00:00
|
|
|
);
|
|
|
|
} else {
|
2008-12-19 18:14:02 +00:00
|
|
|
safe_strcpy(g_reply->code_sign_key, code_sign_key);
|
|
|
|
safe_strcpy(g_reply->code_sign_key_signature, signature);
|
2003-04-03 18:35:40 +00:00
|
|
|
free(signature);
|
2002-07-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(oldkey);
|
2008-05-21 22:33:21 +00:00
|
|
|
return false;
|
2002-07-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2008-12-19 18:14:02 +00:00
|
|
|
safe_strcpy(g_reply->code_sign_key, code_sign_key);
|
2002-07-07 20:39:24 +00:00
|
|
|
}
|
2008-05-21 22:33:21 +00:00
|
|
|
return true;
|
2002-07-07 20:39:24 +00:00
|
|
|
}
|
|
|
|
|
2010-01-13 17:28:59 +00:00
|
|
|
// If <min_core_client_version_announced> is set,
|
|
|
|
// and the core client version is less than this version,
|
|
|
|
// send a warning to users to upgrade before deadline
|
|
|
|
// <min_core_client_upgrade_deadline>
|
2005-02-09 04:38:19 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
void warn_user_if_core_client_upgrade_scheduled() {
|
|
|
|
if (g_request->core_client_version < config.min_core_client_version_announced) {
|
2005-02-09 04:38:19 +00:00
|
|
|
|
|
|
|
// time remaining in hours, before upgrade required
|
|
|
|
int remaining = config.min_core_client_upgrade_deadline-time(0);
|
|
|
|
remaining /= 3600;
|
2007-01-30 18:19:30 +00:00
|
|
|
|
2005-02-09 04:38:19 +00:00
|
|
|
if (0 < remaining) {
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2005-02-09 04:38:19 +00:00
|
|
|
char msg[512];
|
|
|
|
int days = remaining / 24;
|
|
|
|
int hours = remaining % 24;
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2005-02-09 04:38:19 +00:00
|
|
|
sprintf(msg,
|
2010-01-13 17:28:59 +00:00
|
|
|
"In %d days and %d hours, this project will require a minimum "
|
|
|
|
"BOINC core client version of %d.%d.%d. You are currently using "
|
2005-11-19 19:49:46 +00:00
|
|
|
"version %d.%d.%d; please upgrade before this time.",
|
2005-02-09 04:38:19 +00:00
|
|
|
days, hours,
|
2010-01-13 17:28:59 +00:00
|
|
|
config.min_core_client_version_announced / 10000,
|
|
|
|
(config.min_core_client_version_announced / 100)%100,
|
2005-02-09 04:38:19 +00:00
|
|
|
config.min_core_client_version_announced % 100,
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->core_client_major_version,
|
|
|
|
g_request->core_client_minor_version,
|
|
|
|
g_request->core_client_release
|
2005-02-09 04:38:19 +00:00
|
|
|
);
|
2005-02-10 06:21:58 +00:00
|
|
|
// make this low priority until three days are left. Then
|
|
|
|
// bump to high.
|
|
|
|
//
|
|
|
|
if (days<3) {
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(msg, "high");
|
2005-02-10 06:21:58 +00:00
|
|
|
} else {
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(msg, "low");
|
2005-02-10 06:21:58 +00:00
|
|
|
}
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
2005-11-19 19:49:46 +00:00
|
|
|
"Sending warning: upgrade client %d.%d.%d within %d days %d hours\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->core_client_major_version,
|
|
|
|
g_request->core_client_minor_version,
|
|
|
|
g_request->core_client_release,
|
2005-02-10 06:21:58 +00:00
|
|
|
days, hours
|
|
|
|
);
|
2005-02-09 04:38:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
bool unacceptable_os() {
|
2008-02-25 18:05:04 +00:00
|
|
|
unsigned int i;
|
|
|
|
char buf[1024];
|
2007-06-12 21:40:32 +00:00
|
|
|
|
- server code: at some point I made a global var "SCHED_CONFIG config",
mostly so that the parse function could assume
that everything was initially zero.
However, various back-end functions pass around SCHED_CONFIG&
as an argument (also named "config").
This creates a shadow, which is always bad.
Worse is the possibility that some projects have back-end programs
that have a SCHED_CONFIG variable that's automatic,
and therefore isn't zero initially,
and therefore isn't parsing correctly.
To fix this, I changed the 2 vectors in SCHED_CONFIG into pointers,
and have the parse routine zero the structure.
I was tempted to remove the SCHED_CONFIG& args to back-end functions,
but this would have broken some projects' code.
I did, however, change the name from config to config_loc
to avoid shadowing.
Also fixed various other compiler warnings.
svn path=/trunk/boinc/; revision=15541
2008-07-02 17:24:53 +00:00
|
|
|
for (i=0; i<config.ban_os->size(); i++) {
|
|
|
|
regex_t& re = (*config.ban_os)[i];
|
2008-12-19 18:14:02 +00:00
|
|
|
strcpy(buf, g_request->host.os_name);
|
2008-02-25 18:05:04 +00:00
|
|
|
strcat(buf, "\t");
|
2008-12-19 18:14:02 +00:00
|
|
|
strcat(buf, g_request->host.os_version);
|
2008-02-25 18:05:04 +00:00
|
|
|
if (!regexec(&re, buf, 0, NULL, 0)) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2007-06-12 21:40:32 +00:00
|
|
|
"Unacceptable OS %s %s\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->host.os_name, g_request->host.os_version
|
2007-06-12 21:40:32 +00:00
|
|
|
);
|
2008-02-25 18:05:04 +00:00
|
|
|
sprintf(buf, "This project doesn't support OS type %s %s",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->host.os_name, g_request->host.os_version
|
2007-06-12 21:40:32 +00:00
|
|
|
);
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(buf, "low");
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_UNACCEPTABLE_OS);
|
2007-06-12 21:40:32 +00:00
|
|
|
return true;
|
|
|
|
}
|
2005-03-19 18:24:24 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2007-06-12 21:40:32 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
bool unacceptable_cpu() {
|
2008-02-25 18:05:04 +00:00
|
|
|
unsigned int i;
|
|
|
|
char buf[1024];
|
|
|
|
|
- server code: at some point I made a global var "SCHED_CONFIG config",
mostly so that the parse function could assume
that everything was initially zero.
However, various back-end functions pass around SCHED_CONFIG&
as an argument (also named "config").
This creates a shadow, which is always bad.
Worse is the possibility that some projects have back-end programs
that have a SCHED_CONFIG variable that's automatic,
and therefore isn't zero initially,
and therefore isn't parsing correctly.
To fix this, I changed the 2 vectors in SCHED_CONFIG into pointers,
and have the parse routine zero the structure.
I was tempted to remove the SCHED_CONFIG& args to back-end functions,
but this would have broken some projects' code.
I did, however, change the name from config to config_loc
to avoid shadowing.
Also fixed various other compiler warnings.
svn path=/trunk/boinc/; revision=15541
2008-07-02 17:24:53 +00:00
|
|
|
for (i=0; i<config.ban_cpu->size(); i++) {
|
|
|
|
regex_t& re = (*config.ban_cpu)[i];
|
2008-12-19 18:14:02 +00:00
|
|
|
strcpy(buf, g_request->host.p_vendor);
|
2008-02-25 18:05:04 +00:00
|
|
|
strcat(buf, "\t");
|
2008-12-19 18:14:02 +00:00
|
|
|
strcat(buf, g_request->host.p_model);
|
2008-02-25 18:05:04 +00:00
|
|
|
if (!regexec(&re, buf, 0, NULL, 0)) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2007-06-12 21:40:32 +00:00
|
|
|
"Unacceptable CPU %s %s\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->host.p_vendor, g_request->host.p_model
|
2007-06-12 21:40:32 +00:00
|
|
|
);
|
2008-02-25 18:05:04 +00:00
|
|
|
sprintf(buf, "This project doesn't support CPU type %s %s",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->host.p_vendor, g_request->host.p_model
|
2008-02-25 18:05:04 +00:00
|
|
|
);
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(buf, "low");
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_UNACCEPTABLE_OS);
|
2007-06-12 21:40:32 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2005-03-19 18:24:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
2005-02-09 04:38:19 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
bool wrong_core_client_version() {
|
2005-01-31 22:19:03 +00:00
|
|
|
char msg[256];
|
2010-01-13 17:28:59 +00:00
|
|
|
if (!config.min_core_client_version) {
|
|
|
|
return false;
|
2005-01-19 05:34:18 +00:00
|
|
|
}
|
2010-01-13 17:28:59 +00:00
|
|
|
if (g_request->core_client_version >= config.min_core_client_version) {
|
|
|
|
return false;
|
2002-12-02 04:29:40 +00:00
|
|
|
}
|
2010-01-13 17:28:59 +00:00
|
|
|
sprintf(msg,
|
|
|
|
"Need version %d.%d.%d or higher of the BOINC client. You have %d.%d.%d.",
|
|
|
|
config.min_core_client_version / 10000,
|
|
|
|
(config.min_core_client_version / 100)%100,
|
|
|
|
config.min_core_client_version % 100,
|
|
|
|
g_request->core_client_major_version,
|
|
|
|
g_request->core_client_minor_version,
|
|
|
|
g_request->core_client_release
|
|
|
|
);
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"[HOST#%d] Wrong client version from user: wanted %d, got %d\n",
|
|
|
|
g_request->hostid,
|
|
|
|
config.min_core_client_version, g_request->core_client_minor_version
|
|
|
|
);
|
|
|
|
g_reply->insert_message(msg, "low");
|
|
|
|
g_reply->set_delay(DELAY_BAD_CLIENT_VERSION);
|
|
|
|
return true;
|
2002-12-02 04:29:40 +00:00
|
|
|
}
|
2002-10-22 21:44:16 +00:00
|
|
|
|
2003-09-21 22:33:43 +00:00
|
|
|
inline static const char* get_remote_addr() {
|
2003-07-29 01:05:13 +00:00
|
|
|
const char * r = getenv("REMOTE_ADDR");
|
|
|
|
return r ? r : "?.?.?.?";
|
2003-07-25 20:48:29 +00:00
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
void handle_msgs_from_host() {
|
2004-01-08 00:27:59 +00:00
|
|
|
unsigned int i;
|
2004-06-22 22:56:50 +00:00
|
|
|
DB_MSG_FROM_HOST mfh;
|
2004-01-08 00:27:59 +00:00
|
|
|
int retval;
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
for (i=0; i<g_request->msgs_from_host.size(); i++) {
|
|
|
|
g_reply->send_msg_ack = true;
|
|
|
|
MSG_FROM_HOST_DESC& md = g_request->msgs_from_host[i];
|
2004-06-22 22:56:50 +00:00
|
|
|
mfh.clear();
|
|
|
|
mfh.create_time = time(0);
|
2004-07-06 04:10:51 +00:00
|
|
|
safe_strcpy(mfh.variety, md.variety);
|
2008-12-19 18:14:02 +00:00
|
|
|
mfh.hostid = g_reply->host.id;
|
2004-06-22 22:56:50 +00:00
|
|
|
mfh.handled = false;
|
2004-06-24 21:00:13 +00:00
|
|
|
safe_strcpy(mfh.xml, md.msg_text.c_str());
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2006-01-24 21:38:03 +00:00
|
|
|
"got msg from host; variety %s \n",
|
|
|
|
mfh.variety
|
2004-07-06 04:10:51 +00:00
|
|
|
);
|
2004-06-22 22:56:50 +00:00
|
|
|
retval = mfh.insert();
|
2004-03-17 01:26:44 +00:00
|
|
|
if (retval) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2004-06-24 21:00:13 +00:00
|
|
|
"[HOST#%d] message insert failed: %d\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.id, retval
|
2004-03-17 01:26:44 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->send_msg_ack = false;
|
2005-06-17 23:12:00 +00:00
|
|
|
|
|
|
|
// may as well return; if one insert failed, others will too
|
|
|
|
//
|
|
|
|
return;
|
2004-03-17 01:26:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
void handle_msgs_to_host() {
|
2004-06-22 22:56:50 +00:00
|
|
|
DB_MSG_TO_HOST mth;
|
2004-03-17 01:26:44 +00:00
|
|
|
char buf[256];
|
2008-12-19 18:14:02 +00:00
|
|
|
sprintf(buf, "where hostid = %d and handled = %d", g_reply->host.id, 0);
|
2004-06-22 22:56:50 +00:00
|
|
|
while (!mth.enumerate(buf)) {
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->msgs_to_host.push_back(mth);
|
2004-06-22 22:56:50 +00:00
|
|
|
mth.handled = true;
|
|
|
|
mth.update();
|
2004-01-08 00:27:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
static void log_request() {
|
2008-05-02 17:48:29 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2009-01-10 00:43:33 +00:00
|
|
|
"Request: [USER#%d] [HOST#%d] [IP %s] client %d.%d.%d\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->user.id, g_reply->host.id, get_remote_addr(),
|
|
|
|
g_request->core_client_major_version,
|
|
|
|
g_request->core_client_minor_version,
|
2009-01-10 00:43:33 +00:00
|
|
|
g_request->core_client_release
|
2008-05-02 17:48:29 +00:00
|
|
|
);
|
|
|
|
if (config.debug_request_details) {
|
|
|
|
log_messages.printf(MSG_DEBUG,
|
|
|
|
"Request details: auth %s, RPC seqno %d, platform %s\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_request->authenticator,
|
|
|
|
g_request->rpc_seqno,
|
|
|
|
g_request->platform.name
|
2008-05-02 17:48:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
log_messages.set_indent_level(2);
|
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
bool bad_install_type() {
|
2008-10-01 19:48:52 +00:00
|
|
|
if (config.no_vista_sandbox) {
|
2008-12-19 18:14:02 +00:00
|
|
|
if (!strcmp(g_request->host.os_name, "Microsoft Windows Vista")) {
|
|
|
|
if (g_request->sandbox == 1) {
|
2009-01-12 23:47:52 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
2008-10-01 19:48:52 +00:00
|
|
|
"Vista secure install - not sending work\n"
|
|
|
|
);
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"Unable to send work to Vista with BOINC installed in protected mode",
|
|
|
|
"high"
|
2008-10-01 19:48:52 +00:00
|
|
|
);
|
2009-02-26 03:03:35 +00:00
|
|
|
g_reply->insert_message(
|
2009-08-21 19:14:15 +00:00
|
|
|
"Please reinstall BOINC and uncheck 'Protected application execution'",
|
|
|
|
"high"
|
2008-10-01 19:48:52 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-12-22 03:39:50 +00:00
|
|
|
static inline bool requesting_work() {
|
2009-01-12 23:47:52 +00:00
|
|
|
if (g_request->work_req_seconds > 0) return true;
|
|
|
|
if (g_request->cpu_req_secs > 0) return true;
|
2009-01-26 05:00:49 +00:00
|
|
|
if (g_request->coproc_cuda && g_request->coproc_cuda->req_secs) return true;
|
2009-08-17 17:07:38 +00:00
|
|
|
if (g_request->coproc_ati && g_request->coproc_ati->req_secs) return true;
|
2009-01-12 23:47:52 +00:00
|
|
|
return false;
|
2008-12-22 03:39:50 +00:00
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
void process_request(char* code_sign_key) {
|
2002-04-30 22:22:54 +00:00
|
|
|
PLATFORM* platform;
|
2002-06-21 18:31:32 +00:00
|
|
|
int retval;
|
2003-12-23 19:21:52 +00:00
|
|
|
double last_rpc_time;
|
2004-05-30 10:21:19 +00:00
|
|
|
struct tm *rpc_time_tm;
|
2004-05-30 10:16:57 +00:00
|
|
|
int last_rpc_dayofyear;
|
|
|
|
int current_rpc_dayofyear;
|
2004-07-04 18:55:31 +00:00
|
|
|
bool ok_to_send_work = true;
|
2004-07-24 00:09:28 +00:00
|
|
|
bool have_no_work;
|
2005-01-31 22:19:03 +00:00
|
|
|
char buf[256];
|
2005-05-03 21:50:51 +00:00
|
|
|
HOST initial_host;
|
2007-04-19 22:45:57 +00:00
|
|
|
unsigned int i;
|
2008-06-30 23:05:16 +00:00
|
|
|
time_t t;
|
2004-05-29 21:49:03 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
memset(&g_reply->wreq, 0, sizeof(g_reply->wreq));
|
2007-09-28 18:27:02 +00:00
|
|
|
|
2002-12-02 04:29:40 +00:00
|
|
|
// if different major version of BOINC, just send a message
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (wrong_core_client_version()
|
|
|
|
|| unacceptable_os()
|
|
|
|
|| unacceptable_cpu()
|
2007-06-12 21:40:32 +00:00
|
|
|
) {
|
2004-07-04 18:55:31 +00:00
|
|
|
ok_to_send_work = false;
|
|
|
|
|
|
|
|
// if no results, return without accessing DB
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->results.size() == 0) {
|
2004-07-04 18:55:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-02-09 04:38:19 +00:00
|
|
|
} else {
|
2008-12-19 18:14:02 +00:00
|
|
|
warn_user_if_core_client_upgrade_scheduled();
|
2004-07-04 18:55:31 +00:00
|
|
|
}
|
2005-03-19 18:24:24 +00:00
|
|
|
|
2008-12-22 03:39:50 +00:00
|
|
|
if (requesting_work()) {
|
2009-03-03 00:12:55 +00:00
|
|
|
if (config.locality_scheduling || config.locality_scheduler_fraction || config.enable_assignment) {
|
2008-12-22 03:39:50 +00:00
|
|
|
have_no_work = false;
|
|
|
|
} else {
|
|
|
|
lock_sema();
|
|
|
|
have_no_work = ssp->no_work(g_pid);
|
|
|
|
if (have_no_work) {
|
|
|
|
g_wreq->no_jobs_available = true;
|
2009-01-13 00:56:12 +00:00
|
|
|
log_messages.printf(MSG_NORMAL, "No jobs in shmem\n");
|
2008-12-22 03:39:50 +00:00
|
|
|
}
|
|
|
|
unlock_sema();
|
2008-12-22 00:19:20 +00:00
|
|
|
}
|
2005-03-13 20:10:03 +00:00
|
|
|
}
|
|
|
|
|
2009-11-12 21:30:33 +00:00
|
|
|
// If:
|
|
|
|
// - there's no work,
|
|
|
|
// - a config flag is set,
|
|
|
|
// - client isn't returning results,
|
|
|
|
// - this isn't an initial RPC,
|
|
|
|
// - client is requesting work
|
|
|
|
// then return without accessing the DB.
|
|
|
|
// This is an efficiency hack for when servers are overloaded
|
2004-07-04 18:55:31 +00:00
|
|
|
//
|
2005-03-13 20:10:03 +00:00
|
|
|
if (
|
2009-11-12 21:30:33 +00:00
|
|
|
have_no_work
|
|
|
|
&& config.nowork_skip
|
2008-12-22 03:39:50 +00:00
|
|
|
&& requesting_work()
|
2008-12-19 18:14:02 +00:00
|
|
|
&& (g_request->results.size() == 0)
|
|
|
|
&& (g_request->hostid != 0)
|
2004-07-04 18:55:31 +00:00
|
|
|
) {
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message("No work available", "low");
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_NO_WORK_SKIP);
|
2004-08-12 13:36:05 +00:00
|
|
|
if (!config.msg_to_host) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_NORMAL, "No work - skipping DB access\n");
|
2004-08-05 22:14:23 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-05-03 19:30:01 +00:00
|
|
|
}
|
2003-06-11 23:36:45 +00:00
|
|
|
|
2009-11-12 21:30:33 +00:00
|
|
|
// FROM HERE ON DON'T RETURN; "goto leave" instead
|
|
|
|
// (because ssp->no_work() may have tagged an entry in the work array
|
|
|
|
// with our process ID)
|
2004-07-24 00:09:28 +00:00
|
|
|
|
2004-04-30 18:26:20 +00:00
|
|
|
retval = open_database();
|
|
|
|
if (retval) {
|
2008-12-19 18:14:02 +00:00
|
|
|
send_error_message("Server can't open database", 3600);
|
|
|
|
g_reply->project_is_down = true;
|
2004-07-24 00:09:28 +00:00
|
|
|
goto leave;
|
2004-04-30 18:26:20 +00:00
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
retval = authenticate_user();
|
2004-07-24 00:09:28 +00:00
|
|
|
if (retval) goto leave;
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_reply->user.id == 0) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL, "No user ID!\n");
|
2004-01-10 01:08:50 +00:00
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
initial_host = g_reply->host;
|
|
|
|
g_reply->host.rpc_seqno = g_request->rpc_seqno;
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->nucleus_only = false;
|
2008-05-16 00:14:48 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
log_request();
|
2004-06-02 00:02:01 +00:00
|
|
|
|
2007-07-06 16:37:00 +00:00
|
|
|
// is host blacklisted?
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_reply->host.max_results_day == -1) {
|
|
|
|
send_error_message("Not accepting requests from this host", 86400);
|
2007-07-06 16:37:00 +00:00
|
|
|
goto leave;
|
|
|
|
}
|
|
|
|
|
2005-06-03 21:39:38 +00:00
|
|
|
if (strlen(config.sched_lockfile_dir)) {
|
2008-12-19 18:14:02 +00:00
|
|
|
int pid_with_lock = lock_sched();
|
2005-06-03 21:39:38 +00:00
|
|
|
if (pid_with_lock > 0) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2005-06-03 21:39:38 +00:00
|
|
|
"Another scheduler instance [PID=%d] is running for this host\n",
|
|
|
|
pid_with_lock
|
|
|
|
);
|
|
|
|
} else if (pid_with_lock) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
2008-12-19 18:14:02 +00:00
|
|
|
"Error acquiring lock for [HOST#%d]\n", g_reply->host.id
|
2005-06-03 21:39:38 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
if (pid_with_lock) {
|
2007-07-06 16:37:00 +00:00
|
|
|
send_error_message(
|
2008-12-19 18:14:02 +00:00
|
|
|
"Another scheduler instance is running for this host", 60
|
2005-06-03 21:39:38 +00:00
|
|
|
);
|
|
|
|
goto leave;
|
|
|
|
}
|
2005-05-17 05:55:24 +00:00
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
last_rpc_time = g_reply->host.rpc_time;
|
|
|
|
t = g_reply->host.rpc_time;
|
2008-06-30 23:05:16 +00:00
|
|
|
rpc_time_tm = localtime(&t);
|
2004-05-30 10:16:57 +00:00
|
|
|
last_rpc_dayofyear = rpc_time_tm->tm_yday;
|
2004-05-29 21:21:35 +00:00
|
|
|
|
2008-06-30 23:05:16 +00:00
|
|
|
t = time(0);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.rpc_time = t;
|
2008-06-30 23:05:16 +00:00
|
|
|
rpc_time_tm = localtime(&t);
|
2004-05-30 10:16:57 +00:00
|
|
|
current_rpc_dayofyear = rpc_time_tm->tm_yday;
|
2004-05-29 21:49:03 +00:00
|
|
|
|
2005-03-19 18:24:24 +00:00
|
|
|
if (config.daily_result_quota) {
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_reply->host.max_results_day == 0 || g_reply->host.max_results_day > config.daily_result_quota) {
|
|
|
|
g_reply->host.max_results_day = config.daily_result_quota;
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
2005-09-26 23:28:48 +00:00
|
|
|
"[HOST#%d] Initializing max_results_day to %d\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.id, config.daily_result_quota
|
2005-09-26 23:28:48 +00:00
|
|
|
);
|
2005-03-19 18:24:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-30 10:16:57 +00:00
|
|
|
if (last_rpc_dayofyear != current_rpc_dayofyear) {
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
2008-12-19 18:14:02 +00:00
|
|
|
"[HOST#%d] Resetting nresults_today\n", g_reply->host.id
|
2005-09-26 23:28:48 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.nresults_today = 0;
|
2004-05-27 18:13:00 +00:00
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
retval = modify_host_struct(g_reply->host);
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2008-01-13 00:12:14 +00:00
|
|
|
// write time stats to disk if present
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->have_time_stats_log) {
|
|
|
|
write_time_stats_log();
|
2008-01-13 00:12:14 +00:00
|
|
|
}
|
|
|
|
|
2007-04-30 21:19:24 +00:00
|
|
|
// look up the client's platform(s) in the DB
|
2002-04-30 22:22:54 +00:00
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
platform = ssp->lookup_platform(g_request->platform.name);
|
|
|
|
if (platform) g_request->platforms.list.push_back(platform);
|
|
|
|
for (i=0; i<g_request->alt_platforms.size(); i++) {
|
|
|
|
platform = ssp->lookup_platform(g_request->alt_platforms[i].name);
|
|
|
|
if (platform) g_request->platforms.list.push_back(platform);
|
2007-04-19 22:45:57 +00:00
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->platforms.list.size() == 0) {
|
|
|
|
sprintf(buf, "platform '%s' not found", g_request->platform.name);
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(buf, "low");
|
2008-02-21 21:00:58 +00:00
|
|
|
log_messages.printf(MSG_CRITICAL,
|
|
|
|
"[HOST#%d] platform '%s' not found\n",
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->host.id, g_request->platform.name
|
2003-06-14 17:46:08 +00:00
|
|
|
);
|
2008-12-19 18:14:02 +00:00
|
|
|
g_reply->set_delay(DELAY_PLATFORM_UNSUPPORTED);
|
2004-07-24 00:09:28 +00:00
|
|
|
goto leave;
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2007-01-30 18:19:30 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
handle_global_prefs();
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
handle_results();
|
2002-04-30 22:22:54 +00:00
|
|
|
|
2008-10-01 19:48:52 +00:00
|
|
|
// Do this before resending lost jobs
|
|
|
|
//
|
2008-12-19 18:14:02 +00:00
|
|
|
if (bad_install_type()) {
|
2008-10-01 19:48:52 +00:00
|
|
|
ok_to_send_work = false;
|
|
|
|
}
|
2009-03-05 23:08:53 +00:00
|
|
|
send_work_setup();
|
2008-10-01 19:48:52 +00:00
|
|
|
|
2009-06-01 22:15:14 +00:00
|
|
|
g_wreq->njobs_on_host = g_request->other_results.size();
|
|
|
|
for (i=0; i<g_request->other_results.size(); i++) {
|
|
|
|
OTHER_RESULT& r = g_request->other_results[i];
|
|
|
|
if (r.have_plan_class) {
|
|
|
|
if (app_plan_uses_gpu(r.plan_class)) {
|
|
|
|
g_wreq->njobs_on_host_gpu++;
|
|
|
|
} else {
|
|
|
|
g_wreq->njobs_on_host_cpu++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-19 18:14:02 +00:00
|
|
|
if (g_request->have_other_results_list) {
|
2008-10-01 19:48:52 +00:00
|
|
|
if (config.resend_lost_results && ok_to_send_work) {
|
2008-12-19 18:14:02 +00:00
|
|
|
if (resend_lost_work()) {
|
2007-11-30 23:02:55 +00:00
|
|
|
ok_to_send_work = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (config.send_result_abort) {
|
2008-12-19 18:14:02 +00:00
|
|
|
send_result_abort();
|
2005-07-28 09:29:12 +00:00
|
|
|
}
|
2007-04-05 17:02:01 +00:00
|
|
|
}
|
2009-12-24 20:40:27 +00:00
|
|
|
|
2008-12-22 03:39:50 +00:00
|
|
|
if (requesting_work()) {
|
|
|
|
if (!send_code_sign_key(code_sign_key)) {
|
|
|
|
ok_to_send_work = false;
|
|
|
|
}
|
2008-05-21 22:33:21 +00:00
|
|
|
|
2008-12-22 03:39:50 +00:00
|
|
|
// if last RPC was within config.min_sendwork_interval, don't send work
|
|
|
|
//
|
|
|
|
if (!have_no_work && ok_to_send_work) {
|
|
|
|
if (config.min_sendwork_interval) {
|
|
|
|
double diff = dtime() - last_rpc_time;
|
|
|
|
if (diff < config.min_sendwork_interval) {
|
|
|
|
ok_to_send_work = false;
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"Not sending work - last request too recent: %f\n", diff
|
|
|
|
);
|
|
|
|
sprintf(buf,
|
|
|
|
"Not sending work - last request too recent: %d sec", (int)diff
|
|
|
|
);
|
2009-08-21 19:14:15 +00:00
|
|
|
g_reply->insert_message(buf, "low");
|
2005-06-01 22:41:41 +00:00
|
|
|
|
2008-12-22 03:39:50 +00:00
|
|
|
// the 1.01 is in case client's clock
|
|
|
|
// is slightly faster than ours
|
|
|
|
//
|
|
|
|
g_reply->set_delay(1.01*config.min_sendwork_interval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ok_to_send_work) {
|
|
|
|
send_work();
|
2004-05-13 04:48:19 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-22 03:39:50 +00:00
|
|
|
if (g_wreq->no_jobs_available) {
|
2010-01-18 04:52:58 +00:00
|
|
|
g_reply->insert_message("Project has no jobs available", "low");
|
2003-12-31 23:09:21 +00:00
|
|
|
}
|
2003-12-23 19:21:52 +00:00
|
|
|
}
|
2002-07-07 20:39:24 +00:00
|
|
|
|
2004-01-08 00:27:59 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
handle_msgs_from_host();
|
2004-06-24 21:00:13 +00:00
|
|
|
if (config.msg_to_host) {
|
2008-12-19 18:14:02 +00:00
|
|
|
handle_msgs_to_host();
|
2004-03-17 01:26:44 +00:00
|
|
|
}
|
2004-05-27 18:13:00 +00:00
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
update_host_record(initial_host, g_reply->host, g_reply->user);
|
2004-07-24 00:09:28 +00:00
|
|
|
|
|
|
|
leave:
|
|
|
|
if (!have_no_work) {
|
2008-02-22 22:21:00 +00:00
|
|
|
ssp->restore_work(g_pid);
|
2004-07-24 00:09:28 +00:00
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
static void log_incomplete_request() {
|
2008-05-02 17:48:29 +00:00
|
|
|
// BOINC scheduler requests use method POST.
|
|
|
|
// So method GET means that someone is trying a browser.
|
|
|
|
//
|
|
|
|
char *rm=getenv("REQUEST_METHOD");
|
|
|
|
bool used_get = false;
|
|
|
|
if (rm && !strcmp(rm, "GET")) {
|
|
|
|
used_get = true;
|
|
|
|
}
|
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"Incomplete request received %sfrom IP %s, auth %s, platform %s, version %d.%d.%d\n",
|
|
|
|
used_get?"(used GET method - probably a browser) ":"",
|
2008-12-19 18:14:02 +00:00
|
|
|
get_remote_addr(), g_request->authenticator, g_request->platform.name,
|
|
|
|
g_request->core_client_major_version, g_request->core_client_minor_version,
|
|
|
|
g_request->core_client_release
|
2008-05-02 17:48:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2008-12-19 18:14:02 +00:00
|
|
|
static void log_user_messages() {
|
|
|
|
for (unsigned int i=0; i<g_reply->messages.size(); i++) {
|
|
|
|
USER_MESSAGE um = g_reply->messages[i];
|
2008-05-02 17:48:29 +00:00
|
|
|
log_messages.printf(MSG_DEBUG,
|
- scheduler: add support for anonymous-platform coproc apps.
Old: although the request message contained all info
about the app version (flops, coproc usage etc.)
the server ignored this info,
and assumed that all anonymous platform apps where CPU.
With 6.6 client, this could produce infinite work fetch:
- client uses anon platform, has coproc app
- client has idle CPU, requests CPU work
- scheduler sends it jobs, thinking they will be done by CPU app
- client asks for more work etc.
New: scheduler parses full info on anon platform app versions:
plan class, FLOPS, coprocs.
It uses this info to make scheduling decisions;
in particular, if the request is for CUDA work,
if will only send jobs that use a CUDA app version.
The <result> records it returns contain info
(plan_class) that tells the client which app_version to use.
This will work correctly even if the client has multiple app versions
for the same app (e.g., a CPU version and a GPU version)
svn path=/trunk/boinc/; revision=17506
2009-03-05 17:30:10 +00:00
|
|
|
"[HOST#%d] MSG(%4s) %s\n",
|
|
|
|
g_reply->host.id, um.priority.c_str(), um.message.c_str()
|
2008-05-02 17:48:29 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-22 22:21:00 +00:00
|
|
|
void handle_request(FILE* fin, FILE* fout, char* code_sign_key) {
|
2002-04-30 22:22:54 +00:00
|
|
|
SCHEDULER_REQUEST sreq;
|
|
|
|
SCHEDULER_REPLY sreply;
|
2008-07-01 16:34:51 +00:00
|
|
|
char buf[1024];
|
2009-01-12 23:05:49 +00:00
|
|
|
double start_time = dtime();
|
2002-08-20 00:30:13 +00:00
|
|
|
|
2008-12-15 21:14:32 +00:00
|
|
|
g_request = &sreq;
|
|
|
|
g_reply = &sreply;
|
2008-12-16 16:29:54 +00:00
|
|
|
g_wreq = &sreply.wreq;
|
2008-12-15 21:14:32 +00:00
|
|
|
|
2002-04-30 22:22:54 +00:00
|
|
|
memset(&sreq, 0, sizeof(sreq));
|
2008-05-16 00:14:48 +00:00
|
|
|
sreply.nucleus_only = true;
|
2004-03-23 01:44:13 +00:00
|
|
|
|
2008-02-05 20:16:57 +00:00
|
|
|
log_messages.set_indent_level(1);
|
|
|
|
|
2008-07-01 16:34:51 +00:00
|
|
|
const char* p = sreq.parse(fin);
|
|
|
|
if (!p){
|
2008-12-19 18:14:02 +00:00
|
|
|
process_request(code_sign_key);
|
2004-03-20 07:57:34 +00:00
|
|
|
} else {
|
2008-07-01 16:34:51 +00:00
|
|
|
sprintf(buf, "Error in request message: %s", p);
|
2008-12-19 18:14:02 +00:00
|
|
|
log_incomplete_request();
|
2009-08-21 19:14:15 +00:00
|
|
|
sreply.insert_message(buf, "low");
|
2004-03-20 07:57:34 +00:00
|
|
|
}
|
2005-03-19 18:24:24 +00:00
|
|
|
|
2009-03-03 00:12:55 +00:00
|
|
|
if ((config.locality_scheduling || config.locality_scheduler_fraction) && !sreply.nucleus_only) {
|
2008-12-19 18:14:02 +00:00
|
|
|
send_file_deletes();
|
2005-01-31 11:45:45 +00:00
|
|
|
}
|
2007-01-30 18:19:30 +00:00
|
|
|
|
2008-05-02 17:48:29 +00:00
|
|
|
if (config.debug_user_messages) {
|
2008-12-19 18:14:02 +00:00
|
|
|
log_user_messages();
|
2005-03-19 18:24:24 +00:00
|
|
|
}
|
|
|
|
|
2008-10-01 22:07:35 +00:00
|
|
|
sreply.write(fout, sreq);
|
- scheduler: add support for anonymous-platform coproc apps.
Old: although the request message contained all info
about the app version (flops, coproc usage etc.)
the server ignored this info,
and assumed that all anonymous platform apps where CPU.
With 6.6 client, this could produce infinite work fetch:
- client uses anon platform, has coproc app
- client has idle CPU, requests CPU work
- scheduler sends it jobs, thinking they will be done by CPU app
- client asks for more work etc.
New: scheduler parses full info on anon platform app versions:
plan class, FLOPS, coprocs.
It uses this info to make scheduling decisions;
in particular, if the request is for CUDA work,
if will only send jobs that use a CUDA app version.
The <result> records it returns contain info
(plan_class) that tells the client which app_version to use.
This will work correctly even if the client has multiple app versions
for the same app (e.g., a CPU version and a GPU version)
svn path=/trunk/boinc/; revision=17506
2009-03-05 17:30:10 +00:00
|
|
|
log_messages.printf(MSG_NORMAL,
|
|
|
|
"Scheduler ran %.3f seconds\n", dtime()-start_time
|
|
|
|
);
|
2005-06-03 21:39:38 +00:00
|
|
|
|
|
|
|
if (strlen(config.sched_lockfile_dir)) {
|
2008-12-19 18:14:02 +00:00
|
|
|
unlock_sched();
|
2005-05-17 05:55:24 +00:00
|
|
|
}
|
2002-04-30 22:22:54 +00:00
|
|
|
}
|
2004-12-08 00:40:19 +00:00
|
|
|
|
2005-01-02 18:29:53 +00:00
|
|
|
const char *BOINC_RCSID_2ac231f9de = "$Id$";
|