437 lines
14 KiB
PHP
437 lines
14 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @package Campcaster
|
|
* @subpackage StorageServer
|
|
* @copyright 2010 Sourcefabric O.P.S.
|
|
* @license http://www.gnu.org/licenses/gpl.txt
|
|
*/
|
|
class Restore {
|
|
/**
|
|
* Name of logfile
|
|
* @var string
|
|
*/
|
|
private $logFile;
|
|
|
|
/**
|
|
* session id
|
|
* @var string
|
|
*/
|
|
private $sessid;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
private $token;
|
|
|
|
/**
|
|
* Name of statusfile
|
|
* @var string
|
|
*/
|
|
private $statusFile;
|
|
|
|
/**
|
|
* Name of temporary directory, to here extract the backup tarball
|
|
* @var string
|
|
*/
|
|
private $tmpDir;
|
|
|
|
/**
|
|
* @var string
|
|
*/
|
|
// private $loglevel = 'warn';
|
|
public $loglevel = 'warn';
|
|
// public $loglevel = 'debug';
|
|
|
|
/**
|
|
* @var GreenBox
|
|
*/
|
|
private $gb;
|
|
|
|
private $ACCESS_TYPE = 'restore';
|
|
|
|
/**
|
|
* @param GreenBox $gb
|
|
* greenbox object reference
|
|
*/
|
|
public function __construct(&$gb)
|
|
{
|
|
global $CC_CONFIG;
|
|
$this->gb =& $gb;
|
|
$this->token = null;
|
|
$this->logFile = $CC_CONFIG['bufferDir'].'/'.$this->ACCESS_TYPE.'.log';
|
|
if ($this->loglevel == 'debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." construct\n");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Call asyncronously the restore procedure. Restore from backup.
|
|
*
|
|
* @param string $sessid
|
|
* session id
|
|
* @param string $backup_file
|
|
* path of the backup file
|
|
* @return array
|
|
* hasharray with field:
|
|
* token string: backup token
|
|
*/
|
|
function openRestore($sessid, $backup_file)
|
|
{
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I-".date("Ymd-H:i:s")." doRestore - sessid:$sessid\n");
|
|
}
|
|
$this->sessid = $sessid;
|
|
|
|
// generate token
|
|
$this->token = StoredFile::CreateGunid();
|
|
|
|
// status file -> working
|
|
$this->setEnviroment();
|
|
file_put_contents($this->statusFile, 'working');
|
|
|
|
//call the restore script in background
|
|
$command = dirname(__FILE__).'/../bin/restore.php';
|
|
$runLog = "/dev/null";
|
|
$params = "{$backup_file} {$this->statusFile} {$this->token} {$sessid}>> $runLog &";
|
|
$ret = system("$command $params", $st);
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I-".date("Ymd-H:i:s")." restore.php call: $st/$ret\n");
|
|
}
|
|
|
|
return array('token'=>$this->token);
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the status of restore
|
|
*
|
|
* @param string $token
|
|
* @return array
|
|
* hasharray with field:
|
|
* status : string - susccess | working | fault
|
|
* faultString : string - description of fault
|
|
* token : stirng - backup token
|
|
* url : string - access url
|
|
* tmpfile : string - access filename
|
|
*/
|
|
function checkRestore($token)
|
|
{
|
|
if ($this->loglevel == 'debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." checkBackup - token:$token\n");
|
|
}
|
|
$this->token = $token;
|
|
$this->setEnviroment();
|
|
if (is_file($this->statusFile)) {
|
|
$r = array();
|
|
$stat = file_get_contents($this->statusFile);
|
|
if (strpos($stat,'fault|') !== false) {
|
|
list($stat,$message) = explode('|',$stat);
|
|
}
|
|
$r['status'] = $stat;
|
|
if ($stat=='fault') {
|
|
$r['faultString'] = $message;
|
|
} else {
|
|
$r['faultString'] = '';
|
|
}
|
|
return $r;
|
|
} else {
|
|
return PEAR::raiseError('Restore::checkRestore: invalid token!');
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Check the status of restore.
|
|
*
|
|
* @param string $token
|
|
* @return array
|
|
* hasharray with field:
|
|
* status : boolean - is success
|
|
*/
|
|
function closeRestore($token)
|
|
{
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." checkBackup - token:$token\n");
|
|
}
|
|
$this->token = $token;
|
|
$this->setEnviroment();
|
|
$this->rRmDir($this->tmpDir);
|
|
unlink($this->statusFile);
|
|
return array("status" => !is_file($this->statusFile));
|
|
}
|
|
|
|
|
|
/**
|
|
* Do restore in background
|
|
*
|
|
* this function is called from the asyncron commandline script
|
|
* ../bin/restore.php
|
|
*
|
|
* @param string $backupfile
|
|
* path of backupfile
|
|
* @param string $token
|
|
* restore token
|
|
* @param string $sessid
|
|
* session id
|
|
*/
|
|
function startRestore($backupfile, $token, $sessid)
|
|
{
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." startRestore - bufile:$backupfile | token:$token\n");
|
|
}
|
|
$this->token = $token;
|
|
$this->sessid = $sessid;
|
|
$this->setEnviroment();
|
|
|
|
// extract tarball
|
|
$command = 'tar -xf '.$backupfile .' --directory '.$this->tmpDir;
|
|
$res = system($command);
|
|
//$this->addLogItem('command: '.$command."\n");
|
|
//$this->addLogItem('res: '.$res."\n");
|
|
|
|
//simple check of archive format
|
|
if (is_dir($this->tmpDir.'audioClip/') &&
|
|
is_dir($this->tmpDir.'meta-inf/') &&
|
|
is_dir($this->tmpDir.'playlist/')) {
|
|
//search metafiles
|
|
$this->metafiles = $this->getMetaFiles();
|
|
#$this->addLogItem('metafiles:'.print_r($this->metafiles,true));
|
|
//add to storage server
|
|
foreach ($this->metafiles as $info) {
|
|
$r = $this->addFileToStorage($info['file'],$info['type'],$info['id']);
|
|
if (PEAR::isError($r)) {
|
|
$this->addLogItem("-E- ".date("Ymd-H:i:s").
|
|
" startRestore - addFileToStorage \n".
|
|
"(".$put->getMessage()."/".$put->getUserInfo().")\n"
|
|
);
|
|
file_put_contents($this->statusFile, 'fault|'.$put->getMessage()."/".$put->getUserInfo());
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
$this->addLogItem("-E- ".date("Ymd-H:i:s")." startRestore - invalid archive format\n");
|
|
file_put_contents($this->statusFile, 'fault|invalid archive format');
|
|
return;
|
|
}
|
|
file_put_contents($this->statusFile, 'success');
|
|
// unlink($backupfile);
|
|
}
|
|
|
|
|
|
/**
|
|
* Get the metafiles.
|
|
*
|
|
* @return array
|
|
* array of hasharray with field:
|
|
* file : string - metafile path
|
|
* type : stirng - audioClip | playlist
|
|
* id : string - the backuped gunid
|
|
*/
|
|
function getMetaFiles()
|
|
{
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." getMetaFiles - tmpDir:{$this->tmpDir}\n");
|
|
}
|
|
$audioclips = scandir($this->tmpDir.'audioClip/');
|
|
$playlists = scandir($this->tmpDir.'playlist/');
|
|
for ($i = 0; $i < count($audioclips); $i++) {
|
|
if (strpos($audioclips[$i],'xml')!==false)
|
|
$r[] = array('file' => $this->tmpDir.'audioClip/'.$audioclips[$i],
|
|
'type' => 'audioClip',
|
|
'id' => str_replace('.xml','',$audioclips[$i]));
|
|
}
|
|
for ($i = 0; $i < count($playlists); $i++) {
|
|
if (strpos($playlists[$i],'xml') !== false)
|
|
$r[] = array('file' => $this->tmpDir.'playlist/'.$playlists[$i],
|
|
'type' => 'playlist',
|
|
'id' => str_replace('.xml','',$playlists[$i]));
|
|
}
|
|
return $r;
|
|
}
|
|
|
|
|
|
/**
|
|
* Add the file to the storage server.
|
|
*
|
|
* @param string $file
|
|
* path of metafile
|
|
* @param string $type
|
|
* restore token
|
|
* @param string $sessid
|
|
* session id
|
|
*
|
|
* @return mixed
|
|
* true if success or PEAR_error
|
|
*/
|
|
function addFileToStorage($file,$type,$gunid)
|
|
{
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." addFileToStorage - file:$file | type:$type | id:$gunid\n");
|
|
}
|
|
require_once("XmlParser.php");
|
|
$tree = XmlParser::parse($file);
|
|
$mediaFileLP = str_replace('.xml','',$file);
|
|
$mediaFileLP = ($type=='audioClip' && is_file($mediaFileLP))?$mediaFileLP:'';
|
|
$ex = $this->gb->existsFile($this->sessid,$gunid);
|
|
if (PEAR::isError($ex)) {
|
|
$this->addLogItem("-E- ".date("Ymd-H:i:s").
|
|
" addFileToStorage - existsFile($gunid) ".
|
|
"(".$ex->getMessage()."/".$ex->getUserInfo().")\n"
|
|
);
|
|
}
|
|
if (!PEAR::isError($ex) && $ex) { // file is exists in storage server
|
|
//replace it
|
|
$id = BasicStor::IdFromGunid($gunid);
|
|
$replace = $this->gb->replaceFile(
|
|
$id, # id int, virt.file's local id
|
|
$mediaFileLP, # mediaFileLP string, local path of media file
|
|
$file, # mdataFileLP string, local path of metadata file
|
|
$this->sessid); # sessid string, session id
|
|
if (PEAR::isError($replace)) {
|
|
$this->addLogItem("-E- ".date("Ymd-H:i:s").
|
|
" addFileToStorage - replaceFile Error ".
|
|
"(".$replace->getMessage()."/".$replace->getUserInfo().")\n"
|
|
);
|
|
file_put_contents($this->statusFile, 'fault|'.$replace->getMessage()."/".$replace->getUserInfo());
|
|
return $replace;
|
|
}
|
|
#$this->addLogItem("replace it \n");
|
|
} else {
|
|
// add as new
|
|
$name = $tree->children[0]->children[0]->content;
|
|
if (empty($name)) {
|
|
$name = $tree->attrs['title']->val;
|
|
}
|
|
if (empty($name)) {
|
|
$name = '???';
|
|
}
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." putFile\n".
|
|
"$name, $mediaFileLP, $file, {$this->sessid}, $gunid, $type \n"
|
|
);
|
|
}
|
|
$values = array(
|
|
"filename" => $name,
|
|
"filepath" => $mediaFileLP,
|
|
"metadata" => $file,
|
|
"gunid" => $gunid,
|
|
"filetype" => $type
|
|
);
|
|
$put = $this->gb->putFile($values, $this->sessid);
|
|
//$this->addLogItem("add as new \n");
|
|
if (PEAR::isError($put)) {
|
|
$this->addLogItem("-E- ".date("Ymd-H:i:s").
|
|
" addFileToStorage - putFile Error ".
|
|
"(".$put->getMessage()."/".$put->getUserInfo().")\n"
|
|
."\n---\n".file_get_contents($file)."\n---\n"
|
|
);
|
|
file_put_contents($this->statusFile, 'fault|'.$put->getMessage()."/".$put->getUserInfo());
|
|
//$this->addLogItem("Error Object: ".print_r($put,true)."\n");
|
|
return $put;
|
|
}
|
|
}
|
|
$ac = StoredFile::RecallByGunid($gunid);
|
|
if (is_null($ac) || PEAR::isError($ac)) {
|
|
return $ac;
|
|
}
|
|
$res = $ac->setState('ready');
|
|
if (PEAR::isError($res)) {
|
|
return $res;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Figure out the environment to the backup.
|
|
*
|
|
*/
|
|
function setEnviroment()
|
|
{
|
|
global $CC_CONFIG;
|
|
if ($this->loglevel=='debug') {
|
|
$this->addLogItem("-I- ".date("Ymd-H:i:s")." setEnviroment\n");
|
|
}
|
|
$this->statusFile = $CC_CONFIG['accessDir'].'/'.$this->token.'.status';
|
|
$this->tmpDir = '/tmp/ls_restore/'.$this->token.'/';
|
|
$this->rMkDir($this->tmpDir);
|
|
}
|
|
|
|
|
|
/**
|
|
* Add a line to the logfile.
|
|
*
|
|
* @param string $item
|
|
* the new row of log file
|
|
*/
|
|
function addLogItem($item)
|
|
{
|
|
$f = fopen ($this->logFile,'a');
|
|
flock($f,LOCK_SH);
|
|
fwrite($f,$item);
|
|
flock($f,LOCK_UN);
|
|
fclose($f);
|
|
//echo file_get_contents($this->logFile)."<BR><BR>\n\n";
|
|
}
|
|
|
|
|
|
/**
|
|
* Delete a directory recursive
|
|
*
|
|
* @param string $dirname
|
|
* path of dir
|
|
*
|
|
* @return boolean
|
|
* is success
|
|
*/
|
|
function rRmDir($dirname)
|
|
{
|
|
if (is_dir($dirname)) {
|
|
$dir_handle = opendir($dirname);
|
|
}
|
|
while ($file = readdir($dir_handle)) {
|
|
if ($file!="." && $file!="..") {
|
|
if (!is_dir($dirname."/".$file)) {
|
|
unlink ($dirname."/".$file);
|
|
} else {
|
|
Restore::rRmDir($dirname."/".$file);
|
|
}
|
|
}
|
|
}
|
|
closedir($dir_handle);
|
|
rmdir($dirname);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Create a directory recursive
|
|
*
|
|
* @param string $dirname
|
|
* path of dir.
|
|
* @param int $mode
|
|
* octal - rights of dir.
|
|
* @param boolean $recursive
|
|
* do it recursive.
|
|
*
|
|
* @return boolean
|
|
*/
|
|
function rMkDir($dirname, $mode=0777, $recursive=true)
|
|
{
|
|
if (is_null($dirname) || $dirname === "" ) {
|
|
return false;
|
|
}
|
|
if (is_dir($dirname) || $dirname === "/" ) {
|
|
return true;
|
|
}
|
|
if ($this->rMkDir(dirname($dirname), $mode, $recursive)) {
|
|
return mkdir($dirname, $mode);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // class Restore
|
|
?>
|