1
|
|
|
<?php |
2
|
|
|
// This file is part of BOINC. |
3
|
|
|
// http://boinc.berkeley.edu |
4
|
|
|
// Copyright (C) 2020 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
|
|
|
// This file contains a PHP binding of a web-service interface |
20
|
|
|
// for submitting jobs to a BOINC server. |
21
|
|
|
// |
22
|
|
|
// Functions: |
23
|
|
|
// boinc_abort_batch(): abort a batch |
24
|
|
|
// boinc_estimate_batch(); estimate completion time of a batch |
25
|
|
|
// boinc_get_output_file(): get the URL for an output file |
26
|
|
|
// boinc_get_output_files(): get the URL for zipped batch output |
27
|
|
|
// boinc_query_batch(): get details of a batch |
28
|
|
|
// boinc_query_batches(): get list of batches |
29
|
|
|
// boinc_query_job(): get details of a job |
30
|
|
|
// boinc_retire_batch(): retire a batch; delete output files |
31
|
|
|
// boinc_submit_batch(): submit a batch |
32
|
|
|
// boinc_set_timeout($x): set RPC timeout to X seconds |
33
|
|
|
// |
34
|
|
|
// See https://github.com/BOINC/boinc/wiki/RemoteJobs#php-interface |
35
|
|
|
|
36
|
|
|
//// Implementation stuff follows |
37
|
|
|
|
38
|
|
|
// Convert a request message from PHP object to XML string |
39
|
|
|
// |
40
|
|
|
function req_to_xml($req, $op) { |
41
|
|
|
if (!isset($req->batch_name)) { |
42
|
|
|
$req->batch_name = "batch_".time(); |
43
|
|
|
} |
44
|
|
|
$x = "<$op> |
45
|
|
|
<authenticator>$req->authenticator</authenticator> |
46
|
|
|
<batch> |
47
|
|
|
<app_name>$req->app_name</app_name> |
48
|
|
|
<batch_name>$req->batch_name</batch_name> |
49
|
|
|
"; |
50
|
|
|
if ((isset($req->output_template_filename)) && ($req->output_template_filename)) { |
51
|
|
|
$x .= " <output_template_filename>$req->output_template_filename</output_template_filename> |
52
|
|
|
"; |
53
|
|
|
} |
54
|
|
|
if ((isset($req->input_template_filename)) && ($req->input_template_filename)) { |
55
|
|
|
$x .= " <input_template_filename>$req->input_template_filename</input_template_filename> |
56
|
|
|
"; |
57
|
|
|
} |
58
|
|
|
if ((isset($req->app_version_num)) && ($req->app_version_num)) { |
59
|
|
|
$x .= " <app_version_num>$req->app_version_num</app_version_num> |
60
|
|
|
"; |
61
|
|
|
} |
62
|
|
|
if (!empty($req->allocation_priority)) { |
63
|
|
|
$x .= " <allocation_priority/> |
64
|
|
|
"; |
65
|
|
|
} |
66
|
|
|
if (isset($req->priority)) { |
67
|
|
|
$x .= " <priority>$req->priority</priority> |
68
|
|
|
"; |
69
|
|
|
} |
70
|
|
|
foreach ($req->jobs as $job) { |
71
|
|
|
$x .= " <job> |
72
|
|
|
"; |
73
|
|
|
if (!empty($job->name)) { |
74
|
|
|
$x .= " <name>$job->name</name> |
75
|
|
|
"; |
76
|
|
|
} |
77
|
|
|
if (!empty($job->rsc_fpops_est)) { |
78
|
|
|
$x .= " <rsc_fpops_est>$job->rsc_fpops_est</rsc_fpops_est> |
79
|
|
|
"; |
80
|
|
|
} |
81
|
|
|
if (!empty($job->command_line)) { |
82
|
|
|
$x .= " <command_line>$job->command_line</command_line> |
83
|
|
|
"; |
84
|
|
|
} |
85
|
|
|
if (!empty($job->target_team)) { |
86
|
|
|
$x .= " <target_team>$job->target_team</target_team> |
87
|
|
|
"; |
88
|
|
|
} elseif (!empty($job->target_user)) { |
89
|
|
|
$x .= " <target_user>$job->target_user</target_user> |
90
|
|
|
"; |
91
|
|
|
} elseif (!empty($job->target_host)) { |
92
|
|
|
$x .= " <target_host>$job->target_host</target_host> |
93
|
|
|
"; |
94
|
|
|
} |
95
|
|
|
if (isset($job->priority)) { |
96
|
|
|
$x .= " <priority>$job->priority</priority> |
97
|
|
|
"; |
98
|
|
|
} |
99
|
|
|
foreach ($job->input_files as $file) { |
100
|
|
|
$x .= " <input_file>\n"; |
101
|
|
|
$x .= " <mode>$file->mode</mode>\n"; |
102
|
|
|
if ($file->mode == "remote") { |
103
|
|
|
$x .= " <url>$file->url</url>\n"; |
104
|
|
|
$x .= " <nbytes>$file->nbytes</nbytes>\n"; |
105
|
|
|
$x .= " <md5>$file->md5</md5>\n"; |
106
|
|
|
} else { |
107
|
|
|
$x .= " <source>$file->source</source>\n"; |
108
|
|
|
} |
109
|
|
|
$x .= " </input_file>\n"; |
110
|
|
|
} |
111
|
|
|
if (!empty($job->input_template)) { |
112
|
|
|
$x .= " $job->input_template\n"; |
113
|
|
|
} |
114
|
|
|
if (!empty($job->output_template)) { |
115
|
|
|
$x .= " $job->output_template\n"; |
116
|
|
|
} |
117
|
|
|
$x .= " </job> |
118
|
|
|
"; |
119
|
|
|
} |
120
|
|
|
$x .= " </batch> |
121
|
|
|
</$op> |
122
|
|
|
"; |
123
|
|
|
return $x; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
// check whether the PHP structure looks like a batch request object |
127
|
|
|
// |
128
|
|
|
function validate_request($req) { |
129
|
|
|
if (!is_object($req)) return "req is not an object"; |
130
|
|
|
if (!property_exists($req, 'project')) return "missing req->project"; |
131
|
|
|
if (!property_exists($req, 'authenticator')) return "missing req->authenticator"; |
132
|
|
|
if (!property_exists($req, 'app_name')) return "missing req->app_name"; |
133
|
|
|
if (!property_exists($req, 'jobs')) return "missing req->jobs"; |
134
|
|
|
if (!is_array($req->jobs)) return "req->jobs is not an array"; |
135
|
|
|
foreach ($req->jobs as $job) { |
|
|
|
|
136
|
|
|
// other checks |
137
|
|
|
} |
138
|
|
|
return null; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
$rpc_timeout = 0; |
142
|
|
|
|
143
|
|
|
// Given a request object and XML string, issue the HTTP POST request |
144
|
|
|
// |
145
|
|
|
function do_http_op($req, $xml, $op) { |
146
|
|
|
global $rpc_timeout; |
147
|
|
|
|
148
|
|
|
$ch = curl_init("$req->project/submit_rpc_handler.php"); |
149
|
|
|
curl_setopt($ch, CURLOPT_POST, 1); |
150
|
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
151
|
|
|
if ($rpc_timeout) { |
152
|
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, $rpc_timeout); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
// see if we need to send any files |
156
|
|
|
// |
157
|
|
|
$nfiles = 0; |
158
|
|
|
$post = array(); |
159
|
|
|
$post["request"] = $xml; |
160
|
|
|
$cwd = getcwd(); |
161
|
|
|
if ($op == "submit_batch") { |
162
|
|
|
foreach ($req->jobs as $job) { |
163
|
|
|
foreach ($job->input_files as $file) { |
164
|
|
|
if ($file->mode == "inline") { |
165
|
|
|
$path = realpath("$cwd/$file->path"); |
166
|
|
|
$post["file$nfiles"] = $path; |
167
|
|
|
$nfiles++; |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); |
173
|
|
|
$reply = curl_exec($ch); |
174
|
|
|
curl_close($ch); |
175
|
|
|
if (!$reply) return array(null, "HTTP error"); |
176
|
|
|
$r = @simplexml_load_string($reply); |
|
|
|
|
177
|
|
|
if (!$r) { |
178
|
|
|
return array(null, "Can't parse reply XML:\n$reply"); |
179
|
|
|
} |
180
|
|
|
$e = (string)$r->error_msg; |
181
|
|
|
if ($e) { |
182
|
|
|
return array(null, "BOINC server: $e"); |
183
|
|
|
} else { |
184
|
|
|
return array($r, null); |
185
|
|
|
} |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
// do a batch op (estimate or submit) |
189
|
|
|
// |
190
|
|
|
function do_batch_op($req, $op) { |
191
|
|
|
$retval = validate_request($req); |
192
|
|
|
if ($retval) return array(null, $retval); |
193
|
|
|
$xml = req_to_xml($req, $op); |
194
|
|
|
return do_http_op($req, $xml, $op); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
// convert a batch description from XML string to object |
198
|
|
|
// |
199
|
|
|
function batch_xml_to_object($batch) { |
200
|
|
|
$b = new StdClass; |
201
|
|
|
$b->id = (int)($batch->id); |
202
|
|
|
$b->create_time = (double)($batch->create_time); |
203
|
|
|
$b->est_completion_time = (double)($batch->est_completion_time); |
204
|
|
|
$b->njobs = (int)($batch->njobs); |
205
|
|
|
$b->fraction_done = (double) $batch->fraction_done; |
206
|
|
|
$b->nerror_jobs = (int)($batch->nerror_jobs); |
207
|
|
|
$b->state = (int)($batch->state); |
208
|
|
|
$b->completion_time = (double)($batch->completion_time); |
209
|
|
|
$b->credit_estimate = (double)($batch->credit_estimate); |
210
|
|
|
$b->credit_canonical = (double)($batch->credit_canonical); |
211
|
|
|
$b->name = (string)($batch->name); |
212
|
|
|
$b->app_name = (string)($batch->app_name); |
213
|
|
|
$b->total_cpu_time = (double)($batch->total_cpu_time); |
214
|
|
|
return $b; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
// if RPC had a fatal error, return the message |
218
|
|
|
// |
219
|
|
|
function get_error($reply, $outer_tag) { |
220
|
|
|
$name = $reply->getName(); |
221
|
|
|
if ($name != $outer_tag) { |
222
|
|
|
return "Bad reply outer tag"; |
223
|
|
|
} |
224
|
|
|
foreach ($reply->error as $error) { |
225
|
|
|
if (isset($error->error_num)) { |
226
|
|
|
return (string)$error->error_msg; |
227
|
|
|
} |
228
|
|
|
} |
229
|
|
|
return null; |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
//// API functions follow |
233
|
|
|
|
234
|
|
|
function boinc_set_timeout($x) { |
235
|
|
|
global $rpc_timeout; |
236
|
|
|
$rpc_timeout = $x; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
function boinc_ping($req) { |
240
|
|
|
$req_xml = "<ping> |
241
|
|
|
<authenticator>$req->authenticator</authenticator> |
242
|
|
|
</ping> |
243
|
|
|
"; |
244
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
245
|
|
|
if ($errmsg) return array(null, $errmsg); |
246
|
|
|
return array($reply, null); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
function boinc_estimate_batch($req) { |
250
|
|
|
list($reply, $errmsg) = do_batch_op($req, "estimate_batch"); |
251
|
|
|
if ($errmsg) return array(0, $errmsg); |
252
|
|
|
if ($x = get_error($reply, "estimate_batch")) { |
253
|
|
|
return array(null, $x); |
254
|
|
|
} |
255
|
|
|
return array((string)$reply->seconds, null); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
function boinc_submit_batch($req) { |
259
|
|
|
list($reply, $errmsg) = do_batch_op($req, "submit_batch"); |
260
|
|
|
if ($errmsg) return array(0, $errmsg); |
261
|
|
|
if ($x = get_error($reply, "submit_batch")) { |
262
|
|
|
return array(null, $x); |
263
|
|
|
} |
264
|
|
|
return array((int)$reply->batch_id, null); |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
function boinc_query_batches($req) { |
268
|
|
|
$req_xml = "<query_batches> |
269
|
|
|
<authenticator>$req->authenticator</authenticator> |
270
|
|
|
"; |
271
|
|
|
if (!empty($req->get_cpu_time)) { |
272
|
|
|
$req_xml .= " <get_cpu_time>1</get_cpu_time>\n"; |
273
|
|
|
} |
274
|
|
|
$req_xml .= "</query_batches>\n"; |
275
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
276
|
|
|
if ($errmsg) return array(null, $errmsg); |
277
|
|
|
if ($x = get_error($reply, "query_batches")) { |
278
|
|
|
return array(null, $x); |
279
|
|
|
} |
280
|
|
|
$batches = array(); |
281
|
|
|
foreach ($reply->batch as $batch) { |
282
|
|
|
$b = batch_xml_to_object($batch); |
283
|
|
|
$batches[] = $b; |
284
|
|
|
} |
285
|
|
|
return array($batches, null); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
function boinc_query_batch($req) { |
289
|
|
|
$req_xml = "<query_batch> |
290
|
|
|
<authenticator>$req->authenticator</authenticator> |
291
|
|
|
<batch_id>$req->batch_id</batch_id> |
292
|
|
|
"; |
293
|
|
|
if (!empty($req->get_cpu_time)) { |
294
|
|
|
$req_xml .= " <get_cpu_time>1</get_cpu_time>\n"; |
295
|
|
|
} |
296
|
|
|
if (!empty($req->get_job_details)) { |
297
|
|
|
$req_xml .= " <get_job_details>1</get_job_details>\n"; |
298
|
|
|
} |
299
|
|
|
$req_xml .= "</query_batch>\n"; |
300
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
301
|
|
|
if ($errmsg) return array(null, $errmsg); |
302
|
|
|
if ($x = get_error($reply, "query_batch")) { |
303
|
|
|
return array(null, $x); |
304
|
|
|
} |
305
|
|
|
$jobs = array(); |
306
|
|
|
foreach ($reply->job as $job) { |
307
|
|
|
$j = new StdClass; |
308
|
|
|
$j->id = (int)($job->id); |
309
|
|
|
$j->canonical_instance_id = (int)($job->canonical_instance_id); |
310
|
|
|
$jobs[] = $j; |
311
|
|
|
} |
312
|
|
|
$r = batch_xml_to_object($reply); |
313
|
|
|
$r->jobs = $jobs; |
314
|
|
|
return array($r, null); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
function boinc_query_job($req) { |
318
|
|
|
$req_xml = "<query_job> |
319
|
|
|
<authenticator>$req->authenticator</authenticator> |
320
|
|
|
<job_id>$req->job_id</job_id> |
321
|
|
|
</query_job> |
322
|
|
|
"; |
323
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
324
|
|
|
if ($errmsg) return array(null, $errmsg); |
325
|
|
|
if ($x = get_error($reply, "query_job")) { |
326
|
|
|
return array(null, $x); |
327
|
|
|
} |
328
|
|
|
$instances = array(); |
329
|
|
|
foreach ($reply->instance as $instance) { |
330
|
|
|
$i = new StdClass; |
331
|
|
|
$i->name = (string)($instance->name); |
332
|
|
|
$i->id = (int)($instance->id); |
333
|
|
|
$i->state = (string)($instance->state); |
334
|
|
|
$i->outfiles = array(); |
335
|
|
|
foreach ($instance->outfile as $outfile) { |
336
|
|
|
$f = new StdClass; |
337
|
|
|
$f->size = (double)$outfile->size; |
338
|
|
|
$i->outfiles[] = $f; |
339
|
|
|
} |
340
|
|
|
$instances[] = $i; |
341
|
|
|
} |
342
|
|
|
$r = new StdClass; |
343
|
|
|
$r->instances = $instances; |
344
|
|
|
return array($r, null); |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
function boinc_abort_batch($req) { |
348
|
|
|
$req_xml = "<abort_batch> |
349
|
|
|
<authenticator>$req->authenticator</authenticator> |
350
|
|
|
<batch_id>$req->batch_id</batch_id> |
351
|
|
|
</abort_batch> |
352
|
|
|
"; |
353
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
354
|
|
|
if ($errmsg) return $errmsg; |
355
|
|
|
if ($x = get_error($reply, "abort_batch")) { |
356
|
|
|
return array(null, $x); |
357
|
|
|
} |
358
|
|
|
return array(true, null); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
function boinc_get_output_file($req) { |
362
|
|
|
$auth_str = md5($req->authenticator.$req->instance_name); |
363
|
|
|
$name = $req->instance_name; |
364
|
|
|
$file_num = $req->file_num; |
365
|
|
|
return $req->project."/get_output.php?cmd=result_file&result_name=$name&file_num=$file_num&auth_str=$auth_str"; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
function boinc_get_output_files($req) { |
369
|
|
|
$auth_str = md5($req->authenticator.$req->batch_id); |
370
|
|
|
$batch_id = $req->batch_id; |
371
|
|
|
return $req->project."/get_output.php?cmd=batch_files&batch_id=$batch_id&auth_str=$auth_str"; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
function boinc_retire_batch($req) { |
375
|
|
|
$req_xml = "<retire_batch> |
376
|
|
|
<authenticator>$req->authenticator</authenticator> |
377
|
|
|
<batch_id>$req->batch_id</batch_id> |
378
|
|
|
</retire_batch> |
379
|
|
|
"; |
380
|
|
|
list($reply, $errmsg) = do_http_op($req, $req_xml, ""); |
381
|
|
|
if ($errmsg) return $errmsg; |
382
|
|
|
if ($x = get_error($reply, "retire_batch")) { |
383
|
|
|
return array(null, $x); |
384
|
|
|
} |
385
|
|
|
return array(true, null); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
//// example usage follows |
389
|
|
|
if (0) { |
390
|
|
|
$req = new StdClass; |
391
|
|
|
$req->project = "http://isaac.ssl.berkeley.edu/test/"; |
392
|
|
|
$req->authenticator = trim(file_get_contents("test_auth")); |
393
|
|
|
$req->app_name = "uppercase"; |
394
|
|
|
$req->batch_name = "batch_name_12"; |
395
|
|
|
$req->app_version_num = 710; |
396
|
|
|
$req->jobs = array(); |
397
|
|
|
|
398
|
|
|
|
399
|
|
|
$f = new StdClass; |
400
|
|
|
$f->mode = "remote"; |
401
|
|
|
$f->url = "http://isaac.ssl.berkeley.edu/validate_logic.txt"; |
402
|
|
|
$f->md5 = "eec5a142cea5202c9ab2e4575a8aaaa7"; |
403
|
|
|
$f->nbytes = 4250; |
404
|
|
|
|
405
|
|
|
if (0) { |
406
|
|
|
$f = new StdClass; |
407
|
|
|
$f->mode = "local"; |
408
|
|
|
$f->source = "foobar"; |
409
|
|
|
//$job->input_files[] = $f; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
$it = " |
413
|
|
|
<input_template> |
414
|
|
|
<file_info> |
415
|
|
|
</file_info> |
416
|
|
|
<workunit> |
417
|
|
|
<file_ref> |
418
|
|
|
<open_name>in</open_name> |
419
|
|
|
</file_ref> |
420
|
|
|
<target_nresults>1</target_nresults> |
421
|
|
|
<min_quorum>1</min_quorum> |
422
|
|
|
<rsc_fpops_est> 60e9 </rsc_fpops_est> |
423
|
|
|
<rsc_fpops_bound> 60e12 </rsc_fpops_bound> |
424
|
|
|
<rsc_disk_bound>2e6</rsc_disk_bound> |
425
|
|
|
<rsc_memory_bound>1e6</rsc_memory_bound> |
426
|
|
|
<delay_bound>3600</delay_bound> |
427
|
|
|
<credit>1</credit> |
428
|
|
|
</workunit> |
429
|
|
|
</input_template> |
430
|
|
|
"; |
431
|
|
|
$ot = " |
432
|
|
|
<output_template> |
433
|
|
|
<file_info> |
434
|
|
|
<name><OUTFILE_0/></name> |
435
|
|
|
<generated_locally/> |
436
|
|
|
<upload_when_present/> |
437
|
|
|
<max_nbytes>6000000</max_nbytes> |
438
|
|
|
<url><UPLOAD_URL/></url> |
439
|
|
|
</file_info> |
440
|
|
|
<result> |
441
|
|
|
<file_ref> |
442
|
|
|
<file_name><OUTFILE_0/></file_name> |
443
|
|
|
<open_name>out</open_name> |
444
|
|
|
</file_ref> |
445
|
|
|
</result> |
446
|
|
|
</output_template> |
447
|
|
|
"; |
448
|
|
|
for ($i=0; $i<2; $i++) { |
449
|
|
|
$job = new StdClass; |
450
|
|
|
$job->input_files = array(); |
451
|
|
|
$job->input_files[] = $f; |
452
|
|
|
$job->name = $req->batch_name."_$i"; |
453
|
|
|
//$job->rsc_fpops_est = $i*1e9; |
454
|
|
|
$job->command_line = "--t $i"; |
455
|
|
|
$job->input_template = $it; |
456
|
|
|
$job->output_template = $ot; |
457
|
|
|
$req->jobs[] = $job; |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
if (0) { |
461
|
|
|
list($e, $errmsg) = boinc_estimate_batch($req); |
462
|
|
|
if ($errmsg) { |
463
|
|
|
echo "Error from server: $errmsg\n"; |
464
|
|
|
} else { |
465
|
|
|
echo "Batch completion estimate: $e seconds\n"; |
466
|
|
|
} |
467
|
|
|
} else { |
468
|
|
|
list($id, $errmsg) = boinc_submit_batch($req); |
469
|
|
|
if ($errmsg) { |
470
|
|
|
echo "Error from server: $errmsg\n"; |
471
|
|
|
} else { |
472
|
|
|
echo "Batch ID: $id\n"; |
473
|
|
|
} |
474
|
|
|
} |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
if (0) { |
478
|
|
|
list($batches, $errmsg) = boinc_query_batches($req); |
479
|
|
|
if ($errmsg) { |
480
|
|
|
echo "Error: $errmsg\n"; |
481
|
|
|
} else { |
482
|
|
|
print_r($batches); |
483
|
|
|
} |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
if (0) { |
487
|
|
|
$req->batch_id = 20; |
488
|
|
|
list($jobs, $errmsg) = boinc_query_batch($req); |
489
|
|
|
if ($errmsg) { |
490
|
|
|
echo "Error: $errmsg\n"; |
491
|
|
|
} else { |
492
|
|
|
print_r($jobs); |
493
|
|
|
} |
494
|
|
|
} |
495
|
|
|
?> |
496
|
|
|
|
This check looks for
foreach
loops 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.Consider removing the loop.