. require_once("../inc/credit.inc"); require_once("../inc/stats_sites.inc"); require_once("../inc/boinc_db.inc"); function link_to_results($host) { if (!$host) return tra("No host"); $config = get_config(); if (!parse_bool($config, "show_results")) return tra("Unavailable"); $nresults = host_nresults($host); if (!$nresults) return "0"; return "id>$nresults"; } function sched_log_name($x) { if ($x == 0) return "NO_SUCH_LOG"; return gmdate('Y-m-d_H/Y-m-d_H:i', $x) . ".txt"; } function sched_log_link($x) { if (file_exists("sched_logs")) { return "" . time_str($x) . ""; } else { return time_str($x); } } function location_form($host) { $none = "selected"; $h=$w=$s=""; if ($host->venue == "home") $h = "selected"; if ($host->venue == "work") $w = "selected"; if ($host->venue == "school") $s = "selected"; $x = "
id>
"; return $x; } function cross_project_links($host) { global $host_sites; $x = ""; foreach ($host_sites as $h) { $url = $h[0]; $name = $h[1]; $img = $h[2]; $x .= "host_cpid.">\"$name\"\n"; } return $x; } // Show full-page description of $host. // If $user is non-null, it's both the owner of the host // and the logged in user (so show some extra fields) // function show_host($host, $user, $ipprivate) { start_table(); row1(tra("Computer information")); $anonymous = false; if ($user) { if ($ipprivate) { row2(tra("IP address"), "$host->last_ip_addr
".tra("(same the last %1 times)", $host->nsame_ip_addr)); if ($host->last_ip_addr != $host->external_ip_addr) { row2(tra("External IP address"), $host->external_ip_addr); } } else { row2(tra("IP address"), "id&ipprivate=1>".tra("Show IP address").""); } row2(tra("Domain name"), $host->domain_name); $x = $host->timezone/3600; if ($x >= 0) $x="+$x"; row2(tra("Local Standard Time"), tra("UTC %1 hours", $x)); row2(tra("Name"), $host->domain_name); } else { $owner = lookup_user_id($host->userid); if ($owner && $owner->show_hosts) { row2(tra("Owner"), user_links($owner)); } else { row2(tra("Owner"), tra("Anonymous")); $anonymous = true; } } row2(tra("Created"), time_str($host->create_time)); row2(tra("Total credit"), format_credit_large($host->total_credit)); row2(tra("Average credit"), format_credit($host->expavg_credit)); if (!$anonymous) { row2(tra("Cross project credit"), cross_project_links($host)); } row2(tra("CPU type"), "$host->p_vendor
$host->p_model"); row2(tra("Number of processors"), $host->p_ncpus); if ($host->serialnum) { row2(tra("Coprocessors"), gpu_desc($host->serialnum)); } row2(tra("Operating System"), "$host->os_name
$host->os_version"); $v = boinc_version($host->serialnum); if ($v) { row2(tra("BOINC version"), $v); } $x = $host->m_nbytes/(1024*1024); $y = round($x, 2); row2(tra("Memory"), tra("%1 MB", $y)); $x = $host->m_cache/1024; $y = round($x, 2); row2(tra("Cache"), tra("%1 KB", $y)); if ($user) { $x = $host->m_swap/(1024*1024); $y = round($x, 2); row2(tra("Swap space"), tra("%1 MB", $y)); $x = $host->d_total/(1024*1024*1024); $y = round($x, 2); row2(tra("Total disk space"), tra("%1 GB", $y)); $x = $host->d_free/(1024*1024*1024); $y = round($x, 2); row2(tra("Free Disk Space"), tra("%1 GB", $y)); } $x = $host->p_fpops/(1000*1000); $y = round($x, 2); row2(tra("Measured floating point speed"), tra("%1 million ops/sec", $y)); $x = $host->p_iops/(1000*1000); $y = round($x, 2); row2(tra("Measured integer speed"), tra("%1 million ops/sec", $y)); $x = $host->n_bwup/(1024); $y = round($x, 2); if ($y > 0) { row2(tra("Average upload rate"), tra("%1 KB/sec", $y)); } else { row2(tra("Average upload rate"), tra("Unknown")); } $x = $host->n_bwdown/(1024); $y = round($x, 2); if ($y > 0) { row2(tra("Average download rate"), tra("%1 KB/sec", $y)); } else { row2(tra("Average download rate"), tra("Unknown")); } $x = $host->avg_turnaround/86400; row2(tra("Average turnaround time"), tra("%1 days", round($x, 2))); row2(tra("Application details"), "id>".tra("Show")."" ); $config = get_config(); if (parse_bool($config, "show_results")) { $nresults = host_nresults($host); if ($nresults) { $results = "id>$nresults"; } else { $results = "0"; } row2(tra("Tasks"), $results); } if ($user) { row2(tra("Number of times client has contacted server"), $host->rpc_seqno); row2(tra("Last time contacted server"), sched_log_link($host->rpc_time)); row2(tra("% of time BOINC is running"), 100*$host->on_frac." %"); if ($host->connected_frac > 0) { row2(tra("While BOINC running, % of time host has an Internet connection"), 100*$host->connected_frac." %"); } row2(tra("While BOINC running, % of time work is allowed"), 100*$host->active_frac." %"); if ($host->cpu_efficiency) { row2(tra("Average CPU efficiency"), $host->cpu_efficiency); } if ($host->duration_correction_factor) { row2(tra("Task duration correction factor"), $host->duration_correction_factor); } row2(tra("Location"), location_form($host)); if ($nresults == 0) { $x = " · id".url_tokens($user->authenticator).">".tra("Delete this computer")." "; } else { $x = ""; } row2(tra("Merge duplicate records of this computer"), "id>".tra("Merge")." $x"); } else { row2(tra("Number of times client has contacted server"), $host->rpc_seqno); row2(tra("Last contact"), date_str($host->rpc_time)); } echo "\n"; } // the following is used for list of top hosts // function top_host_table_start($sort_by) { global $host_sites; shuffle($host_sites); start_table(); echo ""; echo "".tra("Computer info")."\n"; echo "".tra("Rank").""; echo "".tra("Owner")."\n"; if ($sort_by == 'total_credit') { echo " ".tra("Avg. credit")." ".tra("Total credit")." "; } else { echo " ".tra("Recent average credit")." ".tra("Total credit")." "; } echo " ".tra("BOINC version")." ".tra("CPU")." ".tra("GPU")." ".tra("Operating system")." "; } function host_nresults($host) { return BoincResult::count("hostid=$host->id"); } // Given string of the form [BOINC|vers][type|model|count|RAM|driver-vers][vbox|vers], // return a human-readable version of the GPU info // function gpu_desc($x) { $descs = explode("]", $x); array_pop($descs); $str = ""; foreach ($descs as $desc) { $desc = trim($desc, "["); $d = explode("|", $desc); //print_r($d); if ($d[0] == "BOINC") continue; if ($d[0] == "vbox") continue; if ($str) $str .= ", "; if ($d[2]!="" && $d[2]!="1") $str .= "[".$d[2]."] "; if ($d[0] == "CUDA") { $str .= "NVIDIA"; } else if ($d[0] == "CAL") { $str .= "AMD"; } else { $str .= $d[0]; } $str .= " ".$d[1]; $str .= " (".$d[3].")"; if (array_key_exists(4, $d)) { if ($d[4] != "" && $d[4] != 0) { // if version has no '.', assume it's in 100*maj+min form // if (strchr($d[4], '.')) { $str .= " driver: ".$d[4]; } else { $i = (int)$d[4]; $maj = (int)($i/100); $min = $i%100; $str .= " driver: $maj.$min"; } } } } if (!$str) $str = "---"; return $str; } // Given the same string as above, return the BOINC version // function boinc_version($x) { $y = strstr($x, 'BOINC'); if (!$y) return ''; $y = substr($y, 6); $z = explode("]", $y, 2); return $z[0]; } function cpu_desc($host) { return "$host->p_vendor
$host->p_model
".tra("(%1 processors)", $host->p_ncpus)."\n"; } // If private is true, we're showing the host to its owner, // so it's OK to show the domain name etc. // If private is false, show the owner's name only if they've given permission // function show_host_row($host, $i, $private, $show_owner) { $j = $i % 2; $anonymous = false; if (!$private) { if ($show_owner) { $user = BoincUser::lookup_id($host->userid); if ($user && $user->show_hosts) { } else { $anonymous = true; } } } echo "ID: $host->id
id>".tra("Details")." | id>".tra("Tasks")." "; if (!$anonymous) { echo "
".tra("Cross-project stats:")."
".cross_project_links($host); } echo " "; if ($private) { echo "$host->domain_name\n"; echo "$host->venue\n"; } else { echo "$i\n"; if ($show_owner) { if ($anonymous) { echo "".tra("Anonymous")."\n"; } else { echo "", user_links($user), "\n"; } } } if ($show_owner) { // This is used in the "top computers" display // printf(" %s %s %s %s %s %s
%s", format_credit($host->expavg_credit), format_credit_large($host->total_credit), boinc_version($host->serialnum), cpu_desc($host), gpu_desc($host->serialnum), $host->os_name, $host->os_version ); } else { // This is used to show the computers of a given user // printf(" %s %s %s %s %s %s
%s %s ", format_credit($host->expavg_credit), format_credit_large($host->total_credit), boinc_version($host->serialnum), cpu_desc($host), gpu_desc($host->serialnum), $host->os_name, $host->os_version, sched_log_link($host->rpc_time) ); } echo "\n"; } // Logic for deciding whether two host records might actually // be the same machine, based on CPU info // // p_vendor is typically either AuthenticAMD or GenuineIntel. // Over time we've changed the contents of p_model. // Some examples: // Intel(R) Core(TM)2 Duo CPU E7300 @ 2.66GHz [Family 6 Model 23 Stepping 6] // AMD Athlon(tm) II X2 250 Processor [Family 16 Model 6 Stepping 3] // Intel(R) Xeon(R) CPU X5650 @ 2.67GHz [x86 Family 6 Model 44 Stepping 2] // Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz [Intel64 Family 6 Model 42 Stepping 7] // // in the last 2 cases, let's call x86 and Intel64 the "architecture" // // so, here's the policy: // // if p_ncpus different, return false // if p_vendor different, return false // if both have family/model/stepping info // if info disagrees, return false // if both have GHz info, and they disagree, return false // if both have architecture, and they disagree, return false // return true // if p_model different, return false // return true // // parse p_model to produce the following structure: // x->speed "3.00GHz" etc. or null // x->arch "x86" etc. or null // x->info "Family 6 Model 23 Stepping 6" etc. or null // function parse_model($model) { $y = explode(" ", $model); $x = null; $x->speed = null; $x->arch = null; $x->info = null; foreach ($y as $z) { if (strstr($z, "GHz")) $x->speed = $z; if (strstr($z, "MHz")) $x->speed = $z; } $pos1 = strpos($model, '['); if ($pos1 === false) return $x; $pos2 = strpos($model, ']'); if ($pos2 === false) return $x; $a = substr($model, $pos1+1, $pos2-$pos1-1); $y = explode(" ", $a); if (count($y) == 0) return $x; if ($y[0] == "Family") { $x->info = $a; } else { $x->arch = $y[0]; $x->info = substr($a, strlen($y[0])+1); } return $x; } function cpus_compatible($host1, $host2) { if ($host1->p_ncpus != $host2->p_ncpus) return false; if ($host1->p_vendor != $host2->p_vendor) return false; $x1 = parse_model($host1->p_model); $x2 = parse_model($host2->p_model); if ($x1->info && $x2->info) { if ($x1->info != $x2->info) return false; if ($x1->speed && $x2->speed) { if ($x1->speed != $x2->speed) return false; } if ($x1->arch && $x2->arch) { if ($x1->arch != $x2->arch) return false; } return true; } if ($host1->p_model != $host2->p_model) return false; return true; } // does one host strictly precede the other? // function times_disjoint($host1, $host2) { if ($host1->rpc_time < $host2->create_time) return true; if ($host2->rpc_time < $host1->create_time) return true; return false; } function os_compatible($host1, $host2) { if (strstr($host1->os_name, "Windows") && strstr($host2->os_name, "Windows")) return true; if (strstr($host1->os_name, "Linux") && strstr($host2->os_name, "Linux")) return true; if (strstr($host1->os_name, "Darwin") && strstr($host2->os_name, "Darwin")) return true; if (strstr($host1->os_name, "SunOS") && strstr($host2->os_name, "SunOS")) return true; if ($host1->os_name == $host2->os_name) return true; return false; } // Return true if it's possible that the two host records // correspond to the same host // NOTE: the cheat-proofing comes from checking // that their time intervals are disjoint. // So the CPU/OS checks don't have to be very strict. // function hosts_compatible($host1, $host2, $show_detail) { // A host is "new" if it has no credit and no results. // Skip disjoint-time check if one host or other is new // $new1 = !$host1->total_credit && !host_nresults($host1); $new2 = !$host2->total_credit && !host_nresults($host2); if (!$new1 && !$new2) { if (!times_disjoint($host1, $host2)) { if ($show_detail) { $c1 = date_str($host1->create_time); $r1 = date_str($host1->rpc_time); $c2 = date_str($host2->create_time); $r2 = date_str($host2->rpc_time); echo "
".tra("Host %1 has overlapping lifetime:", $host2->id)." ($c1 - $r1), ($c2 - $r2)"; } return false; } } if (!os_compatible($host1, $host2)) { if ($show_detail) { echo "
".tra("Host %1 has an incompatible OS:", $host2->id)." ($host1->os_name, $host2->os_name)\n"; } return false; } if (!cpus_compatible($host1, $host2)) { if ($show_detail) { echo "
".tra("Host %1 has an incompatible CPU:", $host2->id)." ($host1->p_vendor $host1->p_model, $host2->p_vendor $host2->p_model)\n"; } return false; } return true; } // recompute host's average credit by scanning results. // Could be expensive if lots of results! // function host_update_credit($hostid) { $total = 0; $avg = 0; $avg_time = 0; $results = BoincResult::enum("hostid=$hostid order by received_time"); foreach($results as $result) { if ($result->granted_credit <= 0) continue; $total += $result->granted_credit; update_average( $result->received_time, $result->sent_time, $result->granted_credit, $avg, $avg_time ); //echo "
$avg\n"; } // do a final decay // $now = time(); update_average(now, 0, 0, $avg, $avg_time); $host = new BoincHost(); $host->id = hostid; $host->update("total_credit=$total, expavg_credit=$avg, expavg_time=$now"); } // decay a host's average credit // function host_decay_credit($host) { $avg = $host->expavg_credit; $avg_time = $host->expavg_time; $now = time(0); update_average($now, 0, 0, $avg, $avg_time); $host->update("expavg_credit=$avg, expavg_time=$now"); } // if the host hasn't received new credit for ndays, // decay its average and return true // function host_inactive_ndays($host, $ndays) { $diff = time() - $host->expavg_time; if ($diff > $ndays*86400) { host_decay_credit($host); return true; } return false; } // invariant: old_host.create_time < new_host.create_time // function merge_hosts($old_host, $new_host) { if ($old_host->id == $new_host->id) { return tra("same host"); } if (!hosts_compatible($old_host, $new_host, false)) { return tra("Can't merge host %1 into %2 - they're incompatible", $old_host->id, $new_host->id); } echo "
".tra("Merging host %1 into host %2", $old_host->id, $new_host->id)."\n"; // decay the average credit of both hosts // $now = time(); update_average($now, 0, 0, $old_host->expavg_credit, $old_host->expavg_time); update_average($now, 0, 0, $new_host->expavg_credit, $new_host->expavg_time); // update the database: // - add credit from old to new host // - change results to refer to new host // - put old host in "zombie" state (userid=0, rpc_seqno=new host ID) // $total_credit = $old_host->total_credit + $new_host->total_credit; $recent_credit = $old_host->expavg_credit + $new_host->expavg_credit; $result = $new_host->update("total_credit=$total_credit, expavg_credit=$recent_credit, expavg_time=$now"); if (!$result) { return tra("Couldn't update credit of new computer"); } $result = BoincResult::update_aux("hostid=$new_host->id where hostid=$old_host->id"); if (!$result) { return tra("Couldn't update results"); } $result = $old_host->update("total_credit=0, expavg_credit=0, userid=0, rpc_seqno=$new_host->id"); if (!$result) { return tra("Couldn't retire old computer"); } echo "
".tra("Retired old computer %1", $old_host->id)."\n"; return 0; } //////////////// helper functions for hosts_user.php //////////////// function link_url($sort, $rev, $show_all) { global $userid; $x = $userid ? "&userid=$userid":""; return "hosts_user.php?sort=$sort&rev=$rev&show_all=$show_all$x"; } function link_url_rev($actual_sort, $sort, $rev, $show_all) { if ($actual_sort == $sort) { $rev = 1 - $rev; } return link_url($sort, $rev, $show_all); } function more_or_less($sort, $rev, $show_all) { echo "

"; if ($show_all) { $url = link_url($sort, $rev, 0); echo tra("Show:")." ".tra("All computers")." · ".tra("Only computers active in past 30 days").""; } else { $url = link_url($sort, $rev, 1); echo tra("Show:")." ".tra("All computers")." · ".tra("Only computers active in past 30 days"); } echo "

"; } function user_host_table_start($private, $sort, $rev, $show_all) { start_table(); echo ""; $url = link_url_rev($sort, "id", $rev, $show_all); echo "".tra("Computer ID")."\n"; if ($private) { $url = link_url_rev($sort, "name", $rev, $show_all); echo "".tra("Name")."\n"; $url = link_url_rev($sort, "venue", $rev, $show_all); echo "".tra("Location")."\n"; } else { echo "".tra("Rank").""; } $url = link_url_rev($sort, "expavg_credit", $rev, $show_all); echo "".tra("Avg. credit")."\n"; $url = link_url_rev($sort, "total_credit", $rev, $show_all); echo "".tra("Total credit")."\n"; echo "".tra("BOINC
version")."\n"; $url = link_url_rev($sort, "cpu", $rev, $show_all); echo "".tra("CPU")."\n"; echo "".tra("GPU")."\n"; $url = link_url_rev($sort, "os", $rev, $show_all); echo "".tra("Operating System")."\n"; $url = link_url_rev($sort, "rpc_time", $rev, $show_all); echo "".tra("Last contact")."\n"; } function show_user_hosts($userid, $private, $show_all, $sort, $rev) { $desc = false; // whether the sort order's default is decreasing switch ($sort) { case "total_credit": $sort_clause = "total_credit"; $desc = true; break; case "expavg_credit": $sort_clause = "expavg_credit"; $desc = true; break; case "name": $sort_clause = "domain_name"; break; case "id": $sort_clause = "id"; break; case "cpu": $sort_clause = "p_vendor"; break; case "gpu": $sort_clause = "serialnum"; break; case "os": $sort_clause = "os_name"; break; case "venue": $sort_clause = "venue"; break; default: // default value -- sort by RPC time $sort = "rpc_time"; $sort_clause = "rpc_time"; $desc = true; } if ($rev != $desc) { $sort_clause .= " desc"; } more_or_less($sort, $rev, $show_all); user_host_table_start($private, $sort, $rev, $show_all); $now = time(); $old_hosts=0; $i = 1; $hosts = BoincHost::enum("userid=$userid order by $sort_clause"); foreach ($hosts as $host) { $is_old=false; if (($now - $host->rpc_time) > 30*86400) { $is_old=true; $old_hosts++; } if (!$show_all && $is_old) continue; show_host_row($host, $i, $private, false); $i++; } echo "\n"; if ($old_hosts>0) { more_or_less($sort, $rev, $show_all); } if ($private) { echo " ".tra("Merge computers by name")." "; } } // remove user-specific info from a user's hosts // function anonymize_hosts($user) { $hosts = BoincHost::enum("userid=$user->id"); foreach ($hosts as $h) { $h->update("domain_name='', last_ip_addr=''"); } } $cvs_version_tracker[]="\$Id$"; //Generated automatically - do not edit ?>