Create start of a lib directory
This commit is contained in:
Родитель
669999efbb
Коммит
c87328a1bf
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class BashInterpreter {
|
||||||
|
public static function matchCommand($text, $command) {
|
||||||
|
$command = str_replace("/", "\/", $command);
|
||||||
|
preg_match_all("/".$command." .*[;|$|\r\n]/", $text, $matches);
|
||||||
|
return $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function matchFlag($command, $flag) {
|
||||||
|
$flag = str_replace("/", "\/", $flag);
|
||||||
|
preg_match_all("/".$flag." ([a-zA-Z0-9.~\-\/]*)/", $command, $matches);
|
||||||
|
return $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function removeFlagFromCommand($text, $full_command, $full_flag) {
|
||||||
|
$replaced = str_replace($full_flag, "", $full_command);
|
||||||
|
$text = str_replace($full_command, $replaced, $text);
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function addFlagToCommands($text, $command, $full_flag) {
|
||||||
|
return str_replace($command, $command." ".$full_flag, $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function removeFlagFromCommands($text, $command, $full_flag) {
|
||||||
|
foreach(BashInterpreter::matchCommand($text, $command) as $match) {
|
||||||
|
$text = BashInterpreter::removeFlagFromCommand($text, $match, $full_flag);
|
||||||
|
}
|
||||||
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function removeCommand($text, $full_command) {
|
||||||
|
return str_replace($full_command, "", $text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function normalizeDir($dir) {
|
||||||
|
$dir = str_replace("//", "/", $dir);
|
||||||
|
$dir = str_replace("/./", "/", $dir);
|
||||||
|
$dir = preg_replace("#^./#", "", $dir);
|
||||||
|
$dir = str_replace("~", '$HOME', $dir);
|
||||||
|
$dir = preg_replace("#/$#", "", $dir);
|
||||||
|
return $dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sameDir($dir1, $dir2) {
|
||||||
|
return BashInterpreter::normalizeDir($dir1) == BashInterpreter::normalizeDir($dir2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Mode {
|
||||||
|
|
||||||
|
// db: awfy_mode
|
||||||
|
function __construct($id) {
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function vendor() {
|
||||||
|
$qMode = mysql_query("SELECT vendor_id
|
||||||
|
FROM awfy_mode
|
||||||
|
WHERE id = {$this->id}");
|
||||||
|
$mode = mysql_fetch_object($qMode);
|
||||||
|
return $mode->vendor_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mode() {
|
||||||
|
$qMode = mysql_query("SELECT mode
|
||||||
|
FROM awfy_mode
|
||||||
|
WHERE id = {$this->id}");
|
||||||
|
$mode = mysql_fetch_object($qMode);
|
||||||
|
return $mode->mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function id() {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class QueuedTask {
|
||||||
|
|
||||||
|
// db: control_task_queue
|
||||||
|
function __construct($id) {
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBusy() {
|
||||||
|
mysql_query("UPDATE control_task_queue SET busy = 1 WHERE id = {$this->id}") or die(mysql_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFinished() {
|
||||||
|
mysql_query("DELETE FROM control_task_queue WHERE id = {$this->id}");
|
||||||
|
}
|
||||||
|
|
||||||
|
function task() {
|
||||||
|
$qTask = mysql_query("SELECT task
|
||||||
|
FROM control_task_queue
|
||||||
|
WHERE id = {$this->id}");
|
||||||
|
$task = mysql_fetch_object($qTask);
|
||||||
|
return $task->task;
|
||||||
|
}
|
||||||
|
|
||||||
|
function id() {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once("QueuedTask.php");
|
||||||
|
|
||||||
|
class TaskQueue {
|
||||||
|
|
||||||
|
// db: control_task_queue
|
||||||
|
function __construct($unit_id) {
|
||||||
|
$this->unit_id = $unit_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns if there is a task still running.
|
||||||
|
function has_active_task() {
|
||||||
|
$qTask = mysql_query("SELECT *
|
||||||
|
FROM control_task_queue
|
||||||
|
WHERE control_unit_id = {$this->unit} AND busy = 1
|
||||||
|
ORDER BY id LIMIT 1");
|
||||||
|
return mysql_num_rows($qTask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has_queued_tasks() {
|
||||||
|
$qTask = mysql_query("SELECT *
|
||||||
|
FROM control_task_queue
|
||||||
|
WHERE control_unit_id = $unit and busy = 0
|
||||||
|
ORDER BY id LIMIT 1");
|
||||||
|
return mysql_num_rows($qTask) != 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function pop() {
|
||||||
|
$qTask = mysql_query("SELECT id
|
||||||
|
FROM control_task_queue
|
||||||
|
WHERE control_unit_id = $unit and busy = 0
|
||||||
|
ORDER BY id LIMIT 1");
|
||||||
|
$task = mysql_fetch_object($qTask);
|
||||||
|
|
||||||
|
$task = QueuedTask($task->id);
|
||||||
|
$task->setBusy();
|
||||||
|
|
||||||
|
return $task;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
include_once "BashInterpreter.php";
|
||||||
|
include_once "Task.php";
|
||||||
|
|
||||||
|
class ManipulateTask extends Task {
|
||||||
|
|
||||||
|
public function update_benchmarks($new_benchmarks) {
|
||||||
|
//Note: Impossible to add new benchmarks using this command. Only possible to prune ones.
|
||||||
|
$old_benchmarks = $this->benchmarks();
|
||||||
|
$removed_benchmarks = array_diff($old_benchmarks, $new_benchmarks);
|
||||||
|
foreach($removed_benchmarks as $removed) {
|
||||||
|
$this->task = BashInterpreter::removeFlagFromCommands($this->task, "python execute.py", "-b ".$removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->optimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update_configs($new_configs) {
|
||||||
|
//Note: Impossible to add new configs using this command. Only possible to prune ones.
|
||||||
|
$old_configs= $this->configs();
|
||||||
|
$removed_configs = array_diff($old_configs, $new_configs);
|
||||||
|
foreach($removed_configs as $removed) {
|
||||||
|
$this->task = BashInterpreter::removeFlagFromCommands($this->task, "python execute.py", "-c ".$removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->optimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update_engines($new_engines) {
|
||||||
|
//Note: Impossible to add new engines using this command. Only possible to prune ones.
|
||||||
|
$old_engines = $this->engines();
|
||||||
|
$removed_engines = array_diff($old_engines, $new_engines);
|
||||||
|
|
||||||
|
// Build engines
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python build.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$source_matches = BashInterpreter::matchFlag($command, "-s");
|
||||||
|
$engine = $this->source_rules()[$source_matches[0]];
|
||||||
|
print_r($removed_engines);
|
||||||
|
if (in_array($engine, $removed_engines)) {
|
||||||
|
$this->removeBuildOrDownloadCommand($command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->optimize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update_modes($modes) {
|
||||||
|
$engines = [];
|
||||||
|
$configs = [];
|
||||||
|
$mode_rules = array_flip($this->mode_rules());
|
||||||
|
|
||||||
|
foreach ($modes as $mode) {
|
||||||
|
$rule = $mode_rules[$mode];
|
||||||
|
$rule = split(",", $rule);
|
||||||
|
$engines[] = $rule[0];
|
||||||
|
$configs[] = $rule[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->update_engines($engines);
|
||||||
|
$this->update_configs($configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTipRevision() {
|
||||||
|
$this->removeRevisionInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRevision($new_revision) {
|
||||||
|
$this->removeRevisionInfo();
|
||||||
|
$this->task = BashInterpreter::addFlagToCommands($this->task, "python build.py", "-r ".$new_revision);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeRevisionInfo() {
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python download.py");
|
||||||
|
if (count($commands) != 0)
|
||||||
|
throw new Exception("Not yet supported to specify revision for downloaded builds.");
|
||||||
|
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python build.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$revision_matches = BashInterpreter::matchFlag($command, "-r");
|
||||||
|
for ($revision_matches as $revision) {
|
||||||
|
$this->task = BashInterpreter::removeFlagFromCommand($this->task, $command, "-r ".$revision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeBuildOrDownloadCommand($command) {
|
||||||
|
$output_matches = BashInterpreter::matchFlag($command, "-o");
|
||||||
|
$this->task = BashInterpreter::removeCommand($this->task, $command);
|
||||||
|
if (count($output_matches) == 0) {
|
||||||
|
// If there was no output dir specified, remove all executes where no engine dir is given.
|
||||||
|
// or where the default 'output' dir is specified.
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python execute.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$engine_matches = BashInterpreter::matchFlag($command, "-e");
|
||||||
|
if (count($engine_matches) == 0) {
|
||||||
|
$this->task = BashInterpreter::removeCommand($this->task, $command);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($engine_matches as $engineDir) {
|
||||||
|
if (BashInterpreter::sameDir($engineDir, "output")) {
|
||||||
|
$this->task = BashInterpreter::removeFlagFromCommand($this->task, $command, "-e ".$engineDir);
|
||||||
|
if (count($engine_matches) == 1)
|
||||||
|
$this->task = BashInterpreter::removeCommand($this->task, $command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$outputDir = $output_matches[0];
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python execute.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$engine_matches = BashInterpreter::matchFlag($command, "-e");
|
||||||
|
foreach ($engine_matches as $engineDir) {
|
||||||
|
if (BashInterpreter::sameDir($engineDir, $outputDir)) {
|
||||||
|
$this->task = BashInterpreter::removeFlagFromCommand($this->task, $command, "-e ".$engineDir);
|
||||||
|
if (count($engine_matches) == 1)
|
||||||
|
$this->task = BashInterpreter::removeCommand($this->task, $command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function optimize() {
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python execute.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
// Any execute without benchmarks don't need to get run.
|
||||||
|
if (count(BashInterpreter::matchFlag($command, "-b")) == 0)
|
||||||
|
$this->task = BashInterpreter::removeCommand($this->task, $command);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once("ManipulateTask.php");
|
||||||
|
require_once("DB/Mode.php");
|
||||||
|
|
||||||
|
class RetriggerController {
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->tasks = [];
|
||||||
|
$this->unit_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromUnit($unit_id) {
|
||||||
|
$retrigger = new RetriggerController();
|
||||||
|
$retrigger->unit_id = $unit_id;
|
||||||
|
|
||||||
|
$qTask = mysql_query("SELECT * FROM control_tasks WHERE control_unit_id = $unit_id");
|
||||||
|
while ($task = mysql_fetch_object($qTask)) {
|
||||||
|
$task = new ManipulateTask($task);
|
||||||
|
$retrigger->tasks[] = $task;
|
||||||
|
}
|
||||||
|
return $retrigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromMachine($machine, $mode_id = 0) {
|
||||||
|
$retrigger = new RetriggerController();
|
||||||
|
$mode = new Mode($mode_id);
|
||||||
|
|
||||||
|
$qTask = mysql_query("SELECT * FROM control_tasks WHERE machine_id = $machine");
|
||||||
|
while ($task = mysql_fetch_object($qTask)) {
|
||||||
|
if (!($mode_id == 0 || $task->mode_id == 0 || $task->mode_id == $mode_id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$task = new ManipulateTask($task);
|
||||||
|
if ($mode_id != 0)
|
||||||
|
$task->update_modes($mode->mode());
|
||||||
|
|
||||||
|
$retrigger->tasks[] = $task;
|
||||||
|
|
||||||
|
if ($this->unit_id != 0 && $this->unit_id != $task->control_unit_id)
|
||||||
|
throw new Exception("Only one machine allowed.");
|
||||||
|
|
||||||
|
$this->unit_id = $task->control_unit_id;
|
||||||
|
}
|
||||||
|
return $retrigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRevision($revision) {
|
||||||
|
foreach ($this->tasks as $task) {
|
||||||
|
$task->setRevision($revision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enqueue() {
|
||||||
|
if ($this->unit_id == 0)
|
||||||
|
throw new Exception("No control_unit specified.");
|
||||||
|
|
||||||
|
foreach ($this->tasks as $task) {
|
||||||
|
mysql_query("INSERT INTO control_task_queue
|
||||||
|
(control_unit_id, task)
|
||||||
|
VALUES ({$this->unit_id}, '".mysql_escape_string($task)."')");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Task {
|
||||||
|
|
||||||
|
// The build function contains the 'source' it needs to fetch
|
||||||
|
// the code from. We need to know which source is which engine.
|
||||||
|
// This makes the transition from source to engine.
|
||||||
|
// Note: an engine can have multiple sources.
|
||||||
|
public function source_rules() {
|
||||||
|
return [
|
||||||
|
"mozilla" => "firefox",
|
||||||
|
"v8" => "chrome",
|
||||||
|
"webkit" => "webkit"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// The execute function looks at engine+config to decide which
|
||||||
|
// mode it should send this data to. These contain the default rules.
|
||||||
|
// Though it is possible to add some extra rules in the task
|
||||||
|
// itself. These are not accounted for (TODO).
|
||||||
|
public function mode_rules() {
|
||||||
|
return [
|
||||||
|
"firefox,default" => "jmim",
|
||||||
|
"firefox,noasmjs" => "noasmjs",
|
||||||
|
"firefox,unboxedobjects" => "unboxedobjects",
|
||||||
|
"firefox,testbedregalloc" => "testbed",
|
||||||
|
"chrome,default" => "v8",
|
||||||
|
"chrome,turbofan" => "v8-turbofan",
|
||||||
|
"webkit,default" => "jsc",
|
||||||
|
"native,default" => "clang",
|
||||||
|
"servo,default" => "servo"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct($task) {
|
||||||
|
$this->task = $task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function task() {
|
||||||
|
return $this->task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configs() {
|
||||||
|
$configs = [];
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python execute.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$config_matches = BashInterpreter::matchFlag($command, "-c");
|
||||||
|
foreach ($config_matches as $match) {
|
||||||
|
$configs[] = $match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array_unique($configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function engines() {
|
||||||
|
$engines = [];
|
||||||
|
|
||||||
|
// Fetch all engines that have been build.
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python build.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$source_matches = BashInterpreter::matchFlag($command, "-s");
|
||||||
|
if (count($source_matches) != 1)
|
||||||
|
throw new Error("Expected one match.");
|
||||||
|
|
||||||
|
$engines[] = $this->source_rules()[$source_matches[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all engines that have been downloaded.
|
||||||
|
// TODO.
|
||||||
|
return array_unique($engines);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function modes() {
|
||||||
|
$configs = $this->configs();
|
||||||
|
$engines = $this->engines();
|
||||||
|
$mode_rules = $this->mode_rules();
|
||||||
|
|
||||||
|
$modes = [];
|
||||||
|
foreach ($configs as $config) {
|
||||||
|
foreach ($engines as $engine) {
|
||||||
|
$rule = $engine.",".$config;
|
||||||
|
if (isset($mode_rules[$rule])) {
|
||||||
|
$modes[] = $mode_rules[$rule];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $modes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function benchmarks() {
|
||||||
|
$configs = [];
|
||||||
|
$commands = BashInterpreter::matchCommand($this->task, "python execute.py");
|
||||||
|
foreach ($commands as $command) {
|
||||||
|
$config_matches = BashInterpreter::matchFlag($command, "-b");
|
||||||
|
foreach ($config_matches as $match) {
|
||||||
|
$configs[] = $match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return array_unique($configs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,48 +5,36 @@
|
||||||
|
|
||||||
require_once("internals.php");
|
require_once("internals.php");
|
||||||
|
|
||||||
|
require_once("lib/RetriggerController.php");
|
||||||
|
require_once("lib/DB/TaskQueue.php");
|
||||||
|
require_once("lib/DB/QueuedTask.php");
|
||||||
|
|
||||||
init_database();
|
init_database();
|
||||||
|
|
||||||
if (isset($_GET["unit"]) && is_numeric($_GET["unit"])) {
|
if ($unit = GET_int("unit")) {
|
||||||
$unit = (int)$_GET["unit"];
|
|
||||||
|
|
||||||
$qTask = mysql_query("SELECT *
|
$queue = new TaskQueue($unit);
|
||||||
FROM control_task_queue
|
if ($queue->has_active_task())
|
||||||
WHERE control_unit_id = $unit AND busy = 1
|
|
||||||
ORDER BY id LIMIT 1");
|
|
||||||
if (mysql_num_rows($qTask) != 0) {
|
|
||||||
slack("requesting new task, while old task is still running!");
|
slack("requesting new task, while old task is still running!");
|
||||||
|
|
||||||
|
if (!$queue->has_queued_tasks())
|
||||||
|
$retrigger = RetriggerController::fromUnit($unit);
|
||||||
|
$retrigger->enqueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$task = $queue->pop();
|
||||||
|
|
||||||
$qTask = mysql_query("SELECT *
|
echo json_encode([
|
||||||
FROM control_task_queue
|
"task" => $task->task(),
|
||||||
WHERE control_unit_id = $unit and busy = 0
|
"id" => $task->id()
|
||||||
ORDER BY id LIMIT 1");
|
]);
|
||||||
if (mysql_num_rows($qTask) == 0) {
|
|
||||||
$qTask = mysql_query("SELECT task FROM control_tasks WHERE control_unit_id = $unit");
|
|
||||||
while ($task = mysql_fetch_object($qTask)) {
|
|
||||||
mysql_query("INSERT INTO control_task_queue
|
|
||||||
(control_unit_id, task)
|
|
||||||
VALUES ($unit, '".mysql_escape_string($tasks->task)."')");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$qTask = mysql_query("SELECT *
|
|
||||||
FROM control_task_queue
|
|
||||||
WHERE control_unit_id = $unit and busy = 0
|
|
||||||
ORDER BY id LIMIT 1");
|
|
||||||
$task = mysql_fetch_object($qTask);
|
|
||||||
echo json_encode(Array("task" => $task->task,
|
|
||||||
"id" => $task->id));
|
|
||||||
|
|
||||||
mysql_query("UPDATE control_task_queue SET busy = 1 WHERE id = ".$task->id);
|
|
||||||
|
|
||||||
die();
|
die();
|
||||||
|
|
||||||
} else if (isset($_GET["finish"]) && is_numeric($_GET["finish"])) {
|
} else if ($task_id = GET_int("finish")) {
|
||||||
$task_id = $_GET["finish"];
|
|
||||||
mysql_query("DELETE FROM control_task_queue WHERE id = ".$task_id);
|
$task = QueuedTask($task_id);
|
||||||
|
$task->setFinished();
|
||||||
|
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче