Ops: enhance errorwus.php again

Added more filters and moved logic from PHP to the DB. This results in a smaller memory footprint of the script but stresses the database a little more for big projects.
This commit is contained in:
Christian Beer 2016-03-18 10:51:09 +01:00
parent ef9dfdfde8
commit 0040bd9817
3 changed files with 125 additions and 81 deletions

View File

@ -355,6 +355,13 @@ if (!isset($skip_auth_ops) && array_key_exists("SERVER_PORT", $_SERVER)) {
auth_ops();
}
// returns true when this is a readonly ops section
// currently a dummy because this needs to be ported from Einstein@home
//
function in_rops() {
return false;
}
function cancel_wus_where($clause) {
$q1 = "CREATE TEMPORARY TABLE tmp SELECT id FROM workunit WHERE $clause;";
$q2 = "UPDATE result r INNER JOIN tmp t on r.workunitid=t.id SET server_state=5, outcome=5 WHERE server_state=2;";

View File

@ -19,6 +19,9 @@
require_once("../inc/util_ops.inc");
$cancel = post_int('cancel', true);
$hide_canceled = post_str('hide_canceled', true);
$hide_dlerr = post_str('hide_dlerr', true);
$appid = post_int('appid', true);
$WU = post_arr('WU', true);
$back = post_str('back', true);
$clause = post_str('clause', true);
@ -47,18 +50,24 @@ if ($cancel && ($cancel == 1)) {
//
if($WUs != "") {
echo "<!--- WUs to cancel: $WUs --->\n";
// if (!in_rops()) {
if (!in_rops()) {
cancel_wus_where("id IN (" . $WUs . ")");
// }
}
}
if ($back) {
if ($back == "errorwus") {
$args = "?refresh_cache=1";
if (array_key_exists('hide_canceled',$_REQUEST)) {
if ($hide_canceled && $hide_canceled=="on") {
$args .= "&hide_canceled=on";
}
echo "<p><a href=\"errorwus.php$args\">Return to All-error Workunits page</a></p>";
if ($hide_dlerr && $hide_dlerr=="on") {
$args .= "&hide_dlerr=on";
}
if ($appid) {
$args .= "&appid=$appid";
}
echo "<p><a href=\"errorwus.php$args\">Return to All-error Workunits page</a> (refreshes the cache)</p>";
} else if ($back == "cancelwus") {
if ($clause) {
$clause=urlencode($clause);

View File

@ -1,7 +1,7 @@
<?php
// This file is part of BOINC.
// http://boinc.berkeley.edu
// Copyright (C) 2008 University of California
// Copyright (C) 2016 University of California
//
// BOINC is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
@ -27,113 +27,125 @@ $cache_sec = 1800;
// Number that determines how many client errors are necessary for a WU to show up in this list.
// This number is added to min_quorum of the WU, so a value of 1 means that there must be more than
// (min_quorum + 1) errors for a WU to show up in this list.
$notification_level = 1;
$notification_level = get_int("level", true);
if (!$notification_level) {
$notification_level = 1;
}
$appid_filter = "";
$appid_title = "";
$appid = get_int("appid", true);
if ($appid) {
$appid_filter = " appid = $appid AND ";
$app = BoincApp::lookup_id($appid);
$appid_title = " for ".$app->name;
}
// the following variables are using the cache that is created by the variables above
// hide already canceled WUs
$hide_canceled = get_str("hide_canceled", true);
// hide WU that have only download errors
$hide_dlerr = get_str("hide_dlerr", true);
// refresh cache from DB
$refresh_cache = get_int("refresh_cache", true);
admin_page_head("All-error Workunits");
admin_page_head("All-error Workunits".$appid_title);
function print_wu($row) {
echo "<tr>\n";
echo "<td align=\"left\" valign=\"top\">";
echo "<input type=\"checkbox\" name=\"WU[]\" value=\"".$row['id']."\">\n";
if (!in_rops()) {
echo "<input type=\"checkbox\" name=\"WU[]\" value=\"".$row->id."\">\n";
}
echo "<a href=db_action.php?table=workunit&detail=high&id=";
echo $row['id'];
echo $row->id;
echo ">";
echo $row['id'];
echo $row->id;
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">".$row->name."</td>\n";
echo "<td align=\"left\" valign=\"top\">".$row->appid."</td>\n";
echo "<td align=\"left\" valign=\"top\">".$row->min_quorum."</td>\n";
echo "<td align=\"left\" valign=\"top\">".$row->unsent."</td>\n";
echo "<td align=\"left\" valign=\"top\">".$row->in_progress."</td>\n";
echo "<td align=\"left\" valign=\"top\">";
echo "<a href=db_action.php?table=result&query=&outcome=1&detail=low&workunitid=".$row->id.">";
echo $row->successes;
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">";
echo $row['name'];
echo "</td>\n";
echo "<a href=db_action.php?table=result&query=&outcome=3&client_state=1&detail=low&workunitid=".$row->id.">";
echo $row->download_errors;
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">";
echo $row['quorum'];
echo "</td>\n";
echo "<a href=db_action.php?table=result&query=&outcome=3&client_state=3&sort_by=mod_time&detail=low&workunitid=".$row->id.">";
echo $row->compute_errors;
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">";
if ($row['mask']) {
echo wu_error_mask_str($row['mask']);
echo "<a href=db_action.php?table=result&query=&outcome=6&sort_by=mod_time&detail=low&workunitid=".$row->id.">";
echo $row->validate_errors;
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">";
if ($row->error_mask) {
echo wu_error_mask_str($row->error_mask);
} else {
echo $row['mask'];
echo "&nbsp;";
}
echo "</td>\n";
echo "<td align=\"left\" valign=\"top\">";
echo "<a href=db_action.php?table=result&query=&outcome=3&sort_by=mod_time&detail=low&workunitid=";
echo $row['id'];
echo ">";
echo $row['clerrors'];
echo "</a></td>\n";
echo "<td align=\"left\" valign=\"top\">";
echo "<a href=db_action.php?table=result&query=&outcome=6&sort_by=mod_time&detail=low&workunitid=";
echo $row['id'];
echo ">";
echo $row['valerrors'];
echo "</a></td>\n";
echo "</tr>\n";
}
function get_error_wus() {
global $notification_level;
global $appid_filter;
$db = BoincDb::get();
// this query is obviously expensive for big projects but if there is a replica this does not impact the project
$db = BoincDb::get(true);
$dbresult = $db->do_query("
SELECT workunitid, outcome, workunit.name, min_quorum, error_mask
FROM result INNER JOIN workunit ON workunit.id = workunitid
WHERE server_state = 5
ORDER BY workunitid, outcome DESC
SELECT id, name, appid, unsent, in_progress, successes, compute_errors,
download_errors, validate_errors, error_mask, min_quorum,
(compute_errors + download_errors + validate_errors) as total_errors
FROM (
SELECT
workunitid,
SUM(IF(outcome=1,1,0)) AS successes,
SUM(IF((outcome=3 AND client_state=1),1,0)) AS download_errors,
SUM(IF((outcome=3 AND client_state=3),1,0)) AS compute_errors,
SUM(IF(outcome=6,1,0)) AS validate_errors,
SUM(IF(server_state=2,1,0)) AS unsent,
SUM(IF(server_state=4,1,0)) AS in_progress
FROM result
WHERE server_state IN (2,4,5)
GROUP BY workunitid
) AS t1
JOIN workunit ON workunit.id = workunitid
WHERE canonical_resultid=0 AND $appid_filter
GREATEST(download_errors, compute_errors, validate_errors) > min_quorum + $notification_level
ORDER BY name
;");
$row_cache = array();
$previd = -1;
$prevname = "";
$prevquorum = 1;
$prevmask = 0;
$valerrors = 0;
$clerrors = 0;
while ($res = $dbresult->fetch_object()) {
$id = $res->workunitid;
if ($id != $previd) {
if (($clerrors > $prevquorum + $notification_level) || ($valerrors > $prevquorum + $notification_level)) {
$row_cache[] = array("id" => $previd, "name" => $prevname, "quorum" => $prevquorum, "clerrors" => $clerrors,
"valerrors" => $valerrors, "mask" => $prevmask);
}
$prevmask = $res->error_mask;
$previd = $id;
$prevname = $res->name;
$prevquorum = $res->min_quorum;
$clerrors = 0;
$valerrors = 0;
}
if ($res->outcome == 3) {
$clerrors ++;
}
if ($res->outcome == 6) {
$valerrors ++;
}
if ($res->outcome == 1) {
$clerrors = 0;
$valerrors = 0;
}
while ($row = $dbresult->fetch_object()) {
$row_cache[] = $row;
}
$dbresult->free();
if (($clerrors > $prevquorum + $notification_level) || ($valerrors > $prevquorum + $notification_level)) {
$row_cache[] = array("id" => $previd, "name" => $prevname, "quorum" => $prevquorum, "clerrors" => $clerrors,
"valerrors" => $valerrors, "mask" => $prevmask);
}
return $row_cache;
}
$last_update = 0;
$row_array = null;
$cache_data = get_cached_data($cache_sec);
$cache_args = "level=$notification_level";
if ($appid) $cache_args .= "&appid=$appid";
$cache_data = get_cached_data($cache_sec, $cache_args);
if ($cache_data && !$refresh_cache) {
$cache_data = unserialize($cache_data);
$last_update = $cache_data['last_update'];
@ -142,23 +154,35 @@ if ($cache_data && !$refresh_cache) {
$row_array = get_error_wus();
$last_update = time();
$cache_data = array('last_update' => $last_update, 'row_array' => $row_array);
set_cached_data($cache_sec, serialize($cache_data));
set_cached_data($cache_sec, serialize($cache_data), $cache_args);
}
echo "<br/>";
echo "<form method=\"get\" action=\"errorwus.php\">\n";
print_checkbox("Hide canceled WUs", "hide_canceled", $hide_canceled);
print_checkbox("Hide WUs with only d/l errors", "hide_dlerr", $hide_dlerr);
if ($appid) {
echo "<input type=\"hidden\" name=\"appid\" value=\"$appid\"/>";
}
echo "<input type=\"hidden\" name=\"level\" value=\"$notification_level\"/>";
echo "<input class=\"btn btn-default\" type=\"submit\" value=\"OK\">\n";
echo "</form>\n";
echo "Page last updated ".time_str($last_update);
echo "<form action=\"cancel_workunits_action.php\" method=\"post\">\n";
if (!in_rops()) {
echo "<form action=\"cancel_workunits_action.php\" method=\"post\">\n";
echo "<input type=\"hidden\" name=\"back\" value=\"errorwus\"/>";
}
echo "<br/><table border=\"1\">\n";
echo "<input type=\"hidden\" name=\"back\" value=\"errorwus\"/>";
echo "<tr><th>WU ID</th><th>WU name</th><th>Quorum</th><th>Error mask</th><th>Client Errors</th><th>Validate Errors</th></tr>\n";
echo "<tr><th>WU ID</th><th>WU name</th><th>App ID</th><th>Quorum</th><th>Unsent</th><th>In Progress</th><th>Success</th>";
echo "<th>Download Errors</th><th>Compute Errors</th><th>Validate Errors</th><th>Error mask</th></tr>\n";
$hidden=0;
foreach($row_array as $row) {
if ($hide_canceled == 'on' && (($row['mask'] & WU_ERROR_CANCELLED) == WU_ERROR_CANCELLED)) {
if ($hide_canceled == 'on' && (($row->error_mask & WU_ERROR_CANCELLED) == WU_ERROR_CANCELLED)) {
$hidden++;
continue;
}
if ($hide_dlerr == 'on' && $row->download_errors > 0 && $row->compute_errors == 0 && $row->validate_errors == 0) {
$hidden++;
continue;
}
@ -166,12 +190,16 @@ foreach($row_array as $row) {
}
echo "</table>\n<br>";
echo "<input type=\"hidden\" name=\"cancel\" value=\"1\"/>";
if ($hide_canceled == 'on') {
echo "<input type=\"hidden\" name=\"hide_canceled\" value=\"on\"/>";
if (!in_rops()) {
echo "<input type=\"hidden\" name=\"cancel\" value=\"1\"/>";
echo "<input type=\"hidden\" name=\"hide_canceled\" value=\"$hide_canceled\"/>";
echo "<input type=\"hidden\" name=\"hide_dlerr\" value=\"$hide_dlerr\"/>";
if ($appid) {
echo "<input type=\"hidden\" name=\"appid\" value=\"$appid\"/>";
}
echo "<input class=\"btn btn-default\" type=\"submit\" value=\"Cancel checked WUs\">";
echo "</form>\n";
}
echo "<input class=\"btn btn-default\" type=\"submit\" value=\"Cancel checked WUs\">";
echo "</form>\n";
echo count($row_array)." entries (".$hidden." hidden)\n";
admin_page_tail();