Make it possible to find before and after runs of arbitrary revision
This commit is contained in:
Родитель
92aadfa9db
Коммит
000a68f9e4
|
@ -34,6 +34,32 @@ class Run extends DB {
|
|||
return new Run(mysql_insert_id());
|
||||
}
|
||||
|
||||
public static function closestRun($machine_id, $mode_id, $revisions) {
|
||||
if (count($revisions) == 0)
|
||||
throw new Exception("No revisions provided.");
|
||||
|
||||
$revs = "";
|
||||
for ($i = 0; $i < count($revisions); $i++) {
|
||||
if ($i != 0)
|
||||
$revs .= ",";
|
||||
$revs .= "'".$revisions[$i]->revision()."'";
|
||||
}
|
||||
|
||||
$qRun = mysql_query("SELECT awfy_run.id FROM awfy_run
|
||||
LEFT JOIN awfy_build ON run_id = awfy_run.id
|
||||
WHERE cset IN (".$revs.") AND
|
||||
machine = $machine_id AND
|
||||
mode_id = $mode_id AND
|
||||
status = 1 AND
|
||||
error = ''
|
||||
ORDER BY sort_order DESC
|
||||
LIMIT 1") or die(mysql_error());
|
||||
if (mysql_num_rows($qRun) == 0)
|
||||
return null;
|
||||
$run = mysql_fetch_object($qRun);
|
||||
return new Run($run->id);
|
||||
}
|
||||
|
||||
public function finish($status, $error = "") {
|
||||
if (empty($error))
|
||||
$error = "NULL";
|
||||
|
@ -80,13 +106,6 @@ class Run extends DB {
|
|||
return $this->select("detector");
|
||||
}
|
||||
|
||||
public function builds() {
|
||||
$qRun = mysql_query("SELECT approx_stamp from awfy_builds
|
||||
WHERE id = {$this->id}") or die(mysql_error());
|
||||
$run = mysql_fetch_object($qRun);
|
||||
return $run->approx_stamp;
|
||||
}
|
||||
|
||||
public function isBuildInfoComplete() {
|
||||
// The set of builds cannot change anymore, when the run is finished
|
||||
// or if this run is an out of order run. Out of order runs immediately
|
||||
|
@ -102,6 +121,8 @@ class Run extends DB {
|
|||
machine = {$machine}
|
||||
ORDER BY sort_order ASC
|
||||
LIMIT 1") or throw_exception(mysql_error());
|
||||
if (mysql_num_rows($qRun) == 0)
|
||||
return null;
|
||||
$run = mysql_fetch_object($qRun);
|
||||
return new Run($run->id);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class TaskQueue {
|
|||
FROM control_task_queue
|
||||
WHERE control_unit_id = {$this->unit_id} AND
|
||||
start = 0
|
||||
ORDER BY id LIMIT 1") or die(mysql_error());
|
||||
ORDER BY id") or die(mysql_error());
|
||||
$tasks = Array();
|
||||
while ($task = mysql_fetch_object($qTask)) {
|
||||
$tasks[] = QueuedTask::FromId($task->id);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require_once("ManipulateTask.php");
|
||||
require_once("VersionControl.php");
|
||||
require_once("DB/Mode.php");
|
||||
require_once("DB/Run.php");
|
||||
require_once("DB/Build.php");
|
||||
|
||||
class RetriggerController {
|
||||
|
||||
|
@ -80,9 +82,45 @@ class RetriggerController {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static function computeBeforeAfterId($machine_id, $mode_id, $revision) {
|
||||
$version_control = VersionControl::forMode($mode_id);
|
||||
if (!$version_control->exists($revision))
|
||||
throw new Exception("Revision does not exists.");
|
||||
$next_revision = $revision;
|
||||
$run = null;
|
||||
$it = 0;
|
||||
while (!$run) {
|
||||
$revisions = $version_control->before($next_revision);
|
||||
assert($revisions[0] == $revision);
|
||||
$run = Run::closestRun($machine_id, $mode_id, $revisions);
|
||||
$next_revision = $revisions[count($revisions) - 1]->revision();
|
||||
if ($it > 50)
|
||||
throw new Exception("Too much revisions given revision and previous datapoint.");
|
||||
}
|
||||
|
||||
$run_before_id = $run->id;
|
||||
|
||||
$next = $run->next();
|
||||
while (true) {
|
||||
$cur = $next;
|
||||
$next = $next->next();
|
||||
|
||||
if (!$cur)
|
||||
throw new Exception("Couldn't find a revision with results after the given revision.");
|
||||
if (!$cur->isFinished())
|
||||
continue;
|
||||
if ($cur->hasError())
|
||||
continue;
|
||||
if (!Build::withRunAndMode($cur->id, $mode_id))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
$run_after_id = $cur->id;
|
||||
return Array($run_before_id, $run_after_id);
|
||||
}
|
||||
public function convertToRevision($mode_id, $revision, $run_before_id, $run_after_id) {
|
||||
$mode = new Mode($mode_id);
|
||||
|
||||
foreach ($this->tasks as $task) {
|
||||
$task->update_modes(Array("jmim"/*$mode->mode()*/));
|
||||
$task->setBuildRevision($revision);
|
||||
|
@ -91,13 +129,17 @@ class RetriggerController {
|
|||
}
|
||||
|
||||
private function normalizeBenchmark($benchmark) {
|
||||
// Keep in accordance with retrigger/index.php
|
||||
$benchmark = str_replace("local.", "", $benchmark);
|
||||
$benchmark = str_replace("remote.", "", $benchmark);
|
||||
$benchmark = str_replace("shell.", "", $benchmark);
|
||||
$benchmark = str_replace("-", "", $benchmark);
|
||||
$benchmark = str_replace("misc", "assorted", $benchmark);
|
||||
$benchmark = str_replace("ss", "sunspider", $benchmark);
|
||||
$benchmark = str_replace("asmjsubench", "asmjsmicro", $benchmark);
|
||||
if ($benchmark == "misc")
|
||||
$benchmark = "assorted";
|
||||
if ($benchmark == "ss")
|
||||
$benchmark = "sunspider";
|
||||
if ($benchmark == "asmjsubench")
|
||||
$benchmark = "asmjsmicro";
|
||||
return $benchmark;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@ class HGWeb {
|
|||
throw new Exception("Couldn't find relationship between $revision1 and $revision2.");
|
||||
}
|
||||
|
||||
public function exists($revision) {
|
||||
$html = file_get_contents($this->url."log?rev=$revision");
|
||||
$pattern = '#<a href="/integration/mozilla-inbound/rev/'.$revision.'">diff</a><br/>#';
|
||||
return preg_match($pattern, $html) == 1;
|
||||
}
|
||||
|
||||
public function revisions($from, $to) {
|
||||
$html = file_get_contents($this->url."log?rev=$from%3A%3A$to%20and%20!$from");
|
||||
$html = preg_replace("/[\r\n]*/", "", $html);
|
||||
|
@ -48,4 +54,20 @@ class HGWeb {
|
|||
}
|
||||
return $revisions;
|
||||
}
|
||||
|
||||
public function before($revision) {
|
||||
$html = file_get_contents($this->url."shortlog/".$revision);
|
||||
|
||||
$pattern = '#<a href="/integration/mozilla-inbound/rev/(.*)">diff</a><br/>#';
|
||||
preg_match_all($pattern, $html, $matches);
|
||||
|
||||
$revisions = Array();
|
||||
for ($i = 0; $i < count($matches[0]); $i++) {
|
||||
$revision = $matches[1][$i];
|
||||
$revisions[] = new Revision("", "", $revision, "");
|
||||
}
|
||||
assert($revisions[0] == $revision);
|
||||
return $revisions;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
require_once("../internals.php");
|
||||
require_once("../lib/RetriggerController.php");
|
||||
require_once("../lib/VersionControl/HGWeb.php");
|
||||
require_once("../lib/DB/ControlTasks.php");
|
||||
require_once("../lib/DB/Mode.php");
|
||||
|
||||
init_database();
|
||||
$machine_id = (int)$_GET["machine_id"];
|
||||
$mode_id = (int)$_GET["mode_id"];
|
||||
|
||||
$retrigger = RetriggerController::fromMachine($machine_id, $mode_id);
|
||||
if (count($retrigger->tasks) != 1)
|
||||
die("Machine doesn't support retriggering yet.");
|
||||
|
||||
foreach ($retrigger->tasks as $task) {
|
||||
$benchmarks = Array();
|
||||
foreach ($task->benchmarks() as $task_benchmark) {
|
||||
$benchmarks[] = $task_benchmark;
|
||||
}
|
||||
echo JSON_encode($benchmarks);
|
||||
die();
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
require_once("../internals.php");
|
||||
require_once("../lib/RetriggerController.php");
|
||||
require_once("../lib/VersionControl/HGWeb.php");
|
||||
require_once("../lib/DB/ControlTasks.php");
|
||||
require_once("../lib/DB/Mode.php");
|
||||
|
||||
init_database();
|
||||
|
||||
$machines = Array();
|
||||
$control_tasks = ControlTasks::all();
|
||||
foreach ($control_tasks as $control_task) {
|
||||
$machine_id = $control_task->machine_id();
|
||||
$mode_id = $control_task->mode_id() ? $control_task->mode_id() : Mode::FromMode("jmim")->id;
|
||||
if (RetriggerController::retriggerable($machine_id, $mode_id)) {
|
||||
$description = $control_task->machine()->description();
|
||||
if ($control_task->mode_id())
|
||||
$description .= " - ".$control_task->mode()->name();
|
||||
|
||||
$machines[$description] = Array(
|
||||
"machine_id" => $control_task->machine()->id,
|
||||
"mode_id" => $mode_id
|
||||
);
|
||||
}
|
||||
}
|
||||
echo JSON_encode($machines);
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
require_once("../internals.php");
|
||||
require_once("../lib/RetriggerController.php");
|
||||
require_once("../lib/VersionControl/HGWeb.php");
|
||||
require_once("../lib/DB/ControlTasks.php");
|
||||
require_once("../lib/DB/Mode.php");
|
||||
|
||||
init_database();
|
||||
$machine_id = (int)$_GET["machine_id"];
|
||||
$mode_id = (int)$_GET["mode_id"];
|
||||
$revision = $_GET["revision"];
|
||||
$benchmarks = $_GET["benchmarks"];
|
||||
|
||||
if (!ctype_alnum($revision))
|
||||
throw new Exception("Given revision is not alphanumeric.");
|
||||
|
||||
try {
|
||||
$retrigger = RetriggerController::fromMachine($machine_id, $mode_id);
|
||||
$runs = RetriggerController::computeBeforeAfterId($machine_id, $mode_id, $revision);
|
||||
$retrigger->convertToRevision($mode_id, $revision, $runs[0], $runs[1]);
|
||||
$retrigger->selectBenchmarks($benchmarks);
|
||||
$retrigger->enqueueNow();
|
||||
} catch (Exception $e) {
|
||||
echo 'Caught exception: ', $e->getMessage(), "\n";
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
margin-left:auto;
|
||||
margin-right:auto;
|
||||
width: 500px;
|
||||
}
|
||||
label {
|
||||
margin-top: 25px;
|
||||
display: block;
|
||||
}
|
||||
input, select {
|
||||
display: block;
|
||||
width: 500px;
|
||||
}
|
||||
#benchmarks {
|
||||
height: 150px;
|
||||
}
|
||||
</style>
|
||||
<script src='../jquery/jquery-1.8.3.min.js'></script>
|
||||
<script>
|
||||
$(function() {
|
||||
function report() {
|
||||
alert("Internal error: Please report to hv1989@gmail.com / h4writer on #jsapi.");
|
||||
}
|
||||
function urlHas(key, value) {
|
||||
var params = location.search.split(key+"="+value)
|
||||
if (params.length != 2)
|
||||
return false;
|
||||
|
||||
if (params[0].slice(-1) != "?" && params[0].slice(-1) != "&")
|
||||
return false;
|
||||
|
||||
if (params[1].length != 0 && params[1].substr(0,1) != "&")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
function normalizeBench(name) {
|
||||
// keep in accordance with lib/RetriggerController.php
|
||||
name = name.replace(/ [0-9\.]*$/, "");
|
||||
name = name.replace("local.", "");
|
||||
name = name.replace("remote.", "");
|
||||
name = name.replace("shell.", "");
|
||||
name = name.replace("-", "");
|
||||
if (name == "misc")
|
||||
name = "assorted";
|
||||
if (name == "ss")
|
||||
name = "sunspider";
|
||||
if (name == "asmjsubench")
|
||||
name = "asmjsmicro";
|
||||
return name;
|
||||
}
|
||||
function benchmarksFromUrl() {
|
||||
var params = decodeURIComponent(location.search).split("benchmarks[]=")
|
||||
var benchmarks = []
|
||||
for (var i = 1; i<params.length; i++) {
|
||||
if (params[i-1].slice(-1) != '?' && params[i-1].slice(-1) != "&")
|
||||
continue;
|
||||
var parts = params[i].split("&");
|
||||
var name = normalizeBench(parts[0]);
|
||||
benchmarks.push(name);
|
||||
}
|
||||
return benchmarks;
|
||||
}
|
||||
|
||||
var benchmarks = [];
|
||||
|
||||
$.ajax({
|
||||
url: "data-machines.php",
|
||||
dataType: "json",
|
||||
statusCode: { 500: report }
|
||||
}).done(function(data) {
|
||||
var selection = []
|
||||
$.each(data, function(descr, id) {
|
||||
var option = $('<option>').text(descr);
|
||||
option.data("key", id);
|
||||
|
||||
$('#machines').append(option);
|
||||
|
||||
var select = true;
|
||||
$.each(id, function(key, value) {
|
||||
if (!urlHas(key, value))
|
||||
select = false;
|
||||
});
|
||||
if (select) {
|
||||
benchmarks = benchmarksFromUrl();
|
||||
$('#machines').val(descr).change();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#machines').change(function() {
|
||||
var value = $("#machines option:selected").data("key");
|
||||
$('#benchmarks').text("");
|
||||
if (!value)
|
||||
return;
|
||||
$.ajax({
|
||||
url: "data-benchmarks.php",
|
||||
data: value,
|
||||
dataType: "json",
|
||||
statusCode: { 500: report }
|
||||
}).done(function(data) {
|
||||
if (typeof data === 'string') {
|
||||
alert("Error: "+data);
|
||||
return;
|
||||
}
|
||||
$.each(data, function(id, name) {
|
||||
var option = $('<option>').text(name);
|
||||
if ($.inArray(normalizeBench(name), benchmarks) != -1)
|
||||
option.attr('selected','selected');
|
||||
$('#benchmarks').append(option);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('#benchmarks').change(function() {
|
||||
benchmarks = $('#benchmarks').val();
|
||||
for (var i = 0; i < benchmarks.length; i++) {
|
||||
benchmarks[i] = normalizeBench(benchmarks[i]);
|
||||
}
|
||||
});
|
||||
|
||||
var match = location.search.match(/[&?]revision=([a-zA-Z0-9]*)(&|$)/);
|
||||
if (match)
|
||||
$('#revision').val(match[1]);
|
||||
|
||||
$("#trigger").submit(function(event) {
|
||||
event.preventDefault();
|
||||
var data = $("#machines option:selected").data("key");
|
||||
data["revision"] = $("#revision").val();
|
||||
data["benchmarks"] = $("#benchmarks").val();
|
||||
console.log(data);
|
||||
$.ajax({
|
||||
url: "data-submit.php",
|
||||
data: data,
|
||||
statusCode: { 500: report }
|
||||
}).done(function(data) {
|
||||
if (data.length > 0) {
|
||||
alert("Error: "+data);
|
||||
} else {
|
||||
alert("Succesfully enqueued");
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Trigger a revision on AWFY</h1>
|
||||
<form id='trigger'>
|
||||
<label>Machine:
|
||||
<select id='machines'>
|
||||
<option>--- Select a machine ---</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>Revision:
|
||||
<input type='text' name='revision' id='revision'>
|
||||
</label>
|
||||
|
||||
<label>Benchmarks:
|
||||
<select multiple id='benchmarks'>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
|
||||
<input type='submit' value='Trigger!'>
|
||||
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче