420 lines
11 KiB
PHP
420 lines
11 KiB
PHP
<?php
|
|
|
|
define('TR_LEAVE_CLOSED', TRUE);
|
|
|
|
/**
|
|
* Auxiliary class for transport records
|
|
*
|
|
* @package Airtime
|
|
* @subpackage StorageServer
|
|
* @copyright 2010 Sourcefabric O.P.S.
|
|
* @license http://www.gnu.org/licenses/gpl.txt
|
|
*/
|
|
class TransportRecord
|
|
{
|
|
/**
|
|
* @var DB
|
|
*/
|
|
//public $dbc;
|
|
|
|
/**
|
|
* @var GreenBox
|
|
*/
|
|
private $gb;
|
|
|
|
/**
|
|
* @var array
|
|
*/
|
|
//private $config;
|
|
|
|
/**
|
|
* @var Transport
|
|
*/
|
|
private $tr;
|
|
|
|
/**
|
|
* @var boolean
|
|
*/
|
|
private $recalled = FALSE;
|
|
|
|
/**
|
|
* @var boolean
|
|
*/
|
|
private $dropped = FALSE;
|
|
|
|
|
|
/**
|
|
* @param Transport $tr
|
|
* @return TransportRecord
|
|
*/
|
|
public function __construct(&$tr)
|
|
{
|
|
$this->tr =& $tr;
|
|
$this->gb =& $tr->gb;
|
|
}
|
|
|
|
|
|
/**
|
|
* Factory method
|
|
*
|
|
* @param Transport $tr
|
|
* @param string $trtype
|
|
* transport type (see Transport::install)
|
|
* @param string $direction
|
|
* 'up' | 'down'
|
|
* @param array $defaults
|
|
* default parameters (optional, internal use)
|
|
* @return TransportRecord
|
|
*/
|
|
function create(&$tr, $trtype, $direction='up', $defaults=array())
|
|
{
|
|
global $CC_DBC, $CC_CONFIG;
|
|
$trec = new TransportRecord($tr);
|
|
$trec->trtok = $trtok = $tr->_createTransportToken();
|
|
$trec->row = array_merge($defaults,
|
|
array('trtype'=>$trtype, 'direction'=>$direction));
|
|
$trec->recalled = TRUE;
|
|
if (!isset($defaults['title'])) {
|
|
$defaults['title'] = $trec->getTitle();
|
|
if (PEAR::isError($defaults['title'])) {
|
|
return $defaults['title'];
|
|
}
|
|
}
|
|
$id = $CC_DBC->nextId($CC_CONFIG['transSequence']);
|
|
$names = "id, trtok, direction, state, trtype, start, ts";
|
|
$values = "$id, '$trtok', '$direction', 'init', '$trtype', now(), now()";
|
|
foreach ($defaults as $k => $v) {
|
|
$sqlVal = $trec->_getSqlVal($k, $v);
|
|
$names .= ", $k";
|
|
$values .= ", $sqlVal";
|
|
}
|
|
$query = "
|
|
INSERT INTO ".$CC_CONFIG['transTable']."
|
|
($names)
|
|
VALUES
|
|
($values)
|
|
";
|
|
$res = $CC_DBC->query($query);
|
|
if (PEAR::isError($res)) {
|
|
return $res;
|
|
}
|
|
return $trec;
|
|
}
|
|
|
|
|
|
/**
|
|
* Recall transport record from DB
|
|
*
|
|
* @param Transport $tr
|
|
* @param string $trtok
|
|
* transport token
|
|
* @return TransportRecord
|
|
*/
|
|
function recall(&$tr, $trtok)
|
|
{
|
|
global $CC_DBC, $CC_CONFIG;
|
|
$trec = new TransportRecord($tr);
|
|
$trec->trtok = $trtok;
|
|
$row = $CC_DBC->getRow("
|
|
SELECT
|
|
id, trtok, state, trtype, direction,
|
|
to_hex(gunid)as gunid, to_hex(pdtoken)as pdtoken,
|
|
fname, localfile, url, rtrtok, mdtrtok, uid,
|
|
expectedsize, realsize, expectedsum, realsum,
|
|
errmsg, title, jobpid
|
|
FROM ".$CC_CONFIG['transTable']."
|
|
WHERE trtok='$trtok'
|
|
");
|
|
if (PEAR::isError($row)) {
|
|
return $row;
|
|
}
|
|
if (is_null($row)) {
|
|
return PEAR::raiseError("TransportRecord::recall:".
|
|
" invalid transport token ($trtok)", TRERR_TOK
|
|
);
|
|
}
|
|
$row['pdtoken'] = StoredFile::NormalizeGunid($row['pdtoken']);
|
|
$row['gunid'] = StoredFile::NormalizeGunid($row['gunid']);
|
|
$trec->row = $row;
|
|
$trec->recalled = TRUE;
|
|
return $trec;
|
|
}
|
|
|
|
|
|
/**
|
|
* Set state of transport record
|
|
*
|
|
* @param string $newState
|
|
* @param array $data
|
|
* other data fields to set
|
|
* @param string $oldState
|
|
* check old state and do nothing if differ
|
|
* @param boolean $lock
|
|
* check lock and do nothing if differ
|
|
* @return boolean success
|
|
*/
|
|
function setState($newState, $data=array(), $oldState=NULL, $lock=NULL)
|
|
{
|
|
global $CC_CONFIG, $CC_DBC;
|
|
$set = " state='$newState', ts=now()";
|
|
if (!is_null($lock)) {
|
|
$slock = ($lock ? 'Y' : 'N');
|
|
$nlock = (!$lock);
|
|
$snlock = ($nlock ? 'Y' : 'N');
|
|
$set .= ", lock='$snlock'";
|
|
}
|
|
foreach ($data as $k => $v) {
|
|
$set .= ", $k=".$this->_getSqlVal($k, $v);
|
|
}
|
|
$r = $CC_DBC->query("
|
|
UPDATE ".$CC_CONFIG['transTable']."
|
|
SET $set
|
|
WHERE trtok='{$this->trtok}'".
|
|
(is_null($oldState) ? '' : " AND state='$oldState'").
|
|
(is_null($lock) ? '' : " AND lock = '$slock'")
|
|
);
|
|
if (PEAR::isError($r)) {
|
|
return $r;
|
|
}
|
|
// return TRUE;
|
|
$affRows = $CC_DBC->affectedRows();
|
|
if (PEAR::isError($affRows)) {
|
|
return $affRows;
|
|
}
|
|
return ($affRows == 1);
|
|
}
|
|
|
|
|
|
/**
|
|
* Return state of transport record
|
|
*
|
|
* @return string
|
|
* state
|
|
*/
|
|
function getState()
|
|
{
|
|
if (!$this->recalled) {
|
|
return PEAR::raiseError("TransportRecord::getState:".
|
|
" not recalled ({$this->trtok})", TRERR_TOK
|
|
);
|
|
}
|
|
return $this->row['state'];
|
|
}
|
|
|
|
|
|
/**
|
|
* Set lock on transport record and save/clear process id
|
|
*
|
|
* @param boolean $lock
|
|
* lock if true, release lock if false
|
|
* @param int $pid
|
|
* process id
|
|
* @return mixed
|
|
* true or error
|
|
*/
|
|
function setLock($lock, $pid=NULL)
|
|
{
|
|
global $CC_CONFIG, $CC_DBC;
|
|
$pidsql = (is_null($pid) ? "NULL" : "$pid" );
|
|
if ($this->dropped) {
|
|
return TRUE;
|
|
}
|
|
$slock = ($lock ? 'Y' : 'N');
|
|
$nlock = (!$lock);
|
|
$snlock = ($nlock ? 'Y' : 'N');
|
|
$r = $CC_DBC->query("
|
|
UPDATE ".$CC_CONFIG['transTable']."
|
|
SET lock='$slock', jobpid=$pidsql, ts=now()
|
|
WHERE trtok='{$this->trtok}' AND lock = '$snlock'"
|
|
);
|
|
if (PEAR::isError($r)) {
|
|
return $r;
|
|
}
|
|
$affRows = $CC_DBC->affectedRows();
|
|
if (PEAR::isError($affRows)) {
|
|
return $affRows;
|
|
}
|
|
if ($affRows === 0) {
|
|
$ltxt = ($lock ? 'lock' : 'unlock' );
|
|
return PEAR::raiseError(
|
|
"TransportRecord::setLock: can't $ltxt ({$this->trtok})"
|
|
);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Return type of transport
|
|
*
|
|
* @return string
|
|
* Transport type
|
|
*/
|
|
function getTransportType()
|
|
{
|
|
if (!$this->recalled) {
|
|
return PEAR::raiseError("TransportRecord::getTransportType:".
|
|
" not recalled ({$this->trtok})", TRERR_TOK
|
|
);
|
|
}
|
|
return $this->row['trtype'];
|
|
}
|
|
|
|
|
|
/**
|
|
* Kill transport job (on pause or cancel)
|
|
*
|
|
* @return string
|
|
* Transport type
|
|
*/
|
|
function killJob()
|
|
{
|
|
if (!$this->recalled) {
|
|
return PEAR::raiseError("TransportRecord::getTransportType:".
|
|
" not recalled ({$this->trtok})", TRERR_TOK
|
|
);
|
|
}
|
|
$jobpid = $this->row['jobpid'];
|
|
$res = system("pkill -P $jobpid", $status);
|
|
}
|
|
|
|
|
|
/**
|
|
* Set state to failed and set error message in transport record
|
|
*
|
|
* @param string $txt
|
|
* base part of error message
|
|
* @param PEAR_Error $eo
|
|
* (opt.) error msg can be construct from it
|
|
* @return mixed
|
|
* boolean true or error
|
|
*/
|
|
function fail($txt='', $eo=NULL)
|
|
{
|
|
if (!$this->recalled) {
|
|
return PEAR::raiseError("TransportRecord::fail:".
|
|
" not recalled ({$this->trtok})", TRERR_TOK
|
|
);
|
|
}
|
|
$msg = $txt;
|
|
if (!is_null($eo)) {
|
|
$msg .= $eo->getMessage()." ".$eo->getUserInfo().
|
|
" [".$eo->getCode()."]";
|
|
}
|
|
$r = $this->setState('failed', array('errmsg'=>$msg));
|
|
if (PEAR::isError($r)) {
|
|
return $r;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Close transport record
|
|
*
|
|
* @return mixed
|
|
* boolean true or error
|
|
*/
|
|
function close()
|
|
{
|
|
global $CC_CONFIG, $CC_DBC;
|
|
if (!$this->recalled) {
|
|
return PEAR::raiseError("TransportRecord::close:".
|
|
" not recalled ({$this->trtok})", TRERR_TOK
|
|
);
|
|
}
|
|
if (TR_LEAVE_CLOSED) {
|
|
$r = $this->setState('closed');
|
|
if (PEAR::isError($r)) {
|
|
return $r;
|
|
}
|
|
} else {
|
|
$r = $CC_DBC->query("
|
|
DELETE FROM ".$CC_CONFIG['transTable']."
|
|
WHERE trtok='{$this->trtok}'
|
|
");
|
|
if (PEAR::isError($r)) {
|
|
return $r;
|
|
}
|
|
$this->recalled = FALSE;
|
|
$this->dropped = TRUE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add field specific envelopes to values (e.g. ' around strings)
|
|
*
|
|
* @param string $fldName
|
|
* field name
|
|
* @param mixed $fldVal
|
|
* field value
|
|
* @return string
|
|
*/
|
|
function _getSqlVal($fldName, $fldVal)
|
|
{
|
|
switch ($fldName) {
|
|
case 'realsize':
|
|
case 'expectedsize':
|
|
case 'uid':
|
|
return ("$fldVal"!='' ? "$fldVal" : "NULL");
|
|
break;
|
|
case 'gunid':
|
|
case 'pdtoken':
|
|
return "x'$fldVal'::bigint";
|
|
break;
|
|
default:
|
|
$fldVal = pg_escape_string($fldVal);
|
|
return "'$fldVal'";
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get title from transported object's metadata (if exists)
|
|
*
|
|
* @return string
|
|
* the title or descriptive string
|
|
*/
|
|
function getTitle()
|
|
{
|
|
$defStr = 'unknown';
|
|
$trtype = $this->getTransportType(); //contains recall check
|
|
if (PEAR::isError($trtype)) {
|
|
return $trtype;
|
|
}
|
|
switch ($trtype) {
|
|
case "audioclip":
|
|
case "playlist":
|
|
case "playlistPkg":
|
|
case "metadata":
|
|
$title = $this->gb->bsGetTitle(NULL, $this->row['gunid']);
|
|
if (is_null($title)) {
|
|
$title = $defStr;
|
|
}
|
|
if (PEAR::isError($title)) {
|
|
if ($title->getCode() == GBERR_FOBJNEX) {
|
|
$title = $defStr;
|
|
} else {
|
|
return $title;
|
|
}
|
|
}
|
|
break;
|
|
case "searchjob":
|
|
$title = 'searchjob';
|
|
break;
|
|
case "file":
|
|
$title = ( isset($this->row['localfile']) ?
|
|
basename($this->row['localfile']) : 'regular file');
|
|
break;
|
|
default:
|
|
$title = $defStr;
|
|
}
|
|
return $title;
|
|
}
|
|
|
|
} // class TransportRecord
|
|
?>
|