Core class updates

Improved database abstraction class to support insert and select queries
in various forms.
Added classes for pulling log entries back out of the database.
Updated Job class to describe a known job in the database, and added
JobStatus to track status updates on jobs.
Updated Config class to connect to the database, and load all settings
on startup.
Improved the class autoloader to support Exceptions in a single file as
a special case, and added this file.
This commit is contained in:
2010-03-18 02:00:53 +00:00
parent 3603445a5b
commit a9ebf6e0cb
11 changed files with 541 additions and 9 deletions

View File

@@ -0,0 +1,13 @@
<?php
class HandBrakeCluster_ClientLogEntry extends HandBrakeCluster_LogEntry {
public static function initialise() {
parent::$table_name = 'client_log';
}
};
HandBrakeCluster_ClientLogEntry::initialise();
?>

View File

@@ -2,10 +2,53 @@
class HandBrakeCluster_Config {
private $filename;
private $dbconfig;
private $database;
public function __construct($filename) {
$this->filename = $filename;
private $databaseConfig = array();
private $settings = array();
public function __construct($dbconfig) {
$this->dbconfig = $dbconfig;
$this->parseDatabaseConfig();
}
public function parseDatabaseConfig() {
$this->databaseConfig = parse_ini_file($this->dbconfig);
}
public function getDatabase($key) {
if (!isset($this->databaseConfig[$key])) {
throw new HandBrakeCluster_Exception_DatabaseConfigMissing($key);
}
return $this->databaseConfig[$key];
}
public function setDatabase(HandBrakeCluster_Database $database) {
$this->database = $database;
$this->preload();
}
public function preload() {
if (!$this->database) {
throw new HandBrakeCluster_Exception_NoDatabaseConnection();
}
$this->settings = $this->database->selectAssoc('SELECT name,value FROM settings', 'name', 'value');
}
public function exists($key) {
return isset($this->settings[$key]);
}
public function get($key) {
if (!isset($this->settings[$key])) {
throw new HandBrakeCluster_Exception_UnknownSetting($key);
}
return $this->settings[$key];
}
};

View File

@@ -3,9 +3,95 @@
class HandBrakeCluster_Database {
private $config;
private $dbh;
private $hostname;
private $username;
private $password;
private $dbname;
private $prepared_statements = array();
public function __construct(HandBrakeCluster_Config $config) {
$this->config = $config;
$this->hostname = $this->config->getDatabase('hostname');
$this->username = $this->config->getDatabase('username');
$this->password = $this->config->getDatabase('password');
$this->dbname = $this->config->getDatabase('dbname');
try {
$this->dbh = new PDO("mysql:host={$this->hostname};dbname={$this->dbname}", $this->username, $this->password);
} catch (PDOException $e) {
throw new HandBrakeCluster_Exception_DatabaseConnectionFailed($e->getMessage());
}
}
public function __destruct() {
$this->dbh = null;
}
public function selectAssoc($sql, $key_col, $value_col) {
$results = array();
foreach ($this->dbh->query($sql) as $row) {
$results[$row[$key_col]] = $row[$value_col];
}
return $results;
}
public function selectList($sql, $bind_params = null) {
if ($bind_params) {
$stmt = $this->dbh->prepare($sql);
foreach ($bind_params as $param) {
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
}
$result = $stmt->execute();
if (!$result) {
throw new HandBrakeCluster_Exception_DatabaseQueryFailed();
}
return $stmt->fetchAll();
} else {
$results = array();
$result = $this->dbh->query($sql);
foreach ($result as $row) {
$results[] = $row;
}
return $results;
}
}
public function selectOne($sql, $bind_params = null) {
$rows = $this->selectList($sql, $bind_params);
if (count($rows) != 1) {
throw new HandBrakeCluster_Exception_ResultCountMismatch(count($rows));
}
return $rows[0];
}
public function insert($sql, $bind_params = null) {
$stmt = $this->dbh->prepare($sql);
if ($bind_params) {
foreach ($bind_params as $param) {
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
}
}
return $stmt->execute();
}
public function errorInfo() {
return $this->dbh->errorInfo();
}
}

View File

@@ -0,0 +1,13 @@
<?php
class HandBrakeCluster_Exception extends Exception {};
class HandBrakeCluster_Exception_DatabaseConfigMissing extends Exception {};
class HandBrakeCluster_Exception_DatabaseConnectFailed extends Exception {};
class HandBrakeCluster_Exception_NoDatabaseConnection extends Exception {};
class HandBrakeCluster_Exception_DatabaseQueryFailed extends Exception {};
class HandBrakeCluster_Exception_ResultCountMismatch extends Exception {};
class HandBrakeCluster_Exception_UnknownSetting extends Exception {};
?>

View File

@@ -3,15 +3,127 @@
class HandBrakeCluster_Job {
private $id;
private $name;
private $source;
private $destination;
private $title;
private $format;
private $video_codec;
private $video_width;
private $video_height;
private $quantizer;
private $deinterlace;
private $audio_tracks;
private $audio_codecs;
private $audio_names;
private $subtitle_tracks;
public function __construct($id) {
private $statuses = null;
public function __construct($id, $name, $source, $destination, $title, $format, $video_codec, $video_width, $video_height, $quantizer, $deinterlace, $audio_tracks, $audio_codecs, $audio_names, $subtitle_tracks) {
$this->id = $id;
$this->name = $name;
$this->source = $source;
$this->destination = $destination;
$this->title = $title;
$this->format = $format;
$this->video_codec = $video_codec;
$this->video_width = $video_width;
$this->video_height = $video_height;
$this->quantizer = $quantizer;
$this->deinterlace = $deinterlace;
$this->audio_tracks = $audio_tracks;
$this->audio_codecs = $audio_codecs;
$this->audio_names = $audio_names;
$this->subtitle_tracks = $subtitle_tracks;
}
public static function fromDatabaseRow($row) {
return new HandBrakeCluster_Job(
$row['id'],
$row['name'],
$row['source'],
$row['destination'],
$row['title'],
$row['format'],
$row['video_codec'],
$row['video_width'],
$row['video_height'],
$row['quantizer'],
$row['deinterlace'],
$row['audio_tracks'],
$row['audio_codecs'],
$row['audio_names'],
$row['subtitle_tracks']
);
}
public static function fromId($id) {
$database = HandBrakeCluster_Main::instance()->database();
return HandBrakeCluster_Job::fromDatabaseRow(
$database->selectOne('SELECT * FROM jobs WHERE id=:id', array(
array('name' => 'id', 'value' => $id, 'type' => PDO::PARAM_INT)
)
)
);
}
public static function all() {
$jobs = array();
$database = HandBrakeCluster_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM jobs') as $row) {
$jobs[] = self::fromDatabaseRow($row);
}
return $jobs;
}
public static function allWithStatus($status) {
$jobs = array();
$database = HandBrakeCluster_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM jobs WHERE id IN (SELECT id FROM job_status_current WHERE status=:status)', array(
array('name' => 'status', 'value' => $status, 'type' => PDO::PARAM_INT)
)) as $row) {
$jobs[] = self::fromDatabaseRow($row);
}
return $jobs;
}
protected function loadStatuses() {
if ($this->statuses == null) {
$this->statuses = HandBrakeCluster_JobStatus::allForJob($this->id);
}
}
public function currentStatus() {
$this->loadStatuses();
return $this->statuses[count($this->statuses) - 1];
}
public function id() {
return $this->id;
}
public function name() {
return $this->name;
}
public function source() {
return $this->source;
}
public function destination() {
return $this->destination;
}
public function title() {
return $this->title;
}
};
?>

View File

@@ -0,0 +1,73 @@
<?php
class HandBrakeCluster_JobStatus {
const QUEUED = 0;
const FAILED = 1;
const RUNNING = 2;
const COMPLETE = 3;
private static $status_names = array(
self::QUEUED => 'Queued',
self::FAILED => 'Failed',
self::RUNNING => 'Running',
self::COMPLETE => 'Complete'
);
protected $id;
protected $job_id;
protected $status;
protected $ctime;
protected function __construct($id, $job_id, $status, $ctime) {
$this->id = $id;
$this->job_id = $job_id;
$this->status = $status;
$this->ctime = $ctime;
}
public static function fromDatabaseRow($row) {
return new HandBrakeCluster_JobStatus(
$row['id'],
$row['job_id'],
$row['status'],
$row['ctime']
);
}
public static function allForJob($job_id) {
$statuses = array();
$database = HandBrakeCluster_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM job_status WHERE job_id=:job_id ORDER BY ctime ASC', array(
array('name' => 'job_id', 'value' => $job_id, 'type' => PDO::PARAM_INT),
)) as $row) {
$statuses[] = HandBrakeCluster_JobStatus::fromDatabaseRow($row);
}
return $statuses;
}
public function id() {
return $this->id;
}
public function jobId() {
return $this->job_id;
}
public function status() {
return $this->status;
}
public function statusName() {
return self::$status_names[$this->status];
}
public function ctime() {
return $this->ctime;
}
};
?>

View File

@@ -2,14 +2,58 @@
class HandBrakeCluster_Log {
private static $hostname = '';
private $database;
private $config;
public function __construct(HandBrakeCluster_Database $database, HandBrakeCluster_Config $config) {
$this->database = $database;
$this->config = $config;
}
public function log($severity, $message, $job_id = 0) {
$result = $this->database->insert('INSERT INTO client_log (job_id,level,ctime,pid,hostname,progname,line,message) VALUES(:job_id, :level, :ctime, :pid, :hostname, :progname, :line, :message)',
array(
array('name' => 'job_id', 'value' => $job_id, 'type' => PDO::PARAM_INT),
array('name' => 'level', 'value' => $severity, 'type' => PDO::PARAM_STR),
array('name' => 'ctime', 'value' => time(), 'type' => PDO::PARAM_INT),
array('name' => 'pid', 'value' => 0, 'type' => PDO::PARAM_INT),
array('name' => 'hostname', 'value' => self::$hostname, 'type' => PDO::PARAM_STR),
array('name' => 'progname', 'value' => 'webui', 'type' => PDO::PARAM_STR),
array('name' => 'line', 'value' => 0, 'type' => PDO::PARAM_INT),
array('name' => 'message', 'value' => $message, 'type' => PDO::PARAM_STR)
)
);
if (!$result) {
var_dump($this->database->errorInfo());
}
}
public function debug($message, $job_id = 0) {
return $this->log('DEBUG', $message, $job_id);
}
public function info($messgae, $job_id = 0) {
return $this->log('INFO', $message, $job_id);
}
public function warning($message, $job_id = 0) {
return $this->log('WARNING', $message, $job_id);
}
public function error($message, $job_id = 0) {
return $this->log('ERROR', $message, $job_id);
}
public static function initialise() {
self::$hostname = trim(`hostname`);
}
}
HandBrakeCluster_Log::initialise();
?>

View File

@@ -0,0 +1,122 @@
<?php
abstract class HandBrakeCluster_LogEntry {
protected static $table_name = "";
protected $id;
protected $job_id;
protected $level;
protected $ctime;
protected $pid;
protected $hostname;
protected $progname;
protected $line;
protected $message;
protected function __construct($id, $job_id, $level, $ctime, $pid, $hostname, $progname, $line, $message) {
$this->id = $id;
$this->job_id = $job_id;
$this->level = $level;
$this->ctime = $ctime;
$this->pid = $pid;
$this->hostname = $hostname;
$this->progname = $progname;
$this->line = $line;
$this->message = $message;
}
public static function fromDatabaseRow($row) {
return new HandBrakeCluster_ClientLogEntry(
$row['id'],
$row['job_id'],
$row['level'],
$row['ctime'],
$row['pid'],
$row['hostname'],
$row['progname'],
$row['line'],
$row['message']
);
}
public static function fromId($id) {
$database = HandBrakeCluster_Main::instance()->database();
return HandBrakeCluster_ClientLogEntry::fromDatabaseRow(
$database->selectOne('SELECT * FROM '.self::$table_name.' WHERE id=:id', array(
array('name' => 'id', 'value' => $id, 'type' => PDO::PARAM_INT)
)
)
);
}
public static function recent($limit = 100) {
$entries = array();
$database = HandBrakeCluster_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM '.self::$table_name.' ORDER BY ctime DESC LIMIT :limit', array(
array('name' => 'limit', 'value' => $limit, 'type' => PDO::PARAM_INT)
)) as $row) {
$entries[] = self::fromDatabaseRow($row);
}
return $entries;
}
public static function recentForJob($job_id, $limit = 100) {
$entries = array();
$database = HandBrakeCluster_Main::instance()->database();
foreach ($database->selectList('SELECT * FROM '.self::$table_name.' WHERE job_id=:job_id ORDER BY ctime DESC LIMIT :limit', array(
array('name' => 'job_id', 'value' => $job_id, 'type' => PDO::PARAM_INT),
array('name' => 'limit', 'value' => $limit, 'type' => PDO::PARAM_INT)
)) as $row) {
$entries[] = self::fromDatabaseRow($row);
}
return $entries;
}
public static function allForNoJob() {
return self::allForJob(0);
}
public function id() {
return $this->id;
}
public function jobId() {
return $this->job_id;
}
public function level() {
return $this->level;
}
public function ctime() {
return $this->ctime;
}
public function pid() {
return $this->pid;
}
public function hostname() {
return $this->hostname;
}
public function progname() {
return $this->progname;
}
public function line() {
return $this->line;
}
public function message() {
return $this->message;
}
};
?>

View File

@@ -13,8 +13,16 @@ class HandBrakeCluster_Main {
private $request;
private function __construct() {
$this->smarty = new Smarty();
$request_string = isset($_GET['l']) ? $_GET['l'] : '';
$this->config = new HandBrakeCluster_Config("dbconfig.conf");
$this->database = new HandBrakeCluster_Database($this->config);
$this->config->setDatabase($this->database);
$this->log = new HandBrakeCluster_Log($this->database, $this->config);
$this->request = new HandBrakeCluster_RequestParser($request_string);
$this->smarty = new Smarty();
$this->smarty->template_dir = './templates';
$this->smarty->compile_dir = './tmp/templates';
$this->smarty->cache_dir = './tmp/cache';
@@ -23,8 +31,6 @@ class HandBrakeCluster_Main {
$this->smarty->assign('version', '0.1');
$this->smarty->assign('base_uri', '/handbrake/');
$request_string = isset($_GET['l']) ? $_GET['l'] : '';
$this->request = new HandBrakeCluster_RequestParser($request_string);
}
public static function instance() {
@@ -70,6 +76,12 @@ class HandBrakeCluster_Main {
return;
}
// Special case: All exceptions are stored in the same file
if (preg_match('/^HandBrakeCluster_Exception_/', $classname)) {
require_once('HandBrakeCluster/Exceptions.class.php');
return;
}
// Replace any underscores with directory separators
$filename = preg_replace('/_/', '/', $classname);

View File

@@ -39,6 +39,7 @@ class HandBrakeCluster_RequestParser {
if (isset($this->vars[$key])) {
return $this->vars[$key];
}
return null;
}

View File

@@ -0,0 +1,13 @@
<?php
class HandBrakeCluster_WorkerLogEntry extends HandBrakeCluster_LogEntry {
public static function initialise() {
parent::$table_name = 'worker_log';
}
};
HandBrakeCluster_WorkerLogEntry::initialise();
?>