1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
31 #include "error_numbers.h"
33 #include "sched_msgs.h"
34 #include "sched_util.h"
38 #include "boinc_fcgi.h"
41 const char* STOP_DAEMONS_FILENAME = "../stop_daemons";
42 // NOTE: this must be same as in the "start" script
43 const char* STOP_SCHED_FILENAME = "../stop_sched";
44 // NOTE: this must be same as in the "start" script
45 const int STOP_SIGNAL = SIGHUP;
46 // NOTE: this must be same as in the "start" script
48 void write_pid_file(const char* filename) {
50 FILE* fpid = fopen(filename, "w");
52 FCGI_FILE* fpid = FCGI::fopen(filename,"w");
56 log_messages.printf(MSG_CRITICAL, "Couldn't write pid file\n");
59 fprintf(fpid, "%d\n", (int)getpid());
63 // caught_sig_int will be set to true if STOP_SIGNAL (normally SIGHUP)
65 bool caught_stop_signal = false;
66 static void stop_signal_handler(int) {
67 fprintf(stderr, "GOT STOP SIGNAL\n");
68 caught_stop_signal = true;
71 void install_stop_signal_handler() {
72 signal(STOP_SIGNAL, stop_signal_handler);
73 // handler is now default again so hitting ^C again will kill the program.
76 void check_stop_daemons() {
77 if (caught_stop_signal) {
78 log_messages.printf(MSG_NORMAL, "Quitting due to SIGHUP\n");
81 if (boinc_file_exists(STOP_DAEMONS_FILENAME)) {
82 log_messages.printf(MSG_NORMAL,
83 "Quitting because trigger file '%s' is present\n",
90 bool check_stop_sched() {
91 return boinc_file_exists(STOP_SCHED_FILENAME);
94 // try to open a file.
96 // return ERR_FOPEN if the dir is there but not file
97 // (this is generally a nonrecoverable failure)
98 // return ERR_OPENDIR if dir is not there.
99 // (this is generally a recoverable error,
100 // like NFS mount failure, that may go away later)
103 int try_fopen(const char* path, FILE*& f, const char* mode) {
105 int try_fopen(const char* path, FCGI_FILE*& f, const char *mode) {
112 f = fopen(path, mode);
114 f = FCGI::fopen(path, mode);
118 memset(dirpath, '\0', sizeof(dirpath));
119 p = strrchr(path, '/');
121 strncpy(dirpath, path, (int)(p-path));
123 strcpy(dirpath, ".");
125 if ((d = opendir(dirpath)) == NULL) {
135 void get_log_path(char* p, const char* filename) {
138 gethostname(host, 256);
139 char* q = strchr(host, '.');
141 sprintf(dir, "../log_%s", host);
142 sprintf(p, "%s/%s", dir, filename);
143 mode_t old_mask = umask(0);
145 // make log_x directory sticky and group-rwx
146 // so that whatever apache puts there will be owned by us
150 static void filename_hash(const char* filename, int fanout, char* dir) {
151 std::string s = md5_string((const unsigned char*)filename, strlen(filename));
152 int x = strtol(s.substr(1, 7).c_str(), 0, 16);
153 sprintf(dir, "%x", x % fanout);
156 // given a filename, compute its path in a directory hierarchy
157 // If create is true, create the directory if needed
160 const char* filename, const char* root, int fanout,
161 char* path, bool create
163 char dir[256], dirpath[256];
167 sprintf(path, "%s/%s", root, filename);
171 filename_hash(filename, fanout, dir);
173 sprintf(dirpath, "%s/%s", root, dir);
175 retval = boinc_mkdir(dirpath);
176 if (retval && (errno != EEXIST)) {
177 fprintf(stderr, "boinc_mkdir(%s): retval %d errno %d\n", dirpath, retval, errno);
181 sprintf(path, "%s/%s", dirpath, filename);
185 // same, but the output is a URL (used by tools/backend_lib.C)
188 const char* filename, const char* root, int fanout,
194 sprintf(result, "%s/%s", root, filename);
198 filename_hash(filename, fanout, dir);
199 sprintf(result, "%s/%s/%s", root, dir, filename);
203 // Locality scheduling: get filename from result name
206 int extract_filename(char* in, char* out) {
208 char* p = strstr(out, "__");
214 void compute_avg_turnaround(HOST& host, double turnaround) {
216 if (host.avg_turnaround == 0) {
217 new_avg = turnaround;
219 new_avg = .7*host.avg_turnaround + .3*turnaround;
221 host.avg_turnaround = new_avg;
224 double elapsed_wallclock_time() {
225 static double wallclock_execution_time=0.0;
227 if (wallclock_execution_time == 0.0) {
228 wallclock_execution_time=dtime();
232 return dtime()-wallclock_execution_time;
235 // Request lock on the given file with given fd. Returns:
237 // PID (>0) if another process has lock
240 int mylockf(int fd) {
243 fl.l_whence=SEEK_SET;
246 if (-1 != fcntl(fd, F_SETLK, &fl)) return 0;
248 // if lock failed, find out why
250 fcntl(fd, F_GETLK, &fl);
251 if (fl.l_pid>0) return fl.l_pid;
255 double fpops_to_credit(double fpops, double intops) {
256 // TODO: use fp_weight if specified in config file
257 double fpc = (fpops/1e9)*COBBLESTONE_FACTOR/SECONDS_PER_DAY;
258 double intc = (intops/1e9)*COBBLESTONE_FACTOR/SECONDS_PER_DAY;
259 return std::max(fpc, intc);
262 double credit_multiplier(int appid, time_t create_time) {
263 DB_CREDIT_MULTIPLIER mult;
264 mult.get_nearest(appid,create_time);
265 return mult.multiplier;
268 int count_results(char* query, int& n) {
270 int retval = result.count(n, query);
271 if (retval) return retval;
275 int count_workunits(int& n, const char* query) {
276 DB_WORKUNIT workunit;
277 int retval = workunit.count(n, query);
278 if (retval) return retval;
282 int count_unsent_results(int& n, int appid) {
285 sprintf(buf, "where server_state=%d and appid=%d ",
286 RESULT_SERVER_STATE_UNSENT, appid
289 sprintf(buf, "where server_state=%d", RESULT_SERVER_STATE_UNSENT);
291 return count_results(buf, n);
297 void simulator_signal_handler(int signum){
299 char currenttime[64];
300 fsim = fopen("../simulator/sim_time.txt","r");
302 fscanf(fsim,"%s", currenttime);
303 simtime = atof(currenttime);
306 log_messages.printf(SCHED_MSG_LOG::MSG_NORMAL,
307 "Invoked by the simulator at time %.0f... \n", simtime
312 return (int) simtime;
315 void continue_simulation(const char *daemonname){
316 char daemonfilelok[64];
318 sprintf(daemonfile, "../simulator/sim_%s.txt",daemonname);
319 sprintf(daemonfilelok, "../simulator/sim_%s.lok",daemonname);
320 FILE *fsimlok = fopen(daemonfilelok, "w");
323 FILE *fsim = fopen(daemonfile, "w");
328 remove(daemonfilelok);
333 const char *BOINC_RCSID_affa6ef1e4 = "$Id: sched_util.cpp 16097 2008-09-30 18:21:41Z davea $";