diff --git a/api/boinc_api.C b/api/boinc_api.C index d8317c4a86..95b6281d62 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -191,15 +191,10 @@ static int setup_shared_mem() { } // Return CPU time of worker thread (and optionally others) -// This may be called from other threads +// This may be called from any thread // double boinc_worker_thread_cpu_time() { - static double last_cpu=0; - // last value returned by this func - static time_t last_time=0; - // when it was returned - time_t now = time(0); - double cpu, time_diff = (double)(now - last_time); + double cpu; #ifdef _WIN32 int retval; if (options.all_threads_cpu_time) { @@ -216,6 +211,18 @@ double boinc_worker_thread_cpu_time() { cpu += (double)worker_thread_ru.ru_stime.tv_sec + (((double)worker_thread_ru.ru_stime.tv_usec)/1000000.0); #endif + +#if 0 + // The following paranoia is (I hope) not needed anymore. + // In any case, the check for CPU incrementing faster than real time + // is misguided - it assumes no multi-threading. + // + static double last_cpu=0; + // last value returned by this func + static time_t last_time=0; + // when it was returned + time_t now = time(0); + double time_diff = (double)(now - last_time); if (!finite(cpu)) { fprintf(stderr, "CPU time infinite or NaN\n"); last_time = now; @@ -228,11 +235,12 @@ double boinc_worker_thread_cpu_time() { return last_cpu; } if (cpu_diff>(time_diff + 1)) { -// fprintf(stderr, "CPU time incrementing faster than real time. Correcting.\n"); + fprintf(stderr, "CPU time incrementing faster than real time. Correcting.\n"); cpu = last_cpu + time_diff + 1; // allow catch-up } last_cpu = cpu; last_time = now; +#endif return cpu; } @@ -923,6 +931,7 @@ void* timer_thread(void*) { block_sigalrm(); while(1) { boinc_sleep(TIMER_PERIOD); + getrusage(RUSAGE_SELF, &worker_thread_ru); timer_handler(); } return 0; @@ -933,7 +942,6 @@ void* timer_thread(void*) { // It must call only signal-safe functions, and must not do FP math // void worker_signal_handler(int) { - getrusage(RUSAGE_SELF, &worker_thread_ru); if (options.direct_process_action) { while (boinc_status.suspended && !in_critical_section) { sleep(1); // don't use boinc_sleep() because it does FP math diff --git a/checkin_notes b/checkin_notes index 41f04d6769..b1a40f76c7 100644 --- a/checkin_notes +++ b/checkin_notes @@ -9556,3 +9556,34 @@ Rom 16 Oct 2007 boinc_tray.h (Added) boinc_tray.rc (Added) tray_win.cpp, .h (Added) + +David 16 Oct 2007 + - API, Unix: call getrusage() from the timer thread, + not the worker signal handler. + There's no reason to call it from the signal handler - + it returns the CPU for the entire process, not the calling thread. + And it may be asynch-signal-handler-unsafe. + - API: comment out checks for bad CPU times. + I don't think this is needed now, and in some cases it's wrong + (multi-threaded apps can accumulate CPU faster than real time) + - API, Unix: in boinc_calling_thread_cpu_time(), don't retry getrusage(). + - Bossa: switch to better class structure (suggested by Nicolas Alvarez). + Haven't switched to mysqli yet, but will later. + Also various other Bossa fixes + + api/ + boinc_api.C + db/ + bossa_constraints.sal + bossa_schema.sql + html/ + inc/ + bossa_db.inc + ops/ + bossa_make_jobs_example.php + bossa_setup_example.php + user/ + bossa_example.php (new) + bossa_get_job.php + lib/ + util.C diff --git a/db/bossa_constraints.sql b/db/bossa_constraints.sql index 1c05f25b31..94530740ce 100644 --- a/db/bossa_constraints.sql +++ b/db/bossa_constraints.sql @@ -2,5 +2,9 @@ alter table bossa_app add unique(name); alter table bossa_job - add unique(name) - add index bj_more_needed(more_needed); + add unique(name), + add index bj_more_needed(app, more_needed); + +alter table bossa_job_inst + add index bji_job(job_id), + add index bji_user(user_id); diff --git a/db/bossa_schema.sql b/db/bossa_schema.sql index da3dd8d99c..8c7faf42d1 100644 --- a/db/bossa_schema.sql +++ b/db/bossa_schema.sql @@ -5,7 +5,6 @@ create table bossa_app ( user_friendly_name varchar(255) not null, long_jobs tinyint not null, start_url varchar(255) not null, - finish_url varchar(255) not null, deprecated tinyint not null, beta tinyint not null, primary key(id) @@ -33,5 +32,6 @@ create table bossa_job_inst ( job_id integer not null, user_id integer not null, finish_time integer not null, + info varchar(255) not null, primary key(id) ); diff --git a/html/inc/bossa_db.inc b/html/inc/bossa_db.inc index e700aa7cab..a5e483c1ab 100644 --- a/html/inc/bossa_db.inc +++ b/html/inc/bossa_db.inc @@ -1,18 +1,25 @@ long_jobs) $app->long_jobs = 0; +function bossa_lookup($id, $table) { + $result = mysql_query("select * from $table where id='$id'"); + if (!$result) return null; + $obj = mysql_fetch_object($result); + mysql_free_result($result); + return $obj; +} + +class BossaApp { + function insert() { + if (!$this->long_jobs) $this->long_jobs = 0; $now = time(); - $query = "insert into bossa_app (create_time, name, user_friendly_name, long_jobs, start_url, finish_url) values ($now, '$app->name', '$app->user_friendly_name', $app->long_jobs, '$app->start_url', '$app->finish_url')"; - echo $query; + $query = "insert into bossa_app (create_time, name, user_friendly_name, long_jobs, start_url) values ($now, '$this->name', '$this->user_friendly_name', $this->long_jobs, '$this->start_url')"; $result = mysql_query($query); if (!$result) return false; - $app->id = mysql_insert_id(); + $this->id = mysql_insert_id(); return true; } - function app_lookup_name($name) { + static function lookup_name($name) { $result = mysql_query("select * from bossa_app where name='$name'"); if (!$result) return null; $app = mysql_fetch_object($result); @@ -20,42 +27,56 @@ class Bossa { return $app; } - function app_lookup_id($id) { - $result = mysql_query("select * from bossa_app where id='$id'"); - if (!$result) return null; - $app = mysql_fetch_object($result); - mysql_free_result($result); - return $app; + static function lookup_id($id) { + return bossa_lookup($id, 'bossa_app'); } +} - function insert_job(&$job) { +class BossaJob { + function insert() { $now = time(); - $query = "insert into bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, more_needed, npending, nsuccess, nsuccess_needed) values ($now, '$job->name', $job->app_id, '$job->info', $job->batch, $job->time_estimate, $job->time_limit, 1, 0, 0, $job->nsuccess_needed)"; + $query = "insert into bossa_job (create_time, name, app_id, info, batch, time_estimate, time_limit, more_needed, npending, nsuccess, nsuccess_needed) values ($now, '$this->name', $this->app_id, '$this->info', $this->batch, $this->time_estimate, $this->time_limit, 1, 0, 0, $this->nsuccess_needed)"; $result = mysql_query($query); if (!$result) { echo "$query\n"; return false; } - $job->id = mysql_insert_id(); + $this->id = mysql_insert_id(); return true; } + function update($clause) { + return mysql_query("update bossa_job set $clause where id=$this->id"); + } + static function lookup_id($id) { + return bossa_lookup($id, 'bossa_job'); + } +} - function insert_job_inst(&$ji) { +class BossaJobInst { + function insert() { $now = time(); - $query = "insert into bossa_job_inst (create_time, job_id, user_id) values ($now, $ji->job_id, $ji->user_id)"; + $query = "insert into bossa_job_inst (create_time, job_id, user_id) values ($now, $this->job_id, $this->user_id)"; $result = mysql_query($query); if (!$result) { echo "$query\n"; return false; } - $ji->id = mysql_insert_id(); + $this->id = mysql_insert_id(); return true; } + static function lookup_id($id) { + return bossa_lookup($id, 'bossa_job_inst'); + } + + function update($clause) { + return mysql_query("update bossa_job_inst set $clause where id=$this->id"); + } + // Assign a job from the given app to the given user. // Returns the job instance or NULL. // - function assign_job($app, $user) { + static function assign($app, $user) { // this query skips jobs for which this user // has already been assigned an instance // @@ -69,15 +90,36 @@ class Bossa { echo "
Please try again later. "; page_tail(); diff --git a/lib/util.C b/lib/util.C index c6e0afe4a0..0ec4b33faa 100644 --- a/lib/util.C +++ b/lib/util.C @@ -191,26 +191,16 @@ int boinc_calling_thread_cpu_time(double& cpu) { #else -// Unix: pthreads doesn't seem to provide an API for getting -// per-thread CPU time. So just get the process's CPU time +// Unix: pthreads doesn't provide an API for getting per-thread CPU time, +// so just get the process's CPU time // int boinc_calling_thread_cpu_time(double &cpu_t) { - int retval=1; struct rusage ru; - // getrusage can return an error, so try a few times if it returns an error. - // - for (int i=0; i<10; i++) { - retval = getrusage(RUSAGE_SELF, &ru); - if (!retval) break; - } - if (retval) { - return ERR_GETRUSAGE; - } - // Sum the user and system time - // - cpu_t = (double)ru.ru_utime.tv_sec + (((double)ru.ru_utime.tv_usec) / ((double)1000000.0)); - cpu_t += (double)ru.ru_stime.tv_sec + (((double)ru.ru_stime.tv_usec) / ((double)1000000.0)); + int retval = getrusage(RUSAGE_SELF, &ru); + if (retval) return ERR_GETRUSAGE; + cpu_t = (double)ru.ru_utime.tv_sec + ((double)ru.ru_utime.tv_usec) / 1e6; + cpu_t += (double)ru.ru_stime.tv_sec + ((double)ru.ru_stime.tv_usec) / 1e6; return 0; }