11 Commits

8 changed files with 96 additions and 36 deletions

View File

@@ -30,11 +30,14 @@ class Net_Gearman_Job_HandBrake extends Net_Gearman_Job_Common implements Rippin
$this->job = RippingCluster_Job::fromId($args['rip_options']['id']); $this->job = RippingCluster_Job::fromId($args['rip_options']['id']);
// Substitute a temporary output filename into the rip options
$args['temp_output_filename'] = tempnam($config->get('rips.temp_dir', '/tmp'), 'hbr_');
$handbrake_cmd_raw = array( $handbrake_cmd_raw = array(
'-n', $config->get('rips.nice'), '-n', $config->get('rips.nice'),
$config->get('rips.handbrake_binary'), $config->get('rips.handbrake_binary'),
self::evaluateOption($args['rip_options'], 'input_filename', '-i'), self::evaluateOption($args['rip_options'], 'input_filename', '-i'),
self::evaluateOption($args['rip_options'], 'output_filename', '-o'), self::evaluateOption($args, 'temp_output_filename', '-o'),
self::evaluateOption($args['rip_options'], 'title'), self::evaluateOption($args['rip_options'], 'title'),
self::evaluateOption($args['rip_options'], 'format', '-f'), self::evaluateOption($args['rip_options'], 'format', '-f'),
self::evaluateOption($args['rip_options'], 'video_codec', '-e'), self::evaluateOption($args['rip_options'], 'video_codec', '-e'),
@@ -61,12 +64,24 @@ class Net_Gearman_Job_HandBrake extends Net_Gearman_Job_Common implements Rippin
list($return_val, $stdout, $stderr) = RippingCluster_ForegroundTask::execute($handbrake_cmd, null, null, null, array($this, 'callbackOutput'), array($this, 'callbackOutput'), $this); list($return_val, $stdout, $stderr) = RippingCluster_ForegroundTask::execute($handbrake_cmd, null, null, null, array($this, 'callbackOutput'), array($this, 'callbackOutput'), $this);
if ($return_val) { if ($return_val) {
// Remove any temporary output files
if (file_exists($args['temp_output_filename'])) {
unlink($args['temp_output_filename']);
}
$this->fail($return_val); $this->fail($return_val);
} else { } else {
$this->job->updateStatus(RippingCluster_JobStatus::COMPLETE); // Move the temporary output file to the desired destination
$this->complete( array( $move = rename($args['temp_output_filename'], $args['rip_options']['output_filename']);
'id' => $this->job->id() if ($move) {
)); $this->job->updateStatus(RippingCluster_JobStatus::COMPLETE);
$this->complete( array(
'id' => $this->job->id()
));
} else {
RippingCluster_WorkerLogEntry::error($log, $this->job->id(), "Failed to move temporary output file to proper destination. File retained as '{$args['temp_output_filename']}'.");
$this->job->updateStatus(RippingCluster_JobStatus::FAILED);
$this->fail('-1');
}
} }
} }

View File

@@ -271,7 +271,20 @@ class RippingCluster_Job {
return $new_status; return $new_status;
} }
public function isFinished() {
$current_status = $this->currentStatus()->status();
return ($current_status == RippingCluster_JobStatus::COMPLETE || $current_status == RippingCluster_JobStatus::FAILED);
}
public function outputFilesize() {
if (file_exists($this->destination_filename)) {
return filesize($this->destination_filename);
}
return null;
}
public function calculateETA() { public function calculateETA() {
$current_status = $this->currentStatus(); $current_status = $this->currentStatus();
if ($current_status->status() != RippingCluster_JobStatus::RUNNING) { if ($current_status->status() != RippingCluster_JobStatus::RUNNING) {

View File

@@ -4,12 +4,20 @@ class RippingCluster_LogEntry extends SihnonFramework_LogEntry {
protected $job_id; protected $job_id;
protected static $types;
public static function initialise() { public static function initialise() {
self::$types['job_id'] = 'int'; // Copy the list of datatypes from the parent
// We can't modify it in place, else we'll break any logging done inside the SihnonFramework tree
// or other subclass trees.
static::$types = parent::$types;
// Add the new data types for this subclass
static::$types['job_id'] = 'int';
} }
protected function __construct($level, $category, $ctime, $pid, $file, $line, $message, $job_id) { protected function __construct($level, $category, $ctime, $hostname, $progname, $pid, $file, $line, $message, $job_id) {
parent::__construct($level, $category, $ctime, $pid, $file, $line, $message); parent::__construct($level, $category, $ctime, $hostname, $progname, $pid, $file, $line, $message);
$this->job_id = $job_id; $this->job_id = $job_id;
} }
@@ -19,6 +27,8 @@ class RippingCluster_LogEntry extends SihnonFramework_LogEntry {
$row['level'], $row['level'],
$row['category'], $row['category'],
$row['ctime'], $row['ctime'],
$row['hostname'],
$row['progname'],
$row['pid'], $row['pid'],
$row['file'], $row['file'],
$row['line'], $row['line'],
@@ -32,8 +42,8 @@ class RippingCluster_LogEntry extends SihnonFramework_LogEntry {
$this->level, $this->level,
$this->category, $this->category,
$this->ctime, $this->ctime,
static::$hostname, $this->hostname,
static::$progname, $this->progname,
$this->pid, $this->pid,
$this->file, $this->file,
$this->line, $this->line,
@@ -48,7 +58,7 @@ class RippingCluster_LogEntry extends SihnonFramework_LogEntry {
protected static function log($logger, $severity, $job_id, $message, $category = SihnonFramework_Log::CATEGORY_DEFAULT) { protected static function log($logger, $severity, $job_id, $message, $category = SihnonFramework_Log::CATEGORY_DEFAULT) {
$backtrace = debug_backtrace(false); $backtrace = debug_backtrace(false);
$entry = new self($severity, $category, time(), getmypid(), $backtrace[1]['file'], $backtrace[1]['line'], $message, $job_id); $entry = new self($severity, $category, time(), static::$localHostname, static::$localProgname, getmypid(), $backtrace[1]['file'], $backtrace[1]['line'], $message, $job_id);
$logger->log($entry); $logger->log($entry);
} }

View File

@@ -11,24 +11,29 @@ class RippingCluster_Main extends SihnonFramework_Main {
protected function __construct() { protected function __construct() {
parent::__construct(); parent::__construct();
$request_string = isset($_GET['l']) ? $_GET['l'] : '';
$this->request = new RippingCluster_RequestParser($request_string);
if (HBC_File == 'index') {
$this->smarty = new Smarty();
$this->smarty->template_dir = './source/templates';
$this->smarty->compile_dir = './tmp/templates';
$this->smarty->cache_dir = './tmp/cache';
$this->smarty->config_dir = './config';
$this->smarty->registerPlugin('modifier', 'formatDuration', array('RippingCluster_Main', 'formatDuration'));
$this->smarty->assign('version', '0.1'); $request_string = isset($_GET['l']) ? $_GET['l'] : '';
$this->smarty->assign('messages', array());
$this->request = new RippingCluster_RequestParser($request_string);
$this->smarty->assign('base_uri', $this->base_uri);
switch (HBC_File) {
case 'index': {
$smarty_tmp = '/tmp/ripping-cluster';
$this->smarty = new Smarty();
$this->smarty->template_dir = static::makeAbsolutePath('./source/templates');
$this->smarty->compile_dir = static::makeAbsolutePath($smarty_tmp . '/tmp/templates');
$this->smarty->cache_dir = static::makeAbsolutePath($smarty_tmp . '/tmp/cache');
$this->smarty->config_dir = static::makeAbsolutePath($smarty_tmp . '/config');
$this->smarty->registerPlugin('modifier', 'formatDuration', array('RippingCluster_Main', 'formatDuration'));
$this->smarty->registerPlugin('modifier', 'formatFilesize', array('RippingCluster_Main', 'formatFilesize'));
$this->smarty->assign('version', '0.1');
$this->smarty->assign('messages', array());
$this->smarty->assign('base_uri', $this->base_uri);
} break;
} }
} }
@@ -37,14 +42,14 @@ class RippingCluster_Main extends SihnonFramework_Main {
} }
/** /**
* *
* @return RippingCluster_RequestParser * @return RippingCluster_RequestParser
*/ */
public function request() { public function request() {
return $this->request; return $this->request;
} }
} }
?> ?>

View File

@@ -1,9 +1,9 @@
<?php <?php
require_once '/etc/ripping-cluster/config.php'; require_once '/etc/ripping-cluster/config.php';
require_once RippingCluster_Lib . 'RippingCluster/Main.class.php'; require_once SihnonFramework_Lib . 'SihnonFramework/Main.class.php';
RippingCluster_Main::registerAutoloadClasses('SihnonFramework', SihnonFramework_Lib, SihnonFramework_Main::registerAutoloadClasses('SihnonFramework', SihnonFramework_Lib,
'RippingCluster', RippingCluster_Lib); 'RippingCluster', RippingCluster_Lib);
?> ?>

View File

@@ -6,6 +6,7 @@ require '_inc.php';
try { try {
$main = RippingCluster_Main::instance(); $main = RippingCluster_Main::instance();
RippingCluster_LogEntry::setLocalProgname('webui');
$smarty = $main->smarty(); $smarty = $main->smarty();
$page = new RippingCluster_Page($smarty, $main->request()); $page = new RippingCluster_Page($smarty, $main->request());

View File

@@ -43,7 +43,12 @@
{assign var=current_status value=$job->currentStatus()} {assign var=current_status value=$job->currentStatus()}
<tr> <tr>
<td><a href="{$base_uri}job-details/id/{$job->id()}" title="View job details">{$job->name()}</a></td> <td><a href="{$base_uri}job-details/id/{$job->id()}" title="View job details">{$job->name()}</a></td>
<td>{$job->destinationFilename()}</td> <td>
{$job->destinationFilename()}
{if $job->isFinished()}
({$job->outputFilesize()|formatFilesize})
{/if}
</td>
<td>{$job->title()}</td> <td>{$job->title()}</td>
<td> <td>
{$current_status->statusName()} {$current_status->statusName()}

View File

@@ -2,7 +2,17 @@
define('HBC_File', 'worker'); define('HBC_File', 'worker');
require_once '/etc/ripping-cluster/config.php'; $options = array();
if (isset($_SERVER['argv'])) {
$options = getopt('c:', array('config:'));
}
if (isset($options['config'])) {
require_once $options['config'];
} else {
require_once '/etc/ripping-cluster/config.php';
}
require_once(SihnonFramework_Lib . 'SihnonFramework/Main.class.php'); require_once(SihnonFramework_Lib . 'SihnonFramework/Main.class.php');
require_once 'Net/Gearman/Worker.php'; require_once 'Net/Gearman/Worker.php';
@@ -16,6 +26,7 @@ try {
set_time_limit(0); set_time_limit(0);
$main = RippingCluster_Main::instance(); $main = RippingCluster_Main::instance();
RippingCluster_LogEntry::setLocalProgname('ripping-cluster-worker');
$smarty = $main->smarty(); $smarty = $main->smarty();
$worker = new RippingCluster_Worker(); $worker = new RippingCluster_Worker();