Passed
Pull Request — master (#6667)
by David
18:09 queued 07:13
created

vbox_desc()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 8
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 2
nop 1
dl 0
loc 8
rs 10
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
    row2(tra("BOINC version"), boinc_version($misc));
129
    $x = $host->m_nbytes/GIGA;
130
    $y = round($x, 2);
131
    row2(tra("Memory"), tra("%1 GB", $y));
132
    if ($host->m_cache > 0) {
133
        $x = $host->m_cache/KILO;
134
        $y = round($x, 2);
135
        row2(tra("Cache"), tra("%1 KB", $y));
136
    }
137
138
    if ($user) {
139
        $x = $host->m_swap/GIGA;
140
        $y = round($x, 2);
141
        row2(tra("Swap space"), tra("%1 GB", $y));
142
        $x = $host->d_total/GIGA;
143
        $y = round($x, 2);
144
        row2(tra("Total disk space"), tra("%1 GB", $y));
145
        $x = $host->d_free/GIGA;
146
        $y = round($x, 2);
147
        row2(tra("Free Disk Space"), tra("%1 GB", $y));
148
    }
149
    $x = $host->p_fpops/1e9;
150
    $y = round($x, 2);
151
    row2(tra("Measured floating point speed"), tra("%1 billion ops/sec", $y));
152
    $x = $host->p_iops/1e9;
153
    $y = round($x, 2);
154
    row2(tra("Measured integer speed"), tra("%1 billion ops/sec", $y));
155
    $x = $host->n_bwup/MEGA;
156
    $y = round($x, 2);
157
    if ($y > 0) {
158
        row2(tra("Average upload rate"), tra("%1 MB/sec", $y));
159
    } else {
160
        row2(tra("Average upload rate"), tra("Unknown"));
161
    }
162
    $x = $host->n_bwdown/MEGA;
163
    $y = round($x, 2);
164
    if ($y > 0) {
165
        row2(tra("Average download rate"), tra("%1 MB/sec", $y));
166
    } else {
167
        row2(tra("Average download rate"), tra("Unknown"));
168
    }
169
    $x = $host->avg_turnaround/86400;
170
    if (!NO_COMPUTING) {
171
        row2(tra("Average turnaround time"), tra("%1 days", round($x, 2)));
172
        row2(tra("Application details"),
173
            "<a href=host_app_versions.php?hostid=$host->id>".tra("Show")."</a>"
174
        );
175
        $show_results = parse_bool($config, "show_results");
176
        if ($show_results) {
177
            $nresults = host_nresults($host);
178
            if ($nresults) {
179
                $results = "<a href=results.php?hostid=$host->id>$nresults</a>";
180
            } else {
181
                $results = "0";
182
            }
183
            row2(tra("Tasks"), $results);
184
        }
185
        if (defined('BATCH_ACCEL') && BATCH_ACCEL) {
186
            row2('Low turnaround time?',
187
                $host->error_rate?'yes':'no'
188
            );
189
        }
190
    }
191
192
    if ($user) {
193
        row2(tra("Number of times client has contacted server"), $host->rpc_seqno);
194
        row2(tra("Last time contacted server"), sched_log_link($host->rpc_time));
195
        row2(tra("Fraction of time BOINC is running"), number_format(100*$host->on_frac, 2)."%");
196
        if ($host->connected_frac > 0) {
197
            row2(tra("While BOINC is running, fraction of time computer has an Internet connection"), number_format(100*$host->connected_frac, 2)."%");
198
        }
199
        row2(tra("While BOINC is running, fraction of time computing is allowed"), number_format(100*$host->active_frac, 2)."%");
200
        row2(tra("While is BOINC running, fraction of time GPU computing is allowed"), number_format(100*$host->gpu_active_frac, 2)."%");
201
        if ($host->cpu_efficiency) {
202
            row2(tra("Average CPU efficiency"), $host->cpu_efficiency);
203
        }
204
        if (!NO_COMPUTING) {
205
            if ($host->duration_correction_factor) {
206
                row2(tra("Task duration correction factor"), $host->duration_correction_factor);
207
            }
208
        }
209
        row2(tra("Location"), location_form($host));
210
        if ($show_results && $nresults == 0) {
0 ignored issues
show
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...
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...
211
            $x = " &middot; <a href=host_delete.php?hostid=$host->id".url_tokens($user->authenticator).">".tra("Delete this computer")."</a> ";
212
        } else {
213
            $x = "";
214
        }
215
        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");
216
    } else {
217
        row2(tra("Number of times client has contacted server"), $host->rpc_seqno);
218
        row2(tra("Last contact"), date_str($host->rpc_time));
219
    }
220
    echo "</table>\n";
221
222
}
223
224
// the following is used for list of top hosts
225
//
226
function top_host_table_start($sort_by) {
227
    global $host_sites;
228
    shuffle($host_sites);
229
    start_table('table-striped');
230
    $x = array(
231
        tra("Info"),
232
        tra("Rank"),
233
        tra("Owner"),
234
    );
235
    if (!NO_STATS) {
236
        if ($sort_by == 'total_credit') {
237
            $x[] = "<a href=top_hosts.php?sort_by=expavg_credit>".tra("Avg. credit")."</a>";
238
            $x[] = tra("Total credit");
239
        } else {
240
            $x[] = tra("Recent average credit");
241
            $x[] = "<a href=top_hosts.php?sort_by=total_credit>".tra("Total credit")."</a>";
242
        }
243
    }
244
    $x[] = tra("BOINC version");
245
    $x[] = tra("CPU");
246
    $x[] = tra("GPU");
247
    $x[] = tra("Operating system");
248
    $s = 'style="text-align:right;"';
249
    $a = array("", "", "", $s, $s, "", "", "", "");
250
    row_heading_array($x, $a, "bg-default");
251
}
252
253
function host_nresults($host) {
254
    return BoincResult::count("hostid=$host->id");
255
}
256
257
function vbox_desc($misc) {
258
    if (empty($misc->vbox)) return '---';
259
    $v = $misc->vbox;
260
    return sprintf(
261
        'Virtualbox %s<br>HW acceleration: %s<br>Enabled: %s',
262
        $v->version,
263
        $v->hw_accel?'yes':'no',
264
        $v->hw_accel_enabled?'yes':'no'
265
    );
266
}
267
268
function docker_desc($misc) {
269
    if (empty($misc->docker)) return '---';
270
    $d = $misc->docker;
271
    $x = sprintf('%s version %s',
272
        $d->type==1?"Docker":"Podman",
273
        $d->version
274
    );
275
    if (!empty($d->wsl_distro)) {
276
        $x .= sprintf(
277
            '<br>WSL distro: %s ver %d',
278
            $d->wsl_distro, $d->boinc_buda_runner_version
279
        );
280
    }
281
    if (!empty($misc->config)) {
282
        $c = $misc->config;
283
        if (!empty($c->dont_use_wsl)) {
284
            $x .= "Config: don't use WSL";
285
        }
286
        if (!empty($c->dont_use_docker)) {
287
            $x .= "Config: don't use Docker";
288
        }
289
    }
290
    return $x;
291
}
292
293
294
// return a human-readable version of the GPU info
295
//
296
function gpu_desc($misc) {
297
    if (empty($misc->gpus)) return '---';
298
    $gpus = [];
299
    foreach ($misc->gpus as $g) {
300
        $x = sprintf(
301
            '%d %s; %dMB RAM',
302
            $g->count, $g->model, $g->ram_mb
303
        );
304
        if (!empty($g->driver_version)) {
305
            $x .= "; Driver: $g->driver_version";
306
        }
307
        if (!empty($g->opencl_version)) {
308
            $x .= "; OpenCL: $g->opencl_version";
309
        }
310
        $gpus[] = $x;
311
    }
312
    return implode('<br>', $gpus);
313
}
314
315
// Given the same string as above, return the BOINC version
316
//
317
function boinc_version($misc) {
318
    $x = $misc->client_version;
319
    if (!empty($misc->client_brand)) {
320
        $x .= " ($misc->client_brand)";
321
    }
322
    return $x;
323
}
324
325
function cpu_desc($host) {
326
    return "$host->p_vendor<br>$host->p_model<br>".tra("(%1 cores)", $host->p_ncpus)."\n";
327
}
328
329
// If private is true, we're showing the host to its owner,
330
// so it's OK to show the domain name etc.
331
// If private is false, show the owner's name only if they've given permission
332
//
333
function show_host_row($host, $i, $private, $show_owner, $any_product_name) {
334
    $anonymous = false;
335
    if (!$private) {
336
        if ($show_owner) {
337
            $user = BoincUser::lookup_id($host->userid);
338
            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...
339
            } else {
340
                $anonymous = true;
341
            }
342
        }
343
    }
344
    echo "<tr><td>ID: $host->id
345
        <br><a href=show_host_detail.php?hostid=$host->id>".tra("Details")."</a>
346
    ";
347
    if (!NO_COMPUTING) {
348
        echo "
349
        | <a href=results.php?hostid=$host->id>".tra("Tasks")."</a>
350
        ";
351
    }
352
    if (!NO_STATS) {
353
        if (!$anonymous) {
354
            echo "
355
                <br><nobr><small>".tra("Cross-project stats:")."</small></nobr><br>".cross_project_links($host);
356
        }
357
    }
358
    echo "
359
        </td>
360
    ";
361
    if ($private) {
362
        echo "<td>$host->domain_name</td>\n";
363
        if ($any_product_name) {
364
            echo "<td>$host->product_name</td>\n";
365
        }
366
        echo "<td>$host->venue</td>\n";
367
    } else {
368
        echo "<td>$i</td>\n";
369
        if ($show_owner) {
370
            if ($anonymous) {
371
                echo "<td>".tra("Anonymous")."</td>\n";
372
            } else {
373
                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...
374
            }
375
        }
376
    }
377
    $misc = json_decode($host->misc);
378
    if ($show_owner) {
379
        // This is used in the "top computers" display
380
        //
381
        if (!NO_STATS) {
382
            printf("
383
                <td align=right>%s</td>
384
                <td align=right>%s</td>",
385
                format_credit($host->expavg_credit),
386
                format_credit_large($host->total_credit)
387
            );
388
        }
389
        printf("
390
            <td>%s</td>
391
            <td>%s</td>
392
            <td>%s</td>
393
            <td>%s <br> %s</td>",
394
            boinc_version($misc),
395
            cpu_desc($host),
396
            gpu_desc($misc),
397
            $host->os_name, $host->os_version
398
        );
399
    } else {
400
        // This is used to show the computers of a given user
401
        //
402
        if (!NO_STATS) {
403
            printf("
404
                <td align=right>%s</td>
405
                <td align=right>%s</td>",
406
                format_credit($host->expavg_credit),
407
                format_credit_large($host->total_credit)
408
            );
409
        }
410
        printf("
411
            <td>%s</td>
412
            <td>%s</td>
413
            <td>%s</td>
414
            <td>%s<br><small>%s</small></td>
415
            <td>%s</td>
416
            ",
417
            boinc_version($misc),
418
            cpu_desc($host),
419
            gpu_desc($misc),
420
            $host->os_name, $host->os_version,
421
            sched_log_link($host->rpc_time)
422
        );
423
    }
424
425
    echo "</tr>\n";
426
}
427
428
// Logic for deciding whether two host records might actually
429
// be the same machine, based on CPU info
430
//
431
// p_vendor is typically either AuthenticAMD or GenuineIntel.
432
// Over time we've changed the contents of p_model.
433
// Some examples:
434
// Intel(R) Core(TM)2 Duo CPU  E7300  @ 2.66GHz [Family 6 Model 23 Stepping 6]
435
// AMD Athlon(tm) II X2 250 Processor [Family 16 Model 6 Stepping 3]
436
// Intel(R) Xeon(R) CPU X5650 @ 2.67GHz [x86 Family 6 Model 44 Stepping 2]
437
// Intel(R) Core(TM) i5-2500K CPU @ 3.30GHz [Intel64 Family 6 Model 42 Stepping 7]
438
//
439
// in the last 2 cases, let's call x86 and Intel64 the "architecture"
440
//
441
// so, here's the policy:
442
//
443
// if p_ncpus different, return false
444
// if p_vendor different, return false
445
// if both have family/model/stepping info
446
//    if info disagrees, return false
447
//    if both have GHz info, and they disagree, return false
448
//    if both have architecture, and they disagree, return false
449
//    return true
450
// if p_model different, return false
451
// return true
452
//
453
454
// parse p_model to produce the following structure:
455
// x->speed     "3.00GHz" etc. or null
456
// x->arch      "x86" etc. or null
457
// x->info      "Family 6 Model 23 Stepping 6" etc. or null
458
//
459
function parse_model($model) {
460
    $y = explode(" ", $model);
461
    $x = new StdClass;
462
    $x->speed = null;
463
    $x->arch = null;
464
    $x->info = null;
465
    foreach ($y as $z) {
466
        if (strstr($z, "GHz")) $x->speed = $z;
467
        if (strstr($z, "MHz")) $x->speed = $z;
468
    }
469
    $pos1 = strpos($model, '[');
470
    if ($pos1 === false) return $x;
471
    $pos2 = strpos($model, ']');
472
    if ($pos2 === false) return $x;
473
    $a = substr($model, $pos1+1, $pos2-$pos1-1);
474
    $y = explode(" ", $a);
475
    if (count($y) == 0) return $x;
476
    if ($y[0] == "Family") {
477
        $x->info = $a;
478
    } else {
479
        $x->arch = $y[0];
480
        $x->info = substr($a, strlen($y[0])+1);
481
    }
482
    return $x;
483
}
484
485
function cpus_compatible($host1, $host2) {
486
    if ($host1->p_ncpus != $host2->p_ncpus) return false;
487
    if ($host1->p_vendor != $host2->p_vendor) return false;
488
    $x1 = parse_model($host1->p_model);
489
    $x2 = parse_model($host2->p_model);
490
    if ($x1->info && $x2->info) {
491
        if ($x1->info != $x2->info) return false;
492
        if ($x1->speed && $x2->speed) {
493
            if ($x1->speed != $x2->speed) return false;
494
        }
495
        if ($x1->arch && $x2->arch) {
496
            if ($x1->arch != $x2->arch) return false;
497
        }
498
        return true;
499
    }
500
    if ($host1->p_model != $host2->p_model) return false;
501
    return true;
502
}
503
504
// does one host strictly precede the other?
505
//
506
function times_disjoint($host1, $host2) {
507
    if ($host1->rpc_time < $host2->create_time) return true;
508
    if ($host2->rpc_time < $host1->create_time) return true;
509
    return false;
510
}
511
512
function os_compatible($host1, $host2) {
513
    if (strstr($host1->os_name, "Windows") && strstr($host2->os_name, "Windows")) return true;
514
    if (strstr($host1->os_name, "Linux") && strstr($host2->os_name, "Linux")) return true;
515
    if (strstr($host1->os_name, "Darwin") && strstr($host2->os_name, "Darwin")) return true;
516
    if (strstr($host1->os_name, "SunOS") && strstr($host2->os_name, "SunOS")) return true;
517
    if ($host1->os_name == $host2->os_name) return true;
518
    return false;
519
}
520
521
// Return true if it's possible that the two host records
522
// correspond to the same host
523
// NOTE: the cheat-proofing comes from checking
524
// that their time intervals are disjoint.
525
// So the CPU/OS checks don't have to be very strict.
526
//
527
function hosts_compatible($host1, $host2, $show_detail) {
528
    // A host is "new" if it has no credit and no results.
529
    // Skip disjoint-time check if one host or other is new
530
    //
531
    $new1 = !$host1->total_credit && !host_nresults($host1);
532
    $new2 = !$host2->total_credit && !host_nresults($host2);
533
    if (!$new1 && !$new2) {
534
        if (!times_disjoint($host1, $host2)) {
535
            if ($show_detail) {
536
                $c1 = date_str($host1->create_time);
537
                $r1 = date_str($host1->rpc_time);
538
                $c2 = date_str($host2->create_time);
539
                $r2 = date_str($host2->rpc_time);
540
                echo "<br>".tra("Host %1 has overlapping lifetime:", $host2->id)." ($c1 - $r1), ($c2 - $r2)";
541
            }
542
            return false;
543
        }
544
    }
545
    if (!os_compatible($host1, $host2)) {
546
        if ($show_detail) {
547
            echo "<br>".tra("Host %1 has an incompatible OS:", $host2->id)." ($host1->os_name, $host2->os_name)\n";
548
        }
549
        return false;
550
    }
551
    if (!cpus_compatible($host1, $host2)) {
552
        if ($show_detail) {
553
            echo "<br>".tra("Host %1 has an incompatible CPU:", $host2->id)." ($host1->p_vendor $host1->p_model, $host2->p_vendor $host2->p_model)\n";
554
        }
555
        return false;
556
    }
557
    return true;
558
}
559
560
// recompute host's average credit by scanning results.
561
// Could be expensive if lots of results!
562
//
563
function host_update_credit($hostid) {
564
    $total = 0;
565
    $avg = 0;
566
    $avg_time = 0;
567
568
    $results = BoincResult::enum("hostid=$hostid order by received_time");
569
    foreach($results as $result) {
570
        if ($result->granted_credit <= 0) continue;
571
        $total += $result->granted_credit;
572
573
        update_average(
574
            $result->received_time,
575
            $result->sent_time,
576
            $result->granted_credit,
577
            $avg,
578
            $avg_time
579
        );
580
581
        //echo "<br>$avg\n";
582
    }
583
584
    // do a final decay
585
    //
586
    $now = time();
587
    update_average(now, 0, 0, $avg, $avg_time);
588
589
    $host = new BoincHost();
590
    $host->id = hostid;
591
    $host->update("total_credit=$total, expavg_credit=$avg, expavg_time=$now");
592
}
593
594
// decay a host's average credit
595
//
596
function host_decay_credit($host) {
597
    $avg = $host->expavg_credit;
598
    $avg_time = $host->expavg_time;
599
    $now = time();
600
    update_average($now, 0, 0, $avg, $avg_time);
601
    $host->update("expavg_credit=$avg, expavg_time=$now");
602
}
603
604
// if the host hasn't received new credit for ndays,
605
// decay its average and return true
606
//
607
function host_inactive_ndays($host, $ndays) {
608
    $diff = time() - $host->expavg_time;
609
    if ($diff > $ndays*86400) {
610
        host_decay_credit($host);
611
        return true;
612
    }
613
    return false;
614
}
615
616
// invariant: old_host.create_time < new_host.create_time
617
//
618
function merge_hosts($old_host, $new_host) {
619
    if ($old_host->id == $new_host->id) {
620
        return tra("same host");
621
    }
622
    if (!hosts_compatible($old_host, $new_host, false)) {
623
        return tra("Can't merge host %1 into %2 - they're incompatible", $old_host->id, $new_host->id);
624
    }
625
626
    echo "<br>".tra("Merging host %1 into host %2", $old_host->id, $new_host->id)."\n";
627
628
    // decay the average credit of both hosts
629
    //
630
    $now = time();
631
    update_average($now, 0, 0, $old_host->expavg_credit, $old_host->expavg_time);
632
    update_average($now, 0, 0, $new_host->expavg_credit, $new_host->expavg_time);
633
634
    // update the database:
635
    // - add credit from old to new host
636
    // - change results to refer to new host
637
    // - put old host in "zombie" state (userid=0, rpc_seqno=new host ID)
638
    //
639
    $total_credit = $old_host->total_credit + $new_host->total_credit;
640
    $recent_credit = $old_host->expavg_credit + $new_host->expavg_credit;
641
    $result = $new_host->update("total_credit=$total_credit, expavg_credit=$recent_credit, expavg_time=$now");
642
    if (!$result) {
643
        return tra("Couldn't update credit of new computer");
644
    }
645
    $result = BoincResult::update_aux("hostid=$new_host->id where hostid=$old_host->id");
646
    if (!$result) {
647
        return tra("Couldn't update results");
648
    }
649
650
    $result = $old_host->update("total_credit=0, expavg_credit=0, userid=0, rpc_seqno=$new_host->id");
651
    if (!$result) {
652
        return tra("Couldn't retire old computer");
653
    }
654
    echo "<br>".tra("Retired old computer %1", $old_host->id)."\n";
655
    return 0;
656
}
657
658
//////////////// helper functions for hosts_user.php ////////////////
659
660
function link_url($sort, $rev, $show_all) {
661
    global $userid;
662
    $x = $userid ? "&userid=$userid":"";
663
    return "hosts_user.php?sort=$sort&rev=$rev&show_all=$show_all$x";
664
}
665
666
function link_url_rev($actual_sort, $sort, $rev, $show_all) {
667
    if ($actual_sort == $sort) {
668
        $rev = 1 - $rev;
669
    }
670
    return link_url($sort, $rev, $show_all);
671
}
672
673
function more_or_less($sort, $rev, $show_all) {
674
    echo "<p>";
675
    if ($show_all) {
676
        $url = link_url($sort, $rev, 0);
677
        echo tra("Show:")." ".tra("All computers")." &middot; <a href=$url>".tra("Only computers active in past 30 days")."</a>";
678
    } else {
679
        $url = link_url($sort, $rev, 1);
680
        echo tra("Show:")." <a href=$url>".tra("All computers")."</a> &middot; ".tra("Only computers active in past 30 days");
681
    }
682
    echo "<p>";
683
}
684
685
function user_host_table_start(
686
    $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...
687
) {
688
    start_table('table-striped');
689
    $x = array();
690
    $a = array();
691
692
    $url = link_url_rev($sort, "id", $rev, $show_all);
693
    $x[] = "<a href=$url>".tra("Computer ID")."</a>";
694
    $a[] = '';
695
696
    if ($private) {
697
        $url = link_url_rev($sort, "name", $rev, $show_all);
698
        $x[] = "<a href=$url>".tra("Name")."</a>";
699
        $a[] = null;
700
        $url = link_url_rev($sort, "venue", $rev, $show_all);
701
        if ($any_product_name) {
702
            $x[] = tra("Model");
703
            $a[] = null;
704
        }
705
        $x[] = "<a href=$url>".tra("Location")."</a>";
706
        $a[] = null;
707
    } else {
708
        $x[] = tra("Rank");
709
        $a[] = null;
710
    }
711
    if (!NO_STATS) {
712
        $url = link_url_rev($sort, "expavg_credit", $rev, $show_all);
713
        $x[] = "<a href=$url>".tra("Avg. credit")."</a>";
714
        $a[] = ALIGN_RIGHT;
715
        $url = link_url_rev($sort, "total_credit", $rev, $show_all);
716
        $x[] = "<a href=$url>".tra("Total credit")."</a>";
717
        $a[] = ALIGN_RIGHT;
718
    }
719
    $x[] = tra("BOINC<br>version");
720
    $a[] = null;
721
    $url = link_url_rev($sort, "cpu", $rev, $show_all);
722
    $x[] = "<a href=$url>".tra("CPU")."</a>";
723
    $a[] = null;
724
    $x[] = tra("GPU");
725
    $a[] = null;
726
    $url = link_url_rev($sort, "os", $rev, $show_all);
727
    $x[] = "<a href=$url>".tra("Operating System")."</a>";
728
    $a[] = null;
729
    $url = link_url_rev($sort, "rpc_time", $rev, $show_all);
730
    $x[] = "<a href=$url>".tra("Last contact")."</a>";
731
    $a[] = null;
732
    row_heading_array($x, $a, "bg-default");
733
}
734
735
function show_user_hosts($userid, $private, $show_all, $sort, $rev) {
736
    $desc = false;  // whether the sort order's default is decreasing
737
    switch ($sort) {
738
    case "total_credit": $sort_clause = "total_credit"; $desc = true; break;
739
    case "expavg_credit": $sort_clause = "expavg_credit"; $desc = true; break;
740
    case "name": $sort_clause = "domain_name"; break;
741
    case "id": $sort_clause = "id"; break;
742
    case "cpu": $sort_clause = "p_vendor"; break;
743
    case "os": $sort_clause = "os_name"; break;
744
    case "venue": $sort_clause = "venue"; break;
745
    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...
746
        // default value -- sort by RPC time
747
        $sort = "rpc_time";
748
        $sort_clause = "rpc_time";
749
        $desc = true;
750
    }
751
752
    if ($rev != $desc) {
753
        $sort_clause .= " desc";
754
    }
755
    more_or_less($sort, $rev, $show_all);
756
757
    $now = time();
758
    $old_hosts=0;
759
    $i = 1;
760
    $hosts = BoincHost::enum("userid=$userid order by $sort_clause limit 100");
761
    $any_product_name = false;
762
    foreach ($hosts as $host) {
763
        if ($host->product_name) {
764
            $any_product_name = true;
765
            break;
766
        }
767
    }
768
    user_host_table_start($private, $sort, $rev, $show_all, $any_product_name);
769
    foreach ($hosts as $host) {
770
        $is_old=false;
771
        if (($now - $host->rpc_time) > 30*86400) {
772
            $is_old=true;
773
            $old_hosts++;
774
        }
775
        if (!$show_all && $is_old) continue;
776
        show_host_row($host, $i, $private, false, $any_product_name);
777
        $i++;
778
    }
779
    end_table();
780
781
    if ($old_hosts>0) {
782
        more_or_less($sort, $rev, $show_all);
783
    }
784
785
    if ($private) {
786
        echo "
787
            <a href=merge_by_name.php>".tra("Merge computers by name")."</a>
788
        ";
789
    }
790
}
791
792
// remove user-specific info from a user's hosts
793
//
794
function anonymize_hosts($user) {
795
    $hosts = BoincHost::enum("userid=$user->id");
796
    foreach ($hosts as $h) {
797
        $h->update("domain_name='deleted', last_ip_addr=''");
798
    }
799
}
800
801
802
?>
803