Passed
Push — dpa_submit18 ( d7c32c )
by David
09:06
created

get_batches_params()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 11
rs 10
1
<?php
2
3
// This file is part of BOINC.
4
// http://boinc.berkeley.edu
5
// Copyright (C) 2024 University of California
6
//
7
// BOINC is free software; you can redistribute it and/or modify it
8
// under the terms of the GNU Lesser General Public License
9
// as published by the Free Software Foundation,
10
// either version 3 of the License, or (at your option) any later version.
11
//
12
// BOINC is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
// See the GNU Lesser General Public License for more details.
16
//
17
// You should have received a copy of the GNU Lesser General Public License
18
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
19
20
// web interface for remote job submission:
21
// - links to job-submission pages
22
// - Admin (if privileged user)
23
// - manage batches
24
//      view status, get output files, abort, retire
25
// - toggle 'use only my computers'
26
27
require_once("../inc/submit_db.inc");
28
require_once("../inc/util.inc");
29
require_once("../inc/result.inc");
30
require_once("../inc/submit_util.inc");
31
require_once("../project/project.inc");
32
33
display_errors();
34
35
define("PAGE_SIZE", 20);
36
37
function return_link() {
38
    echo "<p><a href=submit.php>Return to job submission page</a>\n";
39
}
40
41
// get params of in-progress batches; they might not be in progress anymore.
42
//
43
function get_batches_params($batches) {
44
    $b = [];
45
    foreach ($batches as $batch) {
46
        if ($batch->state == BATCH_STATE_IN_PROGRESS) {
47
            $wus = BoincWorkunit::enum("batch = $batch->id");
48
            $b[] = get_batch_params($batch, $wus);
49
        } else {
50
            $b[] = $batch;
51
        }
52
    }
53
    return $b;
54
}
55
56
function state_count($batches, $state) {
57
    $n = 0;
58
    foreach ($batches as $batch) {
59
        if ($batch->state == $state) $n++;
60
    }
61
    return $n;
62
}
63
64
function show_all_link($batches, $state, $limit, $user, $app) {
65
    $n = state_count($batches, $state);
66
    if ($n > $limit) {
67
        if ($user) $userid = $user->id;
68
        else $userid = 0;
69
        if ($app) $appid = $app->id;
70
        else $appid = 0;
71
72
        echo "Showing the most recent $limit of $n batches.
73
            <a href=submit.php?action=show_all&state=$state&userid=$userid&appid=$appid>Show all $n</a>
74
            <p>
75
        ";
76
    }
77
}
78
79
function show_in_progress($batches, $limit, $user, $app) {
80
    echo "<h3>Batches in progress</h3>\n";
81
    $first = true;
82
    $n = 0;
83
    foreach ($batches as $batch) {
84
        if ($batch->state != BATCH_STATE_IN_PROGRESS) continue;
85
        if ($limit && $n == $limit) break;
86
        $n++;
87
        if ($first) {
88
            $first = false;
89
            if ($limit) {
90
                show_all_link($batches, BATCH_STATE_IN_PROGRESS, $limit, $user, $app);
91
            }
92
            start_table('table-striped');
93
            table_header(
94
                "Name",
95
                "ID",
96
                "User",
97
                "App",
98
                "# jobs",
99
                "Progress",
100
                "Submitted"
101
                //"Logical end time<br><small>Determines priority</small>"
102
            );
103
        }
104
        $pct_done = (int)($batch->fraction_done*100);
105
        table_row(
106
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
107
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
108
            $batch->user_name,
109
            $batch->app_name,
110
            $batch->njobs,
111
            "$pct_done%",
112
            local_time_str($batch->create_time)
113
            //local_time_str($batch->logical_end_time)
114
        );
115
    }
116
    if ($first) {
117
        echo "<p>None.\n";
118
    } else {
119
        end_table();
120
    }
121
}
122
123
function show_complete($batches, $limit, $user, $app) {
124
    $first = true;
125
    $n = 0;
126
    foreach ($batches as $batch) {
127
        if ($batch->state != BATCH_STATE_COMPLETE) continue;
128
        if ($limit && $n == $limit) break;
129
        $n++;
130
        if ($first) {
131
            $first = false;
132
            echo "<h3>Completed batches</h3>\n";
133
            if ($limit) {
134
                show_all_link($batches, BATCH_STATE_COMPLETE, $limit, $user, $app);
135
            }
136
            form_start('submit.php', 'get');
137
            form_input_hidden('action', 'retire_multi');
138
            start_table('table-striped');
139
            table_header(
140
                "Name", "ID", "User", "App", "# Jobs", "Submitted", "Select"
141
            );
142
        }
143
        table_row(
144
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
145
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
146
            $batch->user_name,
147
            $batch->app_name,
148
            $batch->njobs,
149
            local_time_str($batch->create_time),
150
            sprintf('<input type=checkbox name=retire_%d>', $batch->id)
151
        );
152
    }
153
    if ($first) {
154
        echo "<p>No completed batches.\n";
155
    } else {
156
        end_table();
157
        form_submit('Retire selected batches');
158
    }
159
}
160
161
function show_aborted($batches, $limit, $user, $app) {
162
    $first = true;
163
    $n = 0;
164
    foreach ($batches as $batch) {
165
        if ($batch->state != BATCH_STATE_ABORTED) continue;
166
        if ($limit && $n == $limit) break;
167
        $n++;
168
        if ($first) {
169
            $first = false;
170
            echo "<h2>Aborted batches</h2>\n";
171
            if ($limit) {
172
                show_all_link($batches, BATCH_STATE_ABORTED, $limit, $user, $app);
173
            }
174
            start_table();
175
            table_header("name", "ID", "user", "app", "# jobs", "submitted");
176
        }
177
        table_row(
178
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->name</a>",
179
            "<a href=submit.php?action=query_batch&batch_id=$batch->id>$batch->id</a>",
180
            $batch->user_name,
181
            $batch->app_name,
182
            $batch->njobs,
183
            local_time_str($batch->create_time)
184
        );
185
    }
186
    if (!$first) {
187
        end_table();
188
    }
189
}
190
191
// fill in the app and user names in list of batches
192
//
193
function fill_in_app_and_user_names(&$batches) {
194
    foreach ($batches as $batch) {
195
        $app = BoincApp::lookup_id($batch->app_id);
196
        if ($app) {
197
            $batch->app_name = $app->name;
198
        } else {
199
            $batch->app_name = "unknown";
200
        }
201
        $user = BoincUser::lookup_id($batch->user_id);
202
        if ($user) {
203
            $batch->user_name = $user->name;
204
        } else {
205
            $batch->user_name = "missing user $batch->user_id";
206
        }
207
    }
208
}
209
210
// show a set of batches
211
//
212
function show_batches($batches, $limit, $user, $app) {
213
    fill_in_app_and_user_names($batches);
214
    $batches = get_batches_params($batches);
215
    show_in_progress($batches, $limit, $user, $app);
216
    show_complete($batches, $limit, $user, $app);
217
    show_aborted($batches, $limit, $user, $app);
218
}
219
220
// the job submission "home page":
221
// show the user's in-progress and completed batches,
222
// and a button for creating a new batch
223
//
224
function handle_main($user) {
225
    global $web_apps;
226
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
227
    if (!$user_submit) {
228
        error_page("Ask the project admins for permission to submit jobs");
229
    }
230
231
    page_head("Job submission");
232
233
    if (isset($web_apps) && $web_apps) {
234
        // show links to per-app job submission pages
235
        //
236
        echo "<h3>Submit jobs</h3>
237
            <ul>
238
        ";
239
        foreach ($web_apps as $appname => $web_app) {
240
            $appname = BoincDb::escape_string($appname);
241
            $app = BoincApp::lookup("name='$appname'");
242
            if (!$app) error_page("bad web app name: $appname");
243
            $usa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$app->id");
244
            if ($usa || $user_submit->submit_all) {
245
                echo "<li> <a href=$web_app->submit_url> $app->user_friendly_name </a>";
246
            }
247
        }
248
        echo "</ul>\n";
249
    }
250
251
    echo '<h3>Where your jobs run</h3>';
252
    if ($user->seti_id) {
253
        echo "<p>
254
            Jobs you submit can run only on your computers.
255
            <p>
256
        ";
257
        show_button(
258
            'submit.php?action=toggle_loc',
259
            'Allow them to run on any computer.'
260
        );
261
    } else {
262
        echo "<p>
263
            Jobs you submit can run on any computer.
264
            <p>
265
        ";
266
        show_button(
267
            'submit.php?action=toggle_loc',
268
            'Allow them to run only on your computers.'
269
        );
270
    }
271
272
    // show links to admin pages if relevant
273
    //
274
    $usas = BoincUserSubmitApp::enum("user_id=$user->id");
275
    $app_admin = false;
276
    foreach ($usas as $usa) {
277
        if ($usa->manage) {
278
            $app_admin = true;
279
            break;
280
        }
281
    }
282
    if ($user_submit->manage_all || $app_admin) {
283
        echo "<h3>Administer job submission</h3>\n";
284
        show_button('submit.php?action=admin', 'Administer');
285
    }
286
287
    $batches = BoincBatch::enum("user_id = $user->id order by id desc");
288
    get_batches_params($batches);
289
    show_batches($batches, PAGE_SIZE, $user, null);
290
291
    page_tail();
292
}
293
294
function handle_toggle_loc($user) {
295
    if ($user->seti_id) {
296
        $user->update('seti_id=0');
297
    } else {
298
        $user->update('seti_id=1');
299
    }
300
    handle_main($user);
301
}
302
303
// show links for everything the user has admin access to
304
//
305
function handle_admin($user) {
306
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
307
    if (!$user_submit) error_page('no access');
308
    page_head("Administer job submission");
309
    if ($user_submit->manage_all) {
310
        // user can administer all apps
311
        //
312
        echo "<li>All applications<br>
313
            <ul>
314
            <li> <a href=submit.php?action=admin_all>View all batches</a>
315
            <li> <a href=manage_project.php>Manage user permissions</a>
316
            </ul>
317
        ";
318
        $apps = BoincApp::enum("deprecated=0");
319
        foreach ($apps as $app) {
320
            echo "
321
                <li>$app->user_friendly_name<br>
322
                <ul>
323
                <li><a href=submit.php?action=admin_app&app_id=$app->id>View batches</a>
324
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=app_version_form>Manage app versions</a>
325
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=permissions_form>Manage user permissions</a>
326
                <li> <a href=manage_app.php?app_id=$app->id&amp;action=batches_form>Manage batches</a>
327
                </ul>
328
            ";
329
        }
330
    } else {
331
        // see if user can administer specific apps
332
        //
333
        $usas = BoincUserSubmitApp::enum("user_id=$user->id");
334
        foreach ($usas as $usa) {
335
            $app = BoincApp::lookup_id($usa->app_id);
336
            echo "<li>$app->user_friendly_name<br>
337
                <a href=submit.php?action=admin_app&app_id=$app->id>Batches</a>
338
            ";
339
            if ($usa->manage) {
340
                echo "&middot;
341
                    <a href=manage_app.php?app_id=$app->id&action=app_version_form>Versions</a>
342
                ";
343
            }
344
        }
345
    }
346
    echo "</ul>\n";
347
    page_tail();
348
}
349
350
function handle_admin_app($user) {
351
    $app_id = get_int("app_id");
352
    $app = BoincApp::lookup_id($app_id);
353
    if (!$app) error_page("no such app");
354
    if (!has_admin_access($user, $app_id)) {
355
        error_page('no access');
356
    }
357
358
    page_head("Administer batches for $app->user_friendly_name");
359
    $batches = BoincBatch::enum("app_id = $app_id order by id desc");
360
    show_batches($batches, PAGE_SIZE, null, $app);
361
    page_tail();
362
}
363
function handle_admin_all($user) {
364
    page_head("Administer batches (all apps)");
365
    $batches = BoincBatch::enum("true order by id desc");
366
    show_batches($batches, PAGE_SIZE, null, null);
367
    page_tail();
368
}
369
370
371
// show the statics of mem/disk usage of jobs in a batch
372
//
373
function handle_batch_stats($user) {
374
    $batch_id = get_int('batch_id');
375
    $batch = BoincBatch::lookup_id($batch_id);
376
    $results = BoincResult::enum("batch = $batch->id");
377
    page_head("Statistics for batch $batch_id");
378
    $n = 0;
379
    $wss_sum = 0;
380
    $swap_sum = 0;
381
    $disk_sum = 0;
382
    $wss_max = 0;
383
    $swap_max = 0;
384
    $disk_max = 0;
385
    foreach ($results as $r) {
386
        if ($r->outcome != RESULT_OUTCOME_SUCCESS) {
387
            continue;
388
        }
389
        // pre-7.3.16 clients don't report usage info
390
        //
391
        if ($r->peak_working_set_size == 0) {
392
            continue;
393
        }
394
        $n++;
395
        $wss_sum += $r->peak_working_set_size;
396
        if ($r->peak_working_set_size > $wss_max) {
397
            $wss_max = $r->peak_working_set_size;
398
        }
399
        $swap_sum += $r->peak_swap_size;
400
        if ($r->peak_swap_size > $swap_max) {
401
            $swap_max = $r->peak_swap_size;
402
        }
403
        $disk_sum += $r->peak_disk_usage;
404
        if ($r->peak_disk_usage > $disk_max) {
405
            $disk_max = $r->peak_disk_usage;
406
        }
407
    }
408
    if ($n == 0) {
409
        echo "No qualifying results.";
410
        page_tail();
411
        return;
412
    }
413
    text_start(800);
414
    start_table('table-striped');
415
    row2("qualifying results", $n);
416
    row2("mean WSS", size_string($wss_sum/$n));
417
    row2("max WSS", size_string($wss_max));
418
    row2("mean swap", size_string($swap_sum/$n));
419
    row2("max swap", size_string($swap_max));
420
    row2("mean disk usage", size_string($disk_sum/$n));
421
    row2("max disk usage", size_string($disk_max));
422
    end_table();
423
    text_end();
424
    page_tail();
425
}
426
427
// return HTML for a color-coded batch progress bar
428
// green: successfully completed jobs
429
// red: failed
430
// light green: in progress
431
// light gray: unsent
432
//
433
function progress_bar($batch, $wus, $width) {
434
    $nsuccess = $batch->njobs_success;
435
    $nerror = $batch->nerror_jobs;
436
    $nin_prog = $batch->njobs_in_prog;
437
    $nunsent = $batch->njobs - $nsuccess - $nerror - $nin_prog;
438
    $w_success = $width*$nsuccess/$batch->njobs;
439
    $w_fail = $width*$nerror/$batch->njobs;
440
    $w_prog = $width*$nin_prog/$batch->njobs;
441
    $w_unsent = $width*$nunsent/$batch->njobs;
442
    $x = '<table height=20><tr>';
443
    if ($w_fail) {
444
        $x .= "<td width=$w_fail bgcolor=red></td>";
445
    }
446
    if ($w_success) {
447
        $x .= "<td width=$w_success bgcolor=green></td>";
448
    }
449
    if ($w_prog) {
450
        $x .= "<td width=$w_prog bgcolor=lightgreen></td>";
451
    }
452
    if ($w_unsent) {
453
        $x .= "<td width=$w_unsent bgcolor=lightgray></td>";
454
    }
455
    $x .= "</tr></table>
456
        <strong>
457
        <font color=red>$nerror fail</font> &middot;
458
        <font color=green>$nsuccess success</font> &middot;
459
        <font color=lightgreen>$nin_prog in progress</font> &middot;
460
        <font color=lightgray>$nunsent unsent</font>
461
        </strong>
462
    ";
463
    return $x;
464
}
465
466
// show the details of an existing batch
467
//
468
function handle_query_batch($user) {
469
    $batch_id = get_int('batch_id');
470
    $batch = BoincBatch::lookup_id($batch_id);
471
    $app = BoincApp::lookup_id($batch->app_id);
472
    $wus = BoincWorkunit::enum("batch = $batch->id");
473
    $batch = get_batch_params($batch, $wus);
474
    if ($batch->user_id == $user->id) {
475
        $owner = $user;
476
    } else {
477
        $owner = BoincUser::lookup_id($batch->user_id);
478
    }
479
480
    $web_app = get_web_app($app);
481
482
    page_head("Batch $batch_id");
483
    text_start(800);
484
    start_table();
485
    row2("name", $batch->name);
486
    if ($batch->description) {
487
        row2('description', $batch->description);
488
    }
489
    if ($owner) {
490
        row2('submitter', $owner->name);
491
    }
492
    row2("application", $app?$app->name:'---');
493
    row2("state", batch_state_string($batch->state));
494
    //row2("# jobs", $batch->njobs);
495
    //row2("# error jobs", $batch->nerror_jobs);
496
    //row2("logical end time", time_str($batch->logical_end_time));
497
    if ($batch->expire_time) {
498
        row2("expiration time", time_str($batch->expire_time));
499
    }
500
    if ($batch->njobs) {
501
        row2("progress", progress_bar($batch, $wus, 600));
502
    }
503
    if ($batch->completion_time) {
504
        row2("completed", local_time_str($batch->completion_time));
505
    }
506
    row2("GFLOP/hours, estimated", number_format(credit_to_gflop_hours($batch->credit_estimate), 2));
507
    row2("GFLOP/hours, actual", number_format(credit_to_gflop_hours($batch->credit_canonical), 2));
508
    if (!$web_app->assim_move) {
509
        row2("Total size of output files",
510
            size_string(batch_output_file_size($batch->id))
511
        );
512
    }
513
    end_table();
514
    echo "<p>";
515
516
    if ($web_app->assim_move) {
517
        $url = "get_output3.php?action=get_batch&batch_id=$batch->id";
518
    } else {
519
        $url = "get_output2.php?cmd=batch&batch_id=$batch->id";
520
    }
521
    echo "<p>";
522
    show_button($url, "Get zipped output files");
523
    echo "<p>";
524
    switch ($batch->state) {
525
    case BATCH_STATE_IN_PROGRESS:
526
        show_button(
527
            "submit.php?action=abort_batch&batch_id=$batch_id",
528
            "Abort batch"
529
        );
530
        break;
531
    case BATCH_STATE_COMPLETE:
532
    case BATCH_STATE_ABORTED:
533
        show_button(
534
            "submit.php?action=retire_batch&batch_id=$batch_id",
535
            "Retire batch"
536
        );
537
        break;
538
    }
539
    echo "<p>";
540
    show_button("submit.php?action=batch_stats&batch_id=$batch_id",
541
        "Show memory/disk usage statistics"
542
    );
543
544
    echo "<h2>Jobs</h2>\n";
545
    start_table();
546
    $x = [
547
        "Name <br><small>click for details</small>",
548
        "status"
0 ignored issues
show
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
549
    ];
550
    if (!$web_app->assim_move) {
551
        $x[] = "Download Results";
552
    }
553
    row_heading_array($x);
554
    foreach($wus as $wu) {
555
        $resultid = $wu->canonical_resultid;
556
        if ($resultid) {
557
            $y = '<font color="green">completed</font>';
558
            $text = "<a href=get_output2.php?cmd=workunit&wu_id=$wu->id>Download output files</a>";
559
        } else {
560
            $text = "---";
561
            if ($batch->state == BATCH_STATE_COMPLETE) {
562
                $y = '<font color="red">failed</font>';
563
            }   else {
564
                $y = "in progress";
565
            }
566
        }
567
        $x = [
568
            "<a href=submit.php?action=query_job&wuid=$wu->id>$wu->name</a>",
569
            $y,
570
        ];
571
        if (!$web_app->assim_move) {
572
            $x[] = $text;
573
        }
574
        row_array($x);
575
    }
576
    end_table();
577
    return_link();
578
    text_end();
579
    page_tail();
580
}
581
582
// get the 'web app' structure (from project.inc) for the given app.
583
// This says what output file scheme it uses and what the submit page URL is.
584
// If not listed, return a default structure
585
//
586
function get_web_app($app) {
587
    global $web_apps;
588
    if (isset($web_apps) && array_key_exists($app->name, $web_apps)) {
589
        return $web_apps[$app->name];
590
    }
591
    $x = new StdClass;
592
    $x->submit_url = null;
593
    $x->assim_move = false;
594
    return $x;
595
}
596
597
// show the details of a job, including links to see the output files
598
//
599
function handle_query_job($user) {
600
    $wuid = get_int('wuid');
601
    $wu = BoincWorkunit::lookup_id($wuid);
602
    if (!$wu) error_page("no such job");
603
604
    $app = BoincApp::lookup_id($wu->appid);
605
    $web_app = get_web_app($app);
606
607
    page_head("Job '$wu->name'");
608
    text_start(800);
609
610
    echo "
611
        <li><a href=workunit.php?wuid=$wuid>Workunit details</a>
612
        <p>
613
        <li><a href=submit.php?action=query_batch&batch_id=$wu->batch>Batch details</a>
614
    ";
615
616
    echo "<h2>Job instances</h2>\n";
617
    start_table('table-striped');
618
    table_header(
619
        "ID<br><small>click for details and stderr</small>",
620
        "State",
621
        "Output files"
622
    );
623
    $results = BoincResult::enum("workunitid=$wuid");
624
    $upload_dir = parse_config(get_config(), "<upload_dir>");
625
    $fanout = parse_config(get_config(), "<uldl_dir_fanout>");
626
    foreach($results as $result) {
627
        $x = [
628
            "<a href=result.php?resultid=$result->id>$result->id</a>",
629
            state_string($result)
0 ignored issues
show
Coding Style introduced by
There should be a trailing comma after the last value of an array declaration.
Loading history...
630
        ];
631
        $i = 0;
632
        if ($result->server_state == RESULT_SERVER_STATE_OVER) {
633
            $phys_names = get_outfile_phys_names($result);
634
            $log_names = get_outfile_log_names($result);
635
            for ($i=0; $i<count($phys_names); $i++) {
0 ignored issues
show
Coding Style Performance introduced by
The use of count() inside a loop condition is not allowed; assign the return value to a variable and use the variable in the loop condition instead
Loading history...
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
636
                if ($web_app->assim_move) {
637
                    // file is in
638
                    // project/results/<batchid>/<wu_name>__file_<log_name>
639
                    $path = sprintf('results/%s/%s__file_%s',
640
                        $wu->batch, $wu->name, $log_names[$i]
641
                    );
642
                    $x[] = "<a href=get_output3.php?action=get_file&path=$path>view</a> &middot; <a href=get_output3.php?action=get_file&path=$path&download=1>download</a>";
643
                } else {
644
                    $path = dir_hier_path(
645
                        $phys_names[$i], $upload_dir, $fanout
646
                    );
647
                    if (file_exists($path)) {
648
                        $url = sprintf(
649
                            'get_output2.php?cmd=result&result_id=%d&file_num=%d',
650
                            $result->id, $i
651
                        );
652
                        $s = stat($path);
653
                        $size = $s['size'];
654
                        $x[] = sprintf('<a href=%s>%s</a> (%s bytes)<br/>',
655
                            $url,
656
                            $log_names[$i],
657
                            number_format($size)
658
                        );
659
                    } else {
660
                        $x[] = sprintf("file '%s' is missing", $log_names[$i]);
661
                    }
662
                }
663
            }
664
        } else {
665
            $x[] = '---';
666
        }
667
        row_array($x);
668
    }
669
    end_table();
670
671
    // show input files
672
    //
673
    echo "<h2>Input files</h2>\n";
674
    $x = "<in>".$wu->xml_doc."</in>";
675
    $x = simplexml_load_string($x);
676
    start_table('table-striped');
677
    table_header("Name<br><small>(click to view)</small>", "Size (bytes)");
678
    foreach ($x->workunit->file_ref as $fr) {
679
        $pname = (string)$fr->file_name;
680
        $lname = (string)$fr->open_name;
681
        foreach ($x->file_info as $fi) {
682
            if ((string)$fi->name == $pname) {
683
                table_row(
684
                    "<a href=$fi->url>$lname</a>",
685
                    $fi->nbytes
686
                );
687
                break;
688
            }
689
        }
690
    }
691
692
    end_table();
693
    text_end();
694
    return_link();
695
    page_tail();
696
}
697
698
// is user allowed to retire or abort this batch?
699
//
700
function check_access($user, $batch) {
701
    if ($user->id == $batch->user_id) return;
702
    $user_submit = BoincUserSubmit::lookup_userid($user->id);
703
    if ($user_submit->manage_all) return;
704
    $usa = BoincUserSubmitApp::lookup("user_id=$user->id and app_id=$batch->app_id");
705
    if ($usa->manage) return;
706
    error_page("no access");
707
}
708
709
function handle_abort_batch() {
710
    $batch_id = get_int('batch_id');
711
    $batch = BoincBatch::lookup_id($batch_id);
712
    if (!$batch) error_page("no such batch");
713
    check_access($user, $batch);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $user seems to be never defined.
Loading history...
714
715
    if (get_int('confirmed', true)) {
716
        abort_batch($batch);
717
        page_head("Batch aborted");
718
        return_link();
719
        page_tail();
720
    } else {
721
        page_head("Confirm abort batch");
722
        echo "
723
            Aborting a batch will cancel all unstarted jobs.
724
            Are you sure you want to do this?
725
            <p>
726
        ";
727
        show_button(
728
            "submit.php?action=abort_batch&batch_id=$batch_id&confirmed=1",
729
            "Yes - abort batch"
730
        );
731
        return_link();
732
        page_tail();
733
    }
734
}
735
736
function handle_retire_batch($user) {
737
    $batch_id = get_int('batch_id');
738
    $batch = BoincBatch::lookup_id($batch_id);
739
    if (!$batch) error_page("no such batch");
740
    check_access($user, $batch);
741
742
    if (get_int('confirmed', true)) {
743
        retire_batch($batch);
744
        page_head("Batch retired");
745
        return_link();
746
        page_tail();
747
    } else {
748
        page_head("Confirm retire batch");
749
        echo "
750
            Retiring a batch will remove all of its output files.
751
            Are you sure you want to do this?
752
            <p>
753
        ";
754
        show_button(
755
            "submit.php?action=retire_batch&batch_id=$batch_id&confirmed=1",
756
            "Yes - retire batch"
757
        );
758
        return_link();
759
        page_tail();
760
    }
761
}
762
763
function handle_retire_multi($user) {
764
    $batches = BoincBatch::enum(
765
        sprintf('user_id=%d and state=%d', $user->id, BATCH_STATE_COMPLETE)
766
    );
767
    page_head('Retiring batches');
768
    foreach ($batches as $batch) {
769
        $x = sprintf('retire_%d', $batch->id);
770
        if (get_str($x, true) == 'on') {
771
            retire_batch($batch);
772
            echo "<p>retired batch $batch->name\n";
773
        }
774
    }
775
    return_link();
776
    page_tail();
777
}
778
779
function show_batches_in_state($batches, $state) {
780
    switch ($state) {
781
    case BATCH_STATE_IN_PROGRESS:
782
        page_head("Batches in progress");
783
        show_in_progress($batches, 0, null, null);
784
        break;
785
    case BATCH_STATE_COMPLETE:
786
        page_head("Completed batches");
787
        show_complete($batches, 0, null, null);
788
        break;
789
    case BATCH_STATE_ABORTED:
790
        page_head("Aborted batches");
791
        show_aborted($batches, 0, null, null);
792
        break;
793
    }
794
    page_tail();
795
}
796
797
function handle_show_all($user) {
798
    $userid = get_int("userid");
799
    $appid = get_int("appid");
800
    $state = get_int("state");
801
    if ($userid) {
802
        // user looking at their own batches
803
        //
804
        if ($userid != $user->id) error_page("wrong user");
805
        $batches = BoincBatch::enum("user_id = $user->id and state=$state order by id desc");
806
        fill_in_app_and_user_names($batches);
807
        show_batches_in_state($batches, $state);
808
    } else {
809
        // admin looking at batches
810
        //
811
        if (!has_admin_access($user, $appid)) {
812
            error_page('no access');
813
        }
814
        if ($appid) {
815
            $app = BoincApp::lookup_id($appid);
816
            if (!$app) error_page("no such app");
817
            $batches = BoincBatch::enum("app_id = $appid and state=$state order by id desc");
818
        } else {
819
            $batches = BoincBatch::enum("state=$state order by id desc");
820
        }
821
        fill_in_app_and_user_names($batches);
822
        show_batches_in_state($batches, $state);
823
    }
824
}
825
826
$user = get_logged_in_user();
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $user is correct as get_logged_in_user() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
827
828
$action = get_str('action', true);
829
830
switch ($action) {
831
case '': handle_main($user); break;
832
case 'abort_batch': handle_abort_batch($user); break;
0 ignored issues
show
Unused Code introduced by
The call to handle_abort_batch() has too many arguments starting with $user. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

832
case 'abort_batch': /** @scrutinizer ignore-call */ handle_abort_batch($user); break;

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
833
case 'admin': handle_admin($user); break;
834
case 'admin_app': handle_admin_app($user); break;
835
case 'admin_all': handle_admin_all($user); break;
836
case 'batch_stats': handle_batch_stats($user); break;
837
case 'query_batch': handle_query_batch($user); break;
838
case 'query_job': handle_query_job($user); break;
839
case 'retire_batch': handle_retire_batch($user); break;
840
case 'retire_multi': handle_retire_multi($user); break;
841
case 'show_all': handle_show_all($user); break;
842
case 'toggle_loc': handle_toggle_loc($user); break;
843
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...
844
    error_page("no such action $action");
845
}
846
847
?>
848