Passed
Pull Request — master (#6667)
by David
10:05
created

gpu_desc()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 6
nop 1
dl 0
loc 17
rs 9.5555
c 0
b 0
f 0
1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
require_once("../inc/credit.inc");
20
require_once("../inc/stats_sites.inc");
21
require_once("../inc/boinc_db.inc");
22
require_once("../inc/user.inc");
23
24
function link_to_results($host) {
25
    if (!$host) return tra("No host");
26
    $config = get_config();
27
    if (!parse_bool($config, "show_results")) return tra("Unavailable");
28
    $nresults = host_nresults($host);
29
    if (!$nresults) return "0";
30
    return "<a href=results.php?hostid=$host->id>$nresults</a>";
31
}
32
33
function sched_log_name($x) {
34
    if ($x == 0) return "NO_SUCH_LOG";
35
    return gmdate('Y-m-d_H/Y-m-d_H:i', $x) . ".txt";
36
}
37
38
function sched_log_link($x) {
39
    if (file_exists("sched_logs")) {
40
        return "<a href=\"../sched_logs/" . sched_log_name($x) . "\">" . time_str($x) . "</a>";
41
    } else {
42
        return time_str($x);
43
    }
44
}
45
46
function location_form($host) {
47
    $none = "selected";
48
    $h=$w=$s=$m="";
49
    if ($host->venue == "home") $h = "selected";
50
    if ($host->venue == "work") $w = "selected";
51
    if ($host->venue == "school") $s = "selected";
52
    $x = "<form action=host_venue_action.php>
53
        <input type=hidden name=hostid value=$host->id>
54
        <select class=\"form-control\" name=venue>
55
        <option value=\"\" $none>---
56
        <option value=home $h>".tra("Home")."
57
        <option value=work $w>".tra("Work")."
58
        <option value=school $s>".tra("School")."
59
        </select>
60
        <p></p>
61
        <input class=\"btn btn-primary btn-sm\" type=submit value=\"".tra("Update location")."\">
62
        </form>
63
    ";
64
    return $x;
65
}
66
67
function cross_project_links($host) {
68
    global $host_sites;
69
    $x = "";
70
    foreach ($host_sites as $h) {
71
        $url = $h[0];
72
        $name = $h[1];
73
        $img = $h[2];
74
        $x .= "<a href=$url".$host->host_cpid."><img class=\"icon\" border=2 src=img/$img alt=\"$name\"></a> ";
75
    }
76
    return $x;
77
}
78
79
// Show full-page description of $host.
80
// If $user is non-null, it's both the owner of the host
81
// and the logged in user (so show some extra fields)
82
//
83
function show_host($host, $user, $ipprivate) {
84
    $config = get_config();
85
    start_table();
86
    row1(tra("Computer information"));
87
    $anonymous = false;
88
    if ($user) {
89
        if ($ipprivate) {
90
            row2(tra("IP address"), "$host->last_ip_addr<br>".tra("(same the last %1 times)", $host->nsame_ip_addr));
91
            if ($host->last_ip_addr != $host->external_ip_addr) {
92
                row2(tra("External IP address"), $host->external_ip_addr);
93
            }
94
        } else {
95
            row2(tra("IP address"), "<a href=show_host_detail.php?hostid=$host->id&ipprivate=1>".tra("Show IP address")."</a>");
96
        }
97
        row2(tra("Domain name"), $host->domain_name);
98
        if ($host->product_name) {
99
            row2(tra("Product name"), $host->product_name);
100
        }
101
        $x = $host->timezone/3600;
102
        if ($x >= 0) $x="+$x";
103
        row2(tra("Local Standard Time"), tra("UTC %1 hours", $x));
104
    } else {
105
        $owner = BoincUser::lookup_id($host->userid);
106
        if ($owner && $owner->show_hosts) {
107
            row2(tra("Owner"), user_links($owner, BADGE_HEIGHT_MEDIUM));
108
        } else {
109
            row2(tra("Owner"), tra("Anonymous"));
110
            $anonymous = true;
111
        }
112
    }
113
    row2(tra("Created"), time_str($host->create_time));
114
    if (!NO_STATS) {
115
        row2(tra("Total credit"), format_credit_large($host->total_credit));
116
        row2(tra("Average credit"), format_credit($host->expavg_credit));
117
        if (!$anonymous) {
118
            row2(tra("Cross project credit"), cross_project_links($host));
119
        }
120
    }
121
    row2(tra("CPU type"), "$host->p_vendor <br> $host->p_model");
122
    row2(tra("Number of cores"), $host->p_ncpus);
123
    $misc = json_decode($host->misc);
124
    row2(tra("Coprocessors"), gpu_desc($misc));
125
    row2(tra("Virtualization"), vbox_desc($misc));
126
    row2(tra("Docker"), docker_desc($misc));
127
    row2(tra("Operating System"), "$host->os_name <br> $host->os_version");
128
    $v = boinc_version($misc);
129
    row2(tra("BOINC version"), $misc->client_version);
130
    $x = $host->m_nbytes/GIGA;
131
    $y = round($x, 2);
132
    row2(tra("Memory"), tra("%1 GB", $y));
133
    if ($host->m_cache > 0) {
134
        $x = $host->m_cache/KILO;
135
        $y = round($x, 2);
136
        row2(tra("Cache"), tra("%1 KB", $y));
137
    }
138
139
    if ($user) {
140
        $x = $host->m_swap/GIGA;
141
        $y = round($x, 2);
142
        row2(tra("Swap space"), tra("%1 GB", $y));
143
        $x = $host->d_total/GIGA;
144
        $y = round($x, 2);
145
        row2(tra("Total disk space"), tra("%1 GB", $y));
146
        $x = $host->d_free/GIGA;
147
        $y = round($x, 2);
148
        row2(tra("Free Disk Space"), tra("%1 GB", $y));
149
    }
150
    $x = $host->p_fpops/1e9;
151
    $y = round($x, 2);
152
    row2(tra("Measured floating point speed"), tra("%1 billion ops/sec", $y));
153
    $x = $host->p_iops/1e9;
154
    $y = round($x, 2);
155
    row2(tra("Measured integer speed"), tra("%1 billion ops/sec", $y));
156
    $x = $host->n_bwup/MEGA;
157
    $y = round($x, 2);
158
    if ($y > 0) {
159
        row2(tra("Average upload rate"), tra("%1 MB/sec", $y));
160
    } else {
161
        row2(tra("Average upload rate"), tra("Unknown"));
162
    }
163
    $x = $host->n_bwdown/MEGA;
164
    $y = round($x, 2);
165
    if ($y > 0) {
166
        row2(tra("Average download rate"), tra("%1 MB/sec", $y));
167
    } else {
168
        row2(tra("Average download rate"), tra("Unknown"));
169
    }
170
    $x = $host->avg_turnaround/86400;
171
    if (!NO_COMPUTING) {
172
        row2(tra("Average turnaround time"), tra("%1 days", round($x, 2)));
173
        row2(tra("Application details"),
174
            "<a href=host_app_versions.php?hostid=$host->id>".tra("Show")."</a>"
175
        );
176
        $show_results = parse_bool($config, "show_results");
177
        if ($show_results) {
178
            $nresults = host_nresults($host);
179
            if ($nresults) {
180
                $results = "<a href=results.php?hostid=$host->id>$nresults</a>";
181
            } else {
182
                $results = "0";
183
            }
184
            row2(tra("Tasks"), $results);
185
        }
186
        if (defined('BATCH_ACCEL') && BATCH_ACCEL) {
187
            row2('Low turnaround time?',
188
                $host->error_rate?'yes':'no'
189
            );
190
        }
191
    }
192
193
    if ($user) {
194
        row2(tra("Number of times client has contacted server"), $host->rpc_seqno);
195
        row2(tra("Last time contacted server"), sched_log_link($host->rpc_time));
196
        row2(tra("Fraction of time BOINC is running"), number_format(100*$host->on_frac, 2)."%");
197
        if ($host->connected_frac > 0) {
198
            row2(tra("While BOINC is running, fraction of time computer has an Internet connection"), number_format(100*$host->connected_frac, 2)."%");
199
        }
200
        row2(tra("While BOINC is running, fraction of time computing is allowed"), number_format(100*$host->active_frac, 2)."%");
201
        row2(tra("While is BOINC running, fraction of time GPU computing is allowed"), number_format(100*$host->gpu_active_frac, 2)."%");
202
        if ($host->cpu_efficiency) {
203
            row2(tra("Average CPU efficiency"), $host->cpu_efficiency);
204
        }
205
        if (!NO_COMPUTING) {
206
            if ($host->duration_correction_factor) {
207
                row2(tra("Task duration correction factor"), $host->duration_correction_factor);
208
            }
209
        }
210
        row2(tra("Location"), location_form($host));
211
        if ($show_results && $nresults == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $nresults does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $show_results does not seem to be defined for all execution paths leading up to this point.
Loading history...
212
            $x = " &middot; <a href=host_delete.php?hostid=$host->id".url_tokens($user->authenticator).">".tra("Delete this computer")."</a> ";
213
        } else {
214
            $x = "";
215
        }
216
        row2(tra("Merge duplicate records of this computer"), "<a class=\"btn btn-primary btn-sm\" href=host_edit_form.php?hostid=$host->id>".tra("Merge")."</a> $x");
217
    } else {
218
        row2(tra("Number of times client has contacted server"), $host->rpc_seqno);
219
        row2(tra("Last contact"), date_str($host->rpc_time));
220
    }
221
    echo "</table>\n";
222
223
}
224
225
// the following is used for list of top hosts
226
//
227
function top_host_table_start($sort_by) {
228
    global $host_sites;
229
    shuffle($host_sites);
230
    start_table('table-striped');
231
    $x = array(
232
        tra("Info"),
233
        tra("Rank"),
234
        tra("Owner"),
235
    );
236
    if (!NO_STATS) {
237
        if ($sort_by == 'total_credit') {
238
            $x[] = "<a href=top_hosts.php?sort_by=expavg_credit>".tra("Avg. credit")."</a>";
239
            $x[] = tra("Total credit");
240
        } else {
241
            $x[] = tra("Recent average credit");
242
            $x[] = "<a href=top_hosts.php?sort_by=total_credit>".tra("Total credit")."</a>";
243
        }
244
    }
245
    $x[] = tra("BOINC version");
246
    $x[] = tra("CPU");
247
    $x[] = tra("GPU");
248
    $x[] = tra("Operating system");
249
    $s = 'style="text-align:right;"';
250
    $a = array("", "", "", $s, $s, "", "", "", "");
251
    row_heading_array($x, $a, "bg-default");
252
}
253
254
function host_nresults($host) {
255
    return BoincResult::count("hostid=$host->id");
256
}
257
258
function vbox_desc($misc) {
259
    if (empty($misc->vbox)) return '---';
260
    $v = $misc->vbox;
261
    return sprintf(
262
        'Virtualbox %s<br>HW acceleration: %s<br>Enabled: %s',
263
        $v->version,
264
        $v->hw_accel?'yes':'no',
265
        $v->hw_accel_enabled?'yes':'no'
266
    );
267
}
268
269
function docker_desc($misc) {
270
    if (empty($misc->docker)) return '---';
271
    $d = $misc->docker;
272
    $x = sprintf('%s version %s',
273
        $d->type==1?"Docker":"Podman",
274
        $d->version
275
    );
276
    if (!empty($d->wsl_distro)) {
277
        $x .= sprintf(
278
            '<br>WSL distro: %s ver %d',
279
            $d->wsl_distro, $d->boinc_buda_runner_version
280
        );
281
    }
282
    if (!empty($misc->config)) {
283
        $c = $misc->config;
284
        if (!empty($c->dont_use_wsl)) {
285
            $x .= "Config: don't use WSL";
286
        }
287
        if (!empty($c->dont_use_docker)) {
288
            $x .= "Config: don't use Docker";
289
        }
290
    }
291
    return $x;
292
}
293
294
295
// return a human-readable version of the GPU info
296
//
297
function gpu_desc($misc) {
298
    if (empty($misc->gpus)) return '---';
299
    $gpus = [];
300
    foreach ($misc->gpus as $g) {
301
        $x = sprintf(
302
            '%d %s; %dMB RAM',
303
            $g->count, $g->model, $g->ram_mb
304
        );
305
        if (!empty($g->driver_version)) {
306
            $x .= "; Driver: $g->driver_version";
307
        }
308
        if (!empty($g->opencl_version)) {
309
            $x .= "; OpenCL: $g->opencl_version";
310
        }
311
        $gpus[] = $x;
312
    }
313
    return implode('<br>', $gpus);
314
}
315
316
// Given the same string as above, return the BOINC version
317
//
318
function boinc_version($misc) {
319
    $x = $misc->client_version;
320
    if (!empty($misc->client_brand)) {
321
        $x .= " ($misc->client_brand)";
322
    }
323
    return $x;
324
}
325
326
function cpu_desc($host) {
327
    return "$host->p_vendor<br>$host->p_model<br>".tra("(%1 cores)", $host->p_ncpus)."\n";
328
}
329
330
// If private is true, we're showing the host to its owner,
331
// so it's OK to show the domain name etc.
332
// If private is false, show the owner's name only if they've given permission
333
//
334
function show_host_row($host, $i, $private, $show_owner, $any_product_name) {
335
    $anonymous = false;
336
    if (!$private) {
337
        if ($show_owner) {
338
            $user = BoincUser::lookup_id($host->userid);
339
            if ($user && $user->show_hosts) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
340
            } else {
341
                $anonymous = true;
342
            }
343
        }
344
    }
345
    echo "<tr><td>ID: $host->id
346
        <br><a href=show_host_detail.php?hostid=$host->id>".tra("Details")."</a>
347
    ";
348
    if (!NO_COMPUTING) {
349
        echo "
350
        | <a href=results.php?hostid=$host->id>".tra("Tasks")."</a>
351
        ";
352
    }
353
    if (!NO_STATS) {
354
        if (!$anonymous) {
355
            echo "
356
                <br><nobr><small>".tra("Cross-project stats:")."</small></nobr><br>".cross_project_links($host);
357
        }
358
    }
359
    echo "
360
        </td>
361
    ";
362
    if ($private) {
363
        echo "<td>$host->domain_name</td>\n";
364
        if ($any_product_name) {
365
            echo "<td>$host->product_name</td>\n";
366
        }
367
        echo "<td>$host->venue</td>\n";
368
    } else {
369
        echo "<td>$i</td>\n";
370
        if ($show_owner) {
371
            if ($anonymous) {
372
                echo "<td>".tra("Anonymous")."</td>\n";
373
            } else {
374
                echo "<td>", user_links($user, BADGE_HEIGHT_MEDIUM), "</td>\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user does not seem to be defined for all execution paths leading up to this point.
Loading history...
375
            }
376
        }
377
    }
378
    $misc = json_decode($host->misc);
379
    if ($show_owner) {
380
        // This is used in the "top computers" display
381
        //
382
        if (!NO_STATS) {
383
            printf("
384
                <td align=right>%s</td>
385
                <td align=right>%s</td>",
386
                format_credit($host->expavg_credit),
387
                format_credit_large($host->total_credit)
388
            );
389
        }
390
        printf("
391
            <td>%s</td>
392
            <td>%s</td>
393
            <td>%s</td>
394
            <td>%s <br> %s</td>",
395
            boinc_version($misc),
396
            cpu_desc($host),
397
            gpu_desc($misc),
398
            $host->os_name, $host->os_version
399
        );
400
    } else {
401
        // This is used to show the computers of a given user
402
        //
403
        if (!NO_STATS) {
404
            printf("
405
                <td align=right>%s</td>
406
                <td align=right>%s</td>",
407
                format_credit($host->expavg_credit),
408
                format_credit_large($host->total_credit)
409
            );
410
        }
411
        printf("
412
            <td>%s</td>
413
            <td>%s</td>
414
            <td>%s</td>
415
            <td>%s<br><small>%s</small></td>
416
            <td>%s</td>
417
            ",
418
            boinc_version($misc),
419
            cpu_desc($host),
420
            gpu_desc($misc),
421
            $host->os_name, $host->os_version,
422
            sched_log_link($host->rpc_time)
423
        );
424
    }
425
426
    echo "</tr>\n";
427
}
428
429
// Logic for deciding whether two host records might actually
430
// be the same machine, based on CPU info
431
//
432
// p_vendor is typically either AuthenticAMD or GenuineIntel.
433
// Over time we've changed the contents of p_model.
434
// Some examples:
435
// Intel(R) Core(TM)2 Duo CPU  E7300  @ 2.66GHz [Family 6 Model 23 Stepping 6]
436
// AMD Athlon(tm) II X2 250 Processor [Family 16 Model 6 Stepping 3]
437
// Intel(R) Xeon(R) CPU X5650 @ 2.67GHz [x86 Family 6 Model 44 Stepping 2]
438
// Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz [Intel64 Family 6 Model 42 Stepping 7]
439
//
440
// in the last 2 cases, let's call x86 and Intel64 the "architecture"
441
//
442
// so, here's the policy:
443
//
444
// if p_ncpus different, return false
445
// if p_vendor different, return false
446
// if both have family/model/stepping info
447
//    if info disagrees, return false
448
//    if both have GHz info, and they disagree, return false
449
//    if both have architecture, and they disagree, return false
450
//    return true
451
// if p_model different, return false
452
// return true
453
//
454
455
// parse p_model to produce the following structure:
456
// x->speed     "3.00GHz" etc. or null
457
// x->arch      "x86" etc. or null
458
// x->info      "Family 6 Model 23 Stepping 6" etc. or null
459
//
460
function parse_model($model) {
461
    $y = explode(" ", $model);
462
    $x = new StdClass;
463
    $x->speed = null;
464
    $x->arch = null;
465
    $x->info = null;
466
    foreach ($y as $z) {
467
        if (strstr($z, "GHz")) $x->speed = $z;
468
        if (strstr($z, "MHz")) $x->speed = $z;
469
    }
470
    $pos1 = strpos($model, '[');
471
    if ($pos1 === false) return $x;
472
    $pos2 = strpos($model, ']');
473
    if ($pos2 === false) return $x;
474
    $a = substr($model, $pos1+1, $pos2-$pos1-1);
475
    $y = explode(" ", $a);
476
    if (count($y) == 0) return $x;
477
    if ($y[0] == "Family") {
478
        $x->info = $a;
479
    } else {
480
        $x->arch = $y[0];
481
        $x->info = substr($a, strlen($y[0])+1);
482
    }
483
    return $x;
484
}
485
486
function cpus_compatible($host1, $host2) {
487
    if ($host1->p_ncpus != $host2->p_ncpus) return false;
488
    if ($host1->p_vendor != $host2->p_vendor) return false;
489
    $x1 = parse_model($host1->p_model);
490
    $x2 = parse_model($host2->p_model);
491
    if ($x1->info && $x2->info) {
492
        if ($x1->info != $x2->info) return false;
493
        if ($x1->speed && $x2->speed) {
494
            if ($x1->speed != $x2->speed) return false;
495
        }
496
        if ($x1->arch && $x2->arch) {
497
            if ($x1->arch != $x2->arch) return false;
498
        }
499
        return true;
500
    }
501
    if ($host1->p_model != $host2->p_model) return false;
502
    return true;
503
}
504
505
// does one host strictly precede the other?
506
//
507
function times_disjoint($host1, $host2) {
508
    if ($host1->rpc_time < $host2->create_time) return true;
509
    if ($host2->rpc_time < $host1->create_time) return true;
510
    return false;
511
}
512
513
function os_compatible($host1, $host2) {
514
    if (strstr($host1->os_name, "Windows") && strstr($host2->os_name, "Windows")) return true;
515
    if (strstr($host1->os_name, "Linux") && strstr($host2->os_name, "Linux")) return true;
516
    if (strstr($host1->os_name, "Darwin") && strstr($host2->os_name, "Darwin")) return true;
517
    if (strstr($host1->os_name, "SunOS") && strstr($host2->os_name, "SunOS")) return true;
518
    if ($host1->os_name == $host2->os_name) return true;
519
    return false;
520
}
521
522
// Return true if it's possible that the two host records
523
// correspond to the same host
524
// NOTE: the cheat-proofing comes from checking
525
// that their time intervals are disjoint.
526
// So the CPU/OS checks don't have to be very strict.
527
//
528
function hosts_compatible($host1, $host2, $show_detail) {
529
    // A host is "new" if it has no credit and no results.
530
    // Skip disjoint-time check if one host or other is new
531
    //
532
    $new1 = !$host1->total_credit && !host_nresults($host1);
533
    $new2 = !$host2->total_credit && !host_nresults($host2);
534
    if (!$new1 && !$new2) {
535
        if (!times_disjoint($host1, $host2)) {
536
            if ($show_detail) {
537
                $c1 = date_str($host1->create_time);
538
                $r1 = date_str($host1->rpc_time);
539
                $c2 = date_str($host2->create_time);
540
                $r2 = date_str($host2->rpc_time);
541
                echo "<br>".tra("Host %1 has overlapping lifetime:", $host2->id)." ($c1 - $r1), ($c2 - $r2)";
542
            }
543
            return false;
544
        }
545
    }
546
    if (!os_compatible($host1, $host2)) {
547
        if ($show_detail) {
548
            echo "<br>".tra("Host %1 has an incompatible OS:", $host2->id)." ($host1->os_name, $host2->os_name)\n";
549
        }
550
        return false;
551
    }
552
    if (!cpus_compatible($host1, $host2)) {
553
        if ($show_detail) {
554
            echo "<br>".tra("Host %1 has an incompatible CPU:", $host2->id)." ($host1->p_vendor $host1->p_model, $host2->p_vendor $host2->p_model)\n";
555
        }
556
        return false;
557
    }
558
    return true;
559
}
560
561
// recompute host's average credit by scanning results.
562
// Could be expensive if lots of results!
563
//
564
function host_update_credit($hostid) {
565
    $total = 0;
566
    $avg = 0;
567
    $avg_time = 0;
568
569
    $results = BoincResult::enum("hostid=$hostid order by received_time");
570
    foreach($results as $result) {
571
        if ($result->granted_credit <= 0) continue;
572
        $total += $result->granted_credit;
573
574
        update_average(
575
            $result->received_time,
576
            $result->sent_time,
577
            $result->granted_credit,
578
            $avg,
579
            $avg_time
580
        );
581
582
        //echo "<br>$avg\n";
583
    }
584
585
    // do a final decay
586
    //
587
    $now = time();
588
    update_average(now, 0, 0, $avg, $avg_time);
589
590
    $host = new BoincHost();
591
    $host->id = hostid;
592
    $host->update("total_credit=$total, expavg_credit=$avg, expavg_time=$now");
593
}
594
595
// decay a host's average credit
596
//
597
function host_decay_credit($host) {
598
    $avg = $host->expavg_credit;
599
    $avg_time = $host->expavg_time;
600
    $now = time();
601
    update_average($now, 0, 0, $avg, $avg_time);
602
    $host->update("expavg_credit=$avg, expavg_time=$now");
603
}
604
605
// if the host hasn't received new credit for ndays,
606
// decay its average and return true
607
//
608
function host_inactive_ndays($host, $ndays) {
609
    $diff = time() - $host->expavg_time;
610
    if ($diff > $ndays*86400) {
611
        host_decay_credit($host);
612
        return true;
613
    }
614
    return false;
615
}
616
617
// invariant: old_host.create_time < new_host.create_time
618
//
619
function merge_hosts($old_host, $new_host) {
620
    if ($old_host->id == $new_host->id) {
621
        return tra("same host");
622
    }
623
    if (!hosts_compatible($old_host, $new_host, false)) {
624
        return tra("Can't merge host %1 into %2 - they're incompatible", $old_host->id, $new_host->id);
625
    }
626
627
    echo "<br>".tra("Merging host %1 into host %2", $old_host->id, $new_host->id)."\n";
628
629
    // decay the average credit of both hosts
630
    //
631
    $now = time();
632
    update_average($now, 0, 0, $old_host->expavg_credit, $old_host->expavg_time);
633
    update_average($now, 0, 0, $new_host->expavg_credit, $new_host->expavg_time);
634
635
    // update the database:
636
    // - add credit from old to new host
637
    // - change results to refer to new host
638
    // - put old host in "zombie" state (userid=0, rpc_seqno=new host ID)
639
    //
640
    $total_credit = $old_host->total_credit + $new_host->total_credit;
641
    $recent_credit = $old_host->expavg_credit + $new_host->expavg_credit;
642
    $result = $new_host->update("total_credit=$total_credit, expavg_credit=$recent_credit, expavg_time=$now");
643
    if (!$result) {
644
        return tra("Couldn't update credit of new computer");
645
    }
646
    $result = BoincResult::update_aux("hostid=$new_host->id where hostid=$old_host->id");
647
    if (!$result) {
648
        return tra("Couldn't update results");
649
    }
650
651
    $result = $old_host->update("total_credit=0, expavg_credit=0, userid=0, rpc_seqno=$new_host->id");
652
    if (!$result) {
653
        return tra("Couldn't retire old computer");
654
    }
655
    echo "<br>".tra("Retired old computer %1", $old_host->id)."\n";
656
    return 0;
657
}
658
659
//////////////// helper functions for hosts_user.php ////////////////
660
661
function link_url($sort, $rev, $show_all) {
662
    global $userid;
663
    $x = $userid ? "&userid=$userid":"";
664
    return "hosts_user.php?sort=$sort&rev=$rev&show_all=$show_all$x";
665
}
666
667
function link_url_rev($actual_sort, $sort, $rev, $show_all) {
668
    if ($actual_sort == $sort) {
669
        $rev = 1 - $rev;
670
    }
671
    return link_url($sort, $rev, $show_all);
672
}
673
674
function more_or_less($sort, $rev, $show_all) {
675
    echo "<p>";
676
    if ($show_all) {
677
        $url = link_url($sort, $rev, 0);
678
        echo tra("Show:")." ".tra("All computers")." &middot; <a href=$url>".tra("Only computers active in past 30 days")."</a>";
679
    } else {
680
        $url = link_url($sort, $rev, 1);
681
        echo tra("Show:")." <a href=$url>".tra("All computers")."</a> &middot; ".tra("Only computers active in past 30 days");
682
    }
683
    echo "<p>";
684
}
685
686
function user_host_table_start(
687
    $private, $sort, $rev, $show_all, $any_product_name
0 ignored issues
show
Coding Style introduced by
Multi-line function declarations must define one parameter per line
Loading history...
688
) {
689
    start_table('table-striped');
690
    $x = array();
691
    $a = array();
692
693
    $url = link_url_rev($sort, "id", $rev, $show_all);
694
    $x[] = "<a href=$url>".tra("Computer ID")."</a>";
695
    $a[] = '';
696
697
    if ($private) {
698
        $url = link_url_rev($sort, "name", $rev, $show_all);
699
        $x[] = "<a href=$url>".tra("Name")."</a>";
700
        $a[] = null;
701
        $url = link_url_rev($sort, "venue", $rev, $show_all);
702
        if ($any_product_name) {
703
            $x[] = tra("Model");
704
            $a[] = null;
705
        }
706
        $x[] = "<a href=$url>".tra("Location")."</a>";
707
        $a[] = null;
708
    } else {
709
        $x[] = tra("Rank");
710
        $a[] = null;
711
    }
712
    if (!NO_STATS) {
713
        $url = link_url_rev($sort, "expavg_credit", $rev, $show_all);
714
        $x[] = "<a href=$url>".tra("Avg. credit")."</a>";
715
        $a[] = ALIGN_RIGHT;
716
        $url = link_url_rev($sort, "total_credit", $rev, $show_all);
717
        $x[] = "<a href=$url>".tra("Total credit")."</a>";
718
        $a[] = ALIGN_RIGHT;
719
    }
720
    $x[] = tra("BOINC<br>version");
721
    $a[] = null;
722
    $url = link_url_rev($sort, "cpu", $rev, $show_all);
723
    $x[] = "<a href=$url>".tra("CPU")."</a>";
724
    $a[] = null;
725
    $x[] = tra("GPU");
726
    $a[] = null;
727
    $url = link_url_rev($sort, "os", $rev, $show_all);
728
    $x[] = "<a href=$url>".tra("Operating System")."</a>";
729
    $a[] = null;
730
    $url = link_url_rev($sort, "rpc_time", $rev, $show_all);
731
    $x[] = "<a href=$url>".tra("Last contact")."</a>";
732
    $a[] = null;
733
    row_heading_array($x, $a, "bg-default");
734
}
735
736
function show_user_hosts($userid, $private, $show_all, $sort, $rev) {
737
    $desc = false;  // whether the sort order's default is decreasing
738
    switch ($sort) {
739
    case "total_credit": $sort_clause = "total_credit"; $desc = true; break;
740
    case "expavg_credit": $sort_clause = "expavg_credit"; $desc = true; break;
741
    case "name": $sort_clause = "domain_name"; break;
742
    case "id": $sort_clause = "id"; break;
743
    case "cpu": $sort_clause = "p_vendor"; break;
744
    case "os": $sort_clause = "os_name"; break;
745
    case "venue": $sort_clause = "venue"; break;
746
    default:
0 ignored issues
show
Coding Style introduced by
DEFAULT keyword must be indented 4 spaces from SWITCH keyword
Loading history...
Coding Style introduced by
DEFAULT case must have a breaking statement
Loading history...
747
        // default value -- sort by RPC time
748
        $sort = "rpc_time";
749
        $sort_clause = "rpc_time";
750
        $desc = true;
751
    }
752
753
    if ($rev != $desc) {
754
        $sort_clause .= " desc";
755
    }
756
    more_or_less($sort, $rev, $show_all);
757
758
    $now = time();
759
    $old_hosts=0;
760
    $i = 1;
761
    $hosts = BoincHost::enum("userid=$userid order by $sort_clause limit 100");
762
    $any_product_name = false;
763
    foreach ($hosts as $host) {
764
        if ($host->product_name) {
765
            $any_product_name = true;
766
            break;
767
        }
768
    }
769
    user_host_table_start($private, $sort, $rev, $show_all, $any_product_name);
770
    foreach ($hosts as $host) {
771
        $is_old=false;
772
        if (($now - $host->rpc_time) > 30*86400) {
773
            $is_old=true;
774
            $old_hosts++;
775
        }
776
        if (!$show_all && $is_old) continue;
777
        show_host_row($host, $i, $private, false, $any_product_name);
778
        $i++;
779
    }
780
    end_table();
781
782
    if ($old_hosts>0) {
783
        more_or_less($sort, $rev, $show_all);
784
    }
785
786
    if ($private) {
787
        echo "
788
            <a href=merge_by_name.php>".tra("Merge computers by name")."</a>
789
        ";
790
    }
791
}
792
793
// remove user-specific info from a user's hosts
794
//
795
function anonymize_hosts($user) {
796
    $hosts = BoincHost::enum("userid=$user->id");
797
    foreach ($hosts as $h) {
798
        $h->update("domain_name='deleted', last_ip_addr=''");
799
    }
800
}
801
802
803
?>
804