CC-2977: Never delete files from the database

- Files are marked deleted(file_exists to false) on deletion.
- Dirs are marked removed(removed flag to true) on removal of watched
folder in a usual way. If dir is unmounted, without being removed from
watched list first, it will be marked as not exists(exist flag to false)
- Manage Media Folders will show if dirs exist or not( mounted or not)
- Playlist builder will show if files exists or not
This commit is contained in:
James 2012-01-11 12:17:48 -05:00
parent 61c5355e8a
commit 04b48d47cc
16 changed files with 374 additions and 69 deletions

View file

@ -26,6 +26,8 @@ class ApiController extends Zend_Controller_Action
->addActionContext('update-liquidsoap-status', 'json') ->addActionContext('update-liquidsoap-status', 'json')
->addActionContext('library-init', 'json') ->addActionContext('library-init', 'json')
->addActionContext('live-chat', 'json') ->addActionContext('live-chat', 'json')
->addActionContext('update-file-system-mount', 'json')
->addActionContext('handle-watched-dir-missing', 'json')
->initContext(); ->initContext();
} }
@ -560,16 +562,15 @@ class ApiController extends Zend_Controller_Action
// update import timestamp // update import timestamp
Application_Model_Preference::SetImportTimestamp(); Application_Model_Preference::SetImportTimestamp();
Logging::log("mode: ".$mode);
if ($mode == "create") { if ($mode == "create") {
$filepath = $md['MDATA_KEY_FILEPATH']; $filepath = $md['MDATA_KEY_FILEPATH'];
$filepath = str_replace("\\", "", $filepath); $filepath = str_replace("\\", "", $filepath);
$filepath = str_replace("//", "/", $filepath);
$file = Application_Model_StoredFile::RecallByFilepath($filepath); $file = Application_Model_StoredFile::RecallByFilepath($filepath);
if (is_null($file)) { if (is_null($file)) {
$file = Application_Model_StoredFile::Insert($md); $file = Application_Model_StoredFile::Insert($md);
Logging::log("file: ".print_r($file, true));
} }
else { else {
// path already exist // path already exist
@ -815,5 +816,78 @@ class ApiController extends Zend_Controller_Action
"numEntries"=>Application_Model_Preference::GetLibraryNumEntries() "numEntries"=>Application_Model_Preference::GetLibraryNumEntries()
); );
} }
// handles addition/deletion of mount point which watched dirs reside
public function updateFileSystemMountAction(){
global $CC_CONFIG;
$request = $this->getRequest();
$api_key = $request->getParam('api_key');
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
{
header('HTTP/1.0 401 Unauthorized');
print 'You are not allowed to access this resource.';
exit;
}
$params = $request->getParams();
$temp_list = $params['mount_list'];
$mount_list = explode(',',$temp_list);
// get all watched dirs
$dirs = Application_Model_MusicDir::getWatchedDirs(null, null);
// dirs to be added to watch list again
$addedDirs = array();
// dirs to be deleted from watch list
$removedDirs = array();
$tempDirs = Application_Model_MusicDir::getWatchedDirs(true,null);
foreach( $tempDirs as $d)
{
$removedDirs[$d->getDirectory()] = $d;
}
foreach( $dirs as $dir){
// set Exsits as false as default
foreach($mount_list as $mount_path){
if($mount_path == '/'){
continue;
}
// if dir contaions mount_path
if(strstr($dir->getDirectory(),$mount_path)){
if($dir->getExistsFlag() == false){
$addedDirs[] = $dir;
}else{
unset($removedDirs[$dir->getDirector()]);
}
}
}
}
foreach($addedDirs as $ad){
Application_Model_MusicDir::addWatchedDir($ad->getDirectory(), false);
}
foreach($removedDirs as $rd){
Application_Model_MusicDir::removeWatchedDir($rd->getDirectory(), false);
}
}
// handles case where watched dir is missing
public function handleWatchedDirMissingAction(){
global $CC_CONFIG;
$request = $this->getRequest();
$api_key = $request->getParam('api_key');
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
{
header('HTTP/1.0 401 Unauthorized');
print 'You are not allowed to access this resource.';
exit;
}
$dir = base64_decode($request->getParam('dir'));
Application_Model_MusicDir::removeWatchedDir($dir, false);
}
} }

View file

@ -40,19 +40,28 @@ class Application_Model_MusicDir {
$this->_dir->save(); $this->_dir->save();
} }
public function setRemoved($flag){ public function setExistsFlag($flag){
$this->_dir->setExists($flag);
$this->_dir->save();
}
public function setRemovedFlag($flag){
$this->_dir->setRemoved($flag); $this->_dir->setRemoved($flag);
$this->_dir->save(); $this->_dir->save();
} }
public function getRemoved(){ public function getRemovedFlag(){
return $this->_dir->getRemoved(); return $this->_dir->getRemoved();
} }
public function remove() public function getExistsFlag(){
return $this->_dir->getExists();
}
public function remove($setRemovedFlag=true)
{ {
global $CC_DBC; global $CC_DBC;
Logging::log("remove!!");
$music_dir_id = $this->getId(); $music_dir_id = $this->getId();
$sql = "SELECT DISTINCT s.instance_id from cc_music_dirs as md LEFT JOIN cc_files as f on f.directory = md.id $sql = "SELECT DISTINCT s.instance_id from cc_music_dirs as md LEFT JOIN cc_files as f on f.directory = md.id
@ -66,24 +75,24 @@ Logging::log("remove!!");
// set file_exist flag to false // set file_exist flag to false
foreach( $files as $file_row ){ foreach( $files as $file_row ){
Logging::log(print_r($file_row['id'], true));
$temp_file = Application_Model_StoredFile::Recall($file_row['id']); $temp_file = Application_Model_StoredFile::Recall($file_row['id']);
if($temp_file != null){
$temp_file->setFileExistFlag(false); $temp_file->setFileExistFlag(false);
} }
}
Logging::log("remove!!222222"); // set RemovedFlag to true
Logging::log(print_r($this->_dir,true)); if($setRemovedFlag){
self::setRemovedFlag(true);
// set Removed flat to true }else{
self::setRemoved(true); self::setExistsFlag(false);
}
//$res = $this->_dir->delete(); //$res = $this->_dir->delete();
Logging::log("remove!!44444");
foreach ($show_instances as $show_instance_row) { foreach ($show_instances as $show_instance_row) {
$temp_show = new Application_Model_ShowInstance($show_instance_row["instance_id"]); $temp_show = new Application_Model_ShowInstance($show_instance_row["instance_id"]);
$temp_show->updateScheduledTime(); $temp_show->updateScheduledTime();
} }
Logging::log("remove end!!");
Application_Model_RabbitMq::PushSchedule(); Application_Model_RabbitMq::PushSchedule();
} }
@ -119,7 +128,7 @@ Logging::log("remove end!!");
public static function isPathValid($p_path){ public static function isPathValid($p_path){
$dirs = self::getWatchedDirs(); $dirs = self::getWatchedDirs();
$dirs[] = self::getStorDir(); $dirs[] = self::getStorDir();
Logging::log("dirs: ".print_r($dirs, true));
foreach ($dirs as $dirObj){ foreach ($dirs as $dirObj){
$dir = $dirObj->getDirectory(); $dir = $dirObj->getDirectory();
$diff = strlen($dir) - strlen($p_path); $diff = strlen($dir) - strlen($p_path);
@ -139,7 +148,7 @@ Logging::log("dirs: ".print_r($dirs, true));
} }
} }
public static function addDir($p_path, $p_type) public static function addDir($p_path, $p_type, $setRemovedFlag=true)
{ {
if(!is_dir($p_path)){ if(!is_dir($p_path)){
return array("code"=>2, "error"=>"'$p_path' is not a valid directory."); return array("code"=>2, "error"=>"'$p_path' is not a valid directory.");
@ -148,14 +157,13 @@ Logging::log("dirs: ".print_r($dirs, true));
if($real_path != "/"){ if($real_path != "/"){
$p_path = $real_path; $p_path = $real_path;
} }
Logging::log("dir:".print_r($p_path, true));
$exist_dir = self::getDirByPath($p_path); $exist_dir = self::getDirByPath($p_path);
Logging::log(print_r($exist_dir, true));
if( $exist_dir == NULL ){ if( $exist_dir == NULL ){
Logging::log("new"); $temp_dir = new CcMusicDirs();
$dir = new CcMusicDirs(); $dir = new Application_Model_MusicDir($temp_dir);
}else{ }else{
Logging::log("exist");
$dir = $exist_dir; $dir = $exist_dir;
} }
@ -167,12 +175,13 @@ Logging::log("dirs: ".print_r($dirs, true));
/* isPathValid() checks if path is a substring or a superstring of an /* isPathValid() checks if path is a substring or a superstring of an
* existing dir and if not, throws NestedDirectoryException */ * existing dir and if not, throws NestedDirectoryException */
self::isPathValid($p_path); self::isPathValid($p_path);
$dir->setRemoved(false); if($setRemovedFlag){
$dir->setDirectory($p_path); $dir->setRemovedFlag(false);
Logging::log("dir obj:".print_r($dir, true)); }else{
if( $exist_dir == NULL ){ $dir->setExistsFlag(true);
$dir->save();
} }
$dir->setDirectory($p_path);
return array("code"=>0); return array("code"=>0);
} catch (NestedDirectoryException $nde){ } catch (NestedDirectoryException $nde){
$msg = $nde->getMessage(); $msg = $nde->getMessage();
@ -183,9 +192,20 @@ Logging::log("dirs: ".print_r($dirs, true));
} }
public static function addWatchedDir($p_path) /** There are 2 cases where this function can be called.
* 1. When watched dir was added
* 2. When some dir was watched, but it was unmounted somehow, but gets mounted again
*
* In case of 1, $setRemovedFlag should be true
* In case of 2, $setRemovedFlag should be false
*
* When $setRemovedFlag is true, it will set "Removed" flag to false
* otherwise, it will set "Exists" flag to true
**/
public static function addWatchedDir($p_path, $setRemovedFlag=true)
{ {
$res = self::addDir($p_path, "watched"); $res = self::addDir($p_path, "watched", $setRemovedFlag);
if ($res['code'] == 0){ if ($res['code'] == 0){
//convert "linked" files (Airtime <= 1.8.2) to watched files. //convert "linked" files (Airtime <= 1.8.2) to watched files.
@ -243,7 +263,6 @@ Logging::log("dirs: ".print_r($dirs, true));
public static function getDirByPath($p_path) public static function getDirByPath($p_path)
{ {
Logging::log($p_path);
$dir = CcMusicDirsQuery::create() $dir = CcMusicDirsQuery::create()
->filterByDirectory($p_path) ->filterByDirectory($p_path)
->findOne(); ->findOne();
@ -257,14 +276,25 @@ Logging::log("dirs: ".print_r($dirs, true));
} }
} }
public static function getWatchedDirs() /**
* Search and returns watched dirs
*
* @param $exists search condition with exists flag
* @param $removed search condition with removed flag
*/
public static function getWatchedDirs($exists=true, $removed=false)
{ {
$result = array(); $result = array();
$dirs = CcMusicDirsQuery::create() $dirs = CcMusicDirsQuery::create()
->filterByType("watched") ->filterByType("watched");
->filterByRemoved(false) if($exists !== null){
->find(); $dirs = $dirs->filterByExists($exists);
}
if($removed !== null){
$dirs = $dirs->filterByRemoved($removed);
}
$dirs = $dirs->find();
foreach($dirs as $dir) { foreach($dirs as $dir) {
$result[] = new Application_Model_MusicDir($dir); $result[] = new Application_Model_MusicDir($dir);
@ -311,7 +341,7 @@ Logging::log("dirs: ".print_r($dirs, true));
{ {
$dirs = CcMusicDirsQuery::create() $dirs = CcMusicDirsQuery::create()
->filterByType(array("watched", "stor")) ->filterByType(array("watched", "stor"))
->filterByRemoved(false) ->filterByExists(true)
->find(); ->find();
foreach($dirs as $dir) { foreach($dirs as $dir) {
@ -325,17 +355,27 @@ Logging::log("dirs: ".print_r($dirs, true));
return null; return null;
} }
public static function removeWatchedDir($p_dir){ /** There are 2 cases where this function can be called.
* 1. When watched dir was removed
* 2. When some dir was watched, but it was unmounted
*
* In case of 1, $setRemovedFlag should be true
* In case of 2, $setRemovedFlag should be false
*
* When $setRemovedFlag is true, it will set "Removed" flag to false
* otherwise, it will set "Exists" flag to true
**/
public static function removeWatchedDir($p_dir, $setRemovedFlag=true){
$real_path = realpath($p_dir)."/"; $real_path = realpath($p_dir)."/";
if($real_path != "/"){ if($real_path != "/"){
$p_dir = $real_path; $p_dir = $real_path;
} }
$dir = Application_Model_MusicDir::getDirByPath($p_dir); $dir = Application_Model_MusicDir::getDirByPath($p_dir);
Logging::log(print_r($dir,true));
if($dir == NULL){ if($dir == NULL){
return array("code"=>1,"error"=>"'$p_dir' doesn't exist in the watched list."); return array("code"=>1,"error"=>"'$p_dir' doesn't exist in the watched list.");
}else{ }else{
$dir->remove(); $dir->remove($setRemovedFlag);
$data = array(); $data = array();
$data["directory"] = $p_dir; $data["directory"] = $p_dir;
Application_Model_RabbitMq::SendMessageToMediaMonitor("remove_watch", $data); Application_Model_RabbitMq::SendMessageToMediaMonitor("remove_watch", $data);
@ -346,7 +386,7 @@ Logging::log("dirs: ".print_r($dirs, true));
public static function splitFilePath($p_filepath) public static function splitFilePath($p_filepath)
{ {
$mus_dir = self::getWatchedDirFromFilepath($p_filepath); $mus_dir = self::getWatchedDirFromFilepath($p_filepath);
Logging::log("mus_dir:".print_r($mus_dir, true));
if(is_null($mus_dir)) { if(is_null($mus_dir)) {
return null; return null;
} }
@ -354,7 +394,7 @@ Logging::log("mus_dir:".print_r($mus_dir, true));
$length_dir = strlen($mus_dir->getDirectory()); $length_dir = strlen($mus_dir->getDirectory());
$fp = substr($p_filepath, $length_dir); $fp = substr($p_filepath, $length_dir);
return array($mus_dir->getDirectory(), $fp); return array($mus_dir->getDirectory(), trim($fp));
} }
} }

View file

@ -431,7 +431,7 @@ class Application_Model_StoredFile {
public function setFilePath($p_filepath) public function setFilePath($p_filepath)
{ {
$path_info = Application_Model_MusicDir::splitFilePath($p_filepath); $path_info = Application_Model_MusicDir::splitFilePath($p_filepath);
Logging::log("path_info:".print_r($path_info, true));
if (is_null($path_info)) { if (is_null($path_info)) {
return -1; return -1;
} }
@ -499,7 +499,9 @@ class Application_Model_StoredFile {
$storedFile->_file = $file; $storedFile->_file = $file;
if(isset($md['MDATA_KEY_FILEPATH'])) { if(isset($md['MDATA_KEY_FILEPATH'])) {
$res = $storedFile->setFilePath($md['MDATA_KEY_FILEPATH']); // removed "//" in the path. Always use '/' for path separator
$filepath = str_replace("//", "/", $md['MDATA_KEY_FILEPATH']);
$res = $storedFile->setFilePath($filepath);
if ($res === -1) { if ($res === -1) {
return null; return null;
} }

View file

@ -41,6 +41,7 @@ class CcMusicDirsTableMap extends TableMap {
$this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null); $this->addPrimaryKey('ID', 'Id', 'INTEGER', true, null, null);
$this->addColumn('DIRECTORY', 'Directory', 'LONGVARCHAR', false, null, null); $this->addColumn('DIRECTORY', 'Directory', 'LONGVARCHAR', false, null, null);
$this->addColumn('TYPE', 'Type', 'VARCHAR', false, 255, null); $this->addColumn('TYPE', 'Type', 'VARCHAR', false, 255, null);
$this->addColumn('EXISTS', 'Exists', 'BOOLEAN', false, null, true);
$this->addColumn('REMOVED', 'Removed', 'BOOLEAN', false, null, false); $this->addColumn('REMOVED', 'Removed', 'BOOLEAN', false, null, false);
// validators // validators
} // initialize() } // initialize()

View file

@ -42,6 +42,13 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
*/ */
protected $type; protected $type;
/**
* The value for the exists field.
* Note: this column has a database default value of: true
* @var boolean
*/
protected $exists;
/** /**
* The value for the removed field. * The value for the removed field.
* Note: this column has a database default value of: false * Note: this column has a database default value of: false
@ -76,6 +83,7 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
*/ */
public function applyDefaultValues() public function applyDefaultValues()
{ {
$this->exists = true;
$this->removed = false; $this->removed = false;
} }
@ -119,6 +127,16 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
return $this->type; return $this->type;
} }
/**
* Get the [exists] column value.
*
* @return boolean
*/
public function getExists()
{
return $this->exists;
}
/** /**
* Get the [removed] column value. * Get the [removed] column value.
* *
@ -189,6 +207,27 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
return $this; return $this;
} // setType() } // setType()
/**
* Set the value of [exists] column.
*
* @param boolean $v new value
* @return CcMusicDirs The current object (for fluent API support)
*/
public function setExists($v)
{
Logging::log("setting exists to ".print_r($v, true));
if ($v !== null) {
$v = (boolean) $v;
}
if ($this->exists !== $v || $this->isNew()) {
$this->exists = $v;
$this->modifiedColumns[] = CcMusicDirsPeer::EXISTS;
}
return $this;
} // setExists()
/** /**
* Set the value of [removed] column. * Set the value of [removed] column.
* *
@ -219,6 +258,10 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
*/ */
public function hasOnlyDefaultValues() public function hasOnlyDefaultValues()
{ {
if ($this->exists !== true) {
return false;
}
if ($this->removed !== false) { if ($this->removed !== false) {
return false; return false;
} }
@ -248,7 +291,8 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
$this->id = ($row[$startcol + 0] !== null) ? (int) $row[$startcol + 0] : null; $this->id = ($row[$startcol + 0] !== null) ? (int) $row[$startcol + 0] : null;
$this->directory = ($row[$startcol + 1] !== null) ? (string) $row[$startcol + 1] : null; $this->directory = ($row[$startcol + 1] !== null) ? (string) $row[$startcol + 1] : null;
$this->type = ($row[$startcol + 2] !== null) ? (string) $row[$startcol + 2] : null; $this->type = ($row[$startcol + 2] !== null) ? (string) $row[$startcol + 2] : null;
$this->removed = ($row[$startcol + 3] !== null) ? (boolean) $row[$startcol + 3] : null; $this->exists = ($row[$startcol + 3] !== null) ? (boolean) $row[$startcol + 3] : null;
$this->removed = ($row[$startcol + 4] !== null) ? (boolean) $row[$startcol + 4] : null;
$this->resetModified(); $this->resetModified();
$this->setNew(false); $this->setNew(false);
@ -257,7 +301,7 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
$this->ensureConsistency(); $this->ensureConsistency();
} }
return $startcol + 4; // 4 = CcMusicDirsPeer::NUM_COLUMNS - CcMusicDirsPeer::NUM_LAZY_LOAD_COLUMNS). return $startcol + 5; // 5 = CcMusicDirsPeer::NUM_COLUMNS - CcMusicDirsPeer::NUM_LAZY_LOAD_COLUMNS).
} catch (Exception $e) { } catch (Exception $e) {
throw new PropelException("Error populating CcMusicDirs object", $e); throw new PropelException("Error populating CcMusicDirs object", $e);
@ -584,6 +628,9 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
return $this->getType(); return $this->getType();
break; break;
case 3: case 3:
return $this->getExists();
break;
case 4:
return $this->getRemoved(); return $this->getRemoved();
break; break;
default: default:
@ -612,7 +659,8 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
$keys[0] => $this->getId(), $keys[0] => $this->getId(),
$keys[1] => $this->getDirectory(), $keys[1] => $this->getDirectory(),
$keys[2] => $this->getType(), $keys[2] => $this->getType(),
$keys[3] => $this->getRemoved(), $keys[3] => $this->getExists(),
$keys[4] => $this->getRemoved(),
); );
return $result; return $result;
} }
@ -654,6 +702,9 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
$this->setType($value); $this->setType($value);
break; break;
case 3: case 3:
$this->setExists($value);
break;
case 4:
$this->setRemoved($value); $this->setRemoved($value);
break; break;
} // switch() } // switch()
@ -683,7 +734,8 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]); if (array_key_exists($keys[0], $arr)) $this->setId($arr[$keys[0]]);
if (array_key_exists($keys[1], $arr)) $this->setDirectory($arr[$keys[1]]); if (array_key_exists($keys[1], $arr)) $this->setDirectory($arr[$keys[1]]);
if (array_key_exists($keys[2], $arr)) $this->setType($arr[$keys[2]]); if (array_key_exists($keys[2], $arr)) $this->setType($arr[$keys[2]]);
if (array_key_exists($keys[3], $arr)) $this->setRemoved($arr[$keys[3]]); if (array_key_exists($keys[3], $arr)) $this->setExists($arr[$keys[3]]);
if (array_key_exists($keys[4], $arr)) $this->setRemoved($arr[$keys[4]]);
} }
/** /**
@ -698,6 +750,7 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
if ($this->isColumnModified(CcMusicDirsPeer::ID)) $criteria->add(CcMusicDirsPeer::ID, $this->id); if ($this->isColumnModified(CcMusicDirsPeer::ID)) $criteria->add(CcMusicDirsPeer::ID, $this->id);
if ($this->isColumnModified(CcMusicDirsPeer::DIRECTORY)) $criteria->add(CcMusicDirsPeer::DIRECTORY, $this->directory); if ($this->isColumnModified(CcMusicDirsPeer::DIRECTORY)) $criteria->add(CcMusicDirsPeer::DIRECTORY, $this->directory);
if ($this->isColumnModified(CcMusicDirsPeer::TYPE)) $criteria->add(CcMusicDirsPeer::TYPE, $this->type); if ($this->isColumnModified(CcMusicDirsPeer::TYPE)) $criteria->add(CcMusicDirsPeer::TYPE, $this->type);
if ($this->isColumnModified(CcMusicDirsPeer::EXISTS)) $criteria->add(CcMusicDirsPeer::EXISTS, $this->exists);
if ($this->isColumnModified(CcMusicDirsPeer::REMOVED)) $criteria->add(CcMusicDirsPeer::REMOVED, $this->removed); if ($this->isColumnModified(CcMusicDirsPeer::REMOVED)) $criteria->add(CcMusicDirsPeer::REMOVED, $this->removed);
return $criteria; return $criteria;
@ -762,6 +815,7 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
{ {
$copyObj->setDirectory($this->directory); $copyObj->setDirectory($this->directory);
$copyObj->setType($this->type); $copyObj->setType($this->type);
$copyObj->setExists($this->exists);
$copyObj->setRemoved($this->removed); $copyObj->setRemoved($this->removed);
if ($deepCopy) { if ($deepCopy) {
@ -962,6 +1016,7 @@ abstract class BaseCcMusicDirs extends BaseObject implements Persistent
$this->id = null; $this->id = null;
$this->directory = null; $this->directory = null;
$this->type = null; $this->type = null;
$this->exists = null;
$this->removed = null; $this->removed = null;
$this->alreadyInSave = false; $this->alreadyInSave = false;
$this->alreadyInValidation = false; $this->alreadyInValidation = false;

View file

@ -26,7 +26,7 @@ abstract class BaseCcMusicDirsPeer {
const TM_CLASS = 'CcMusicDirsTableMap'; const TM_CLASS = 'CcMusicDirsTableMap';
/** The total number of columns. */ /** The total number of columns. */
const NUM_COLUMNS = 4; const NUM_COLUMNS = 5;
/** The number of lazy-loaded columns. */ /** The number of lazy-loaded columns. */
const NUM_LAZY_LOAD_COLUMNS = 0; const NUM_LAZY_LOAD_COLUMNS = 0;
@ -40,6 +40,9 @@ abstract class BaseCcMusicDirsPeer {
/** the column name for the TYPE field */ /** the column name for the TYPE field */
const TYPE = 'cc_music_dirs.TYPE'; const TYPE = 'cc_music_dirs.TYPE';
/** the column name for the EXISTS field */
const EXISTS = 'cc_music_dirs.EXISTS';
/** the column name for the REMOVED field */ /** the column name for the REMOVED field */
const REMOVED = 'cc_music_dirs.REMOVED'; const REMOVED = 'cc_music_dirs.REMOVED';
@ -59,12 +62,12 @@ abstract class BaseCcMusicDirsPeer {
* e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id' * e.g. self::$fieldNames[self::TYPE_PHPNAME][0] = 'Id'
*/ */
private static $fieldNames = array ( private static $fieldNames = array (
BasePeer::TYPE_PHPNAME => array ('Id', 'Directory', 'Type', 'Removed', ), BasePeer::TYPE_PHPNAME => array ('Id', 'Directory', 'Type', 'Exists', 'Removed', ),
BasePeer::TYPE_STUDLYPHPNAME => array ('id', 'directory', 'type', 'removed', ), BasePeer::TYPE_STUDLYPHPNAME => array ('id', 'directory', 'type', 'exists', 'removed', ),
BasePeer::TYPE_COLNAME => array (self::ID, self::DIRECTORY, self::TYPE, self::REMOVED, ), BasePeer::TYPE_COLNAME => array (self::ID, self::DIRECTORY, self::TYPE, self::EXISTS, self::REMOVED, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID', 'DIRECTORY', 'TYPE', 'REMOVED', ), BasePeer::TYPE_RAW_COLNAME => array ('ID', 'DIRECTORY', 'TYPE', 'EXISTS', 'REMOVED', ),
BasePeer::TYPE_FIELDNAME => array ('id', 'directory', 'type', 'removed', ), BasePeer::TYPE_FIELDNAME => array ('id', 'directory', 'type', 'exists', 'removed', ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, ) BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, )
); );
/** /**
@ -74,12 +77,12 @@ abstract class BaseCcMusicDirsPeer {
* e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0 * e.g. self::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
*/ */
private static $fieldKeys = array ( private static $fieldKeys = array (
BasePeer::TYPE_PHPNAME => array ('Id' => 0, 'Directory' => 1, 'Type' => 2, 'Removed' => 3, ), BasePeer::TYPE_PHPNAME => array ('Id' => 0, 'Directory' => 1, 'Type' => 2, 'Exists' => 3, 'Removed' => 4, ),
BasePeer::TYPE_STUDLYPHPNAME => array ('id' => 0, 'directory' => 1, 'type' => 2, 'removed' => 3, ), BasePeer::TYPE_STUDLYPHPNAME => array ('id' => 0, 'directory' => 1, 'type' => 2, 'exists' => 3, 'removed' => 4, ),
BasePeer::TYPE_COLNAME => array (self::ID => 0, self::DIRECTORY => 1, self::TYPE => 2, self::REMOVED => 3, ), BasePeer::TYPE_COLNAME => array (self::ID => 0, self::DIRECTORY => 1, self::TYPE => 2, self::EXISTS => 3, self::REMOVED => 4, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'DIRECTORY' => 1, 'TYPE' => 2, 'REMOVED' => 3, ), BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'DIRECTORY' => 1, 'TYPE' => 2, 'EXISTS' => 3, 'REMOVED' => 4, ),
BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'directory' => 1, 'type' => 2, 'removed' => 3, ), BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'directory' => 1, 'type' => 2, 'exists' => 3, 'removed' => 4, ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, ) BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, )
); );
/** /**
@ -154,11 +157,13 @@ abstract class BaseCcMusicDirsPeer {
$criteria->addSelectColumn(CcMusicDirsPeer::ID); $criteria->addSelectColumn(CcMusicDirsPeer::ID);
$criteria->addSelectColumn(CcMusicDirsPeer::DIRECTORY); $criteria->addSelectColumn(CcMusicDirsPeer::DIRECTORY);
$criteria->addSelectColumn(CcMusicDirsPeer::TYPE); $criteria->addSelectColumn(CcMusicDirsPeer::TYPE);
$criteria->addSelectColumn(CcMusicDirsPeer::EXISTS);
$criteria->addSelectColumn(CcMusicDirsPeer::REMOVED); $criteria->addSelectColumn(CcMusicDirsPeer::REMOVED);
} else { } else {
$criteria->addSelectColumn($alias . '.ID'); $criteria->addSelectColumn($alias . '.ID');
$criteria->addSelectColumn($alias . '.DIRECTORY'); $criteria->addSelectColumn($alias . '.DIRECTORY');
$criteria->addSelectColumn($alias . '.TYPE'); $criteria->addSelectColumn($alias . '.TYPE');
$criteria->addSelectColumn($alias . '.EXISTS');
$criteria->addSelectColumn($alias . '.REMOVED'); $criteria->addSelectColumn($alias . '.REMOVED');
} }
} }

View file

@ -9,11 +9,13 @@
* @method CcMusicDirsQuery orderById($order = Criteria::ASC) Order by the id column * @method CcMusicDirsQuery orderById($order = Criteria::ASC) Order by the id column
* @method CcMusicDirsQuery orderByDirectory($order = Criteria::ASC) Order by the directory column * @method CcMusicDirsQuery orderByDirectory($order = Criteria::ASC) Order by the directory column
* @method CcMusicDirsQuery orderByType($order = Criteria::ASC) Order by the type column * @method CcMusicDirsQuery orderByType($order = Criteria::ASC) Order by the type column
* @method CcMusicDirsQuery orderByExists($order = Criteria::ASC) Order by the exists column
* @method CcMusicDirsQuery orderByRemoved($order = Criteria::ASC) Order by the removed column * @method CcMusicDirsQuery orderByRemoved($order = Criteria::ASC) Order by the removed column
* *
* @method CcMusicDirsQuery groupById() Group by the id column * @method CcMusicDirsQuery groupById() Group by the id column
* @method CcMusicDirsQuery groupByDirectory() Group by the directory column * @method CcMusicDirsQuery groupByDirectory() Group by the directory column
* @method CcMusicDirsQuery groupByType() Group by the type column * @method CcMusicDirsQuery groupByType() Group by the type column
* @method CcMusicDirsQuery groupByExists() Group by the exists column
* @method CcMusicDirsQuery groupByRemoved() Group by the removed column * @method CcMusicDirsQuery groupByRemoved() Group by the removed column
* *
* @method CcMusicDirsQuery leftJoin($relation) Adds a LEFT JOIN clause to the query * @method CcMusicDirsQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
@ -30,11 +32,13 @@
* @method CcMusicDirs findOneById(int $id) Return the first CcMusicDirs filtered by the id column * @method CcMusicDirs findOneById(int $id) Return the first CcMusicDirs filtered by the id column
* @method CcMusicDirs findOneByDirectory(string $directory) Return the first CcMusicDirs filtered by the directory column * @method CcMusicDirs findOneByDirectory(string $directory) Return the first CcMusicDirs filtered by the directory column
* @method CcMusicDirs findOneByType(string $type) Return the first CcMusicDirs filtered by the type column * @method CcMusicDirs findOneByType(string $type) Return the first CcMusicDirs filtered by the type column
* @method CcMusicDirs findOneByExists(boolean $exists) Return the first CcMusicDirs filtered by the exists column
* @method CcMusicDirs findOneByRemoved(boolean $removed) Return the first CcMusicDirs filtered by the removed column * @method CcMusicDirs findOneByRemoved(boolean $removed) Return the first CcMusicDirs filtered by the removed column
* *
* @method array findById(int $id) Return CcMusicDirs objects filtered by the id column * @method array findById(int $id) Return CcMusicDirs objects filtered by the id column
* @method array findByDirectory(string $directory) Return CcMusicDirs objects filtered by the directory column * @method array findByDirectory(string $directory) Return CcMusicDirs objects filtered by the directory column
* @method array findByType(string $type) Return CcMusicDirs objects filtered by the type column * @method array findByType(string $type) Return CcMusicDirs objects filtered by the type column
* @method array findByExists(boolean $exists) Return CcMusicDirs objects filtered by the exists column
* @method array findByRemoved(boolean $removed) Return CcMusicDirs objects filtered by the removed column * @method array findByRemoved(boolean $removed) Return CcMusicDirs objects filtered by the removed column
* *
* @package propel.generator.airtime.om * @package propel.generator.airtime.om
@ -206,6 +210,23 @@ abstract class BaseCcMusicDirsQuery extends ModelCriteria
return $this->addUsingAlias(CcMusicDirsPeer::TYPE, $type, $comparison); return $this->addUsingAlias(CcMusicDirsPeer::TYPE, $type, $comparison);
} }
/**
* Filter the query on the exists column
*
* @param boolean|string $exists The value to use as filter.
* Accepts strings ('false', 'off', '-', 'no', 'n', and '0' are false, the rest is true)
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
*
* @return CcMusicDirsQuery The current query, for fluid interface
*/
public function filterByExists($exists = null, $comparison = null)
{
if (is_string($exists)) {
$exists = in_array(strtolower($exists), array('false', 'off', '-', 'no', 'n', '0')) ? false : true;
}
return $this->addUsingAlias(CcMusicDirsPeer::EXISTS, $exists, $comparison);
}
/** /**
* Filter the query on the removed column * Filter the query on the removed column
* *

View file

@ -33,12 +33,12 @@
</ul> </ul>
<?php endif; ?> <?php endif; ?>
</dd> </dd>
<?php $watched_dirs = Application_Model_MusicDir::getWatchedDirs(); ?> <?php $watched_dirs = Application_Model_MusicDir::getWatchedDirs(null, false); ?>
<?php if (count($watched_dirs) > 0): ?> <?php if (count($watched_dirs) > 0): ?>
<?php foreach($watched_dirs as $watched_dir): ?> <?php foreach($watched_dirs as $watched_dir): ?>
<dd class="block-display selected-item"> <dd class="block-display selected-item">
<span><?php echo $watched_dir->getDirectory(); ?></span><span class="ui-icon ui-icon-close"></span> <span><?php echo $watched_dir->getDirectory(); echo " -- Exsits? "; echo ($watched_dir->getExistsFlag())?"YES":"NO";?></span><span class="ui-icon ui-icon-close"></span>
</dd> </dd>
<?php endforeach; ?> <?php endforeach; ?>
<?php else: ?> <?php else: ?>

View file

@ -17,6 +17,7 @@ if (count($items)) : ?>
</div> </div>
<div class="text-row"> <div class="text-row">
<span class="spl_artist"><?php echo $item["CcFiles"]['artist_name'] ?></span> <span class="spl_artist"><?php echo $item["CcFiles"]['artist_name'] ?></span>
<span class="spl_artist"><?php echo ($item["CcFiles"]['file_exist'])?"":"NO FILE FOUND!" ?></span>
<span class="spl_offset"><?php echo $item["offset"]?></span> <span class="spl_offset"><?php echo $item["offset"]?></span>
</div> </div>
<?php //create the crossfade icon. <?php //create the crossfade icon.

View file

@ -28,6 +28,7 @@
<column name="id" phpName="Id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/> <column name="id" phpName="Id" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
<column name="directory" phpName="Directory" type="LONGVARCHAR" required="false"/> <column name="directory" phpName="Directory" type="LONGVARCHAR" required="false"/>
<column name="type" phpName="Type" type="VARCHAR" size="255" required="false"/> <column name="type" phpName="Type" type="VARCHAR" size="255" required="false"/>
<column name="exists" phpName="Exists" type="BOOLEAN" required="false" defaultValue="true"/>
<column name="removed" phpName="Removed" type="BOOLEAN" required="false" defaultValue="false"/> <column name="removed" phpName="Removed" type="BOOLEAN" required="false" defaultValue="false"/>
<unique name="cc_music_dir_unique"> <unique name="cc_music_dir_unique">
<unique-column name="directory"/> <unique-column name="directory"/>

View file

@ -42,6 +42,7 @@ CREATE TABLE "cc_music_dirs"
"id" serial NOT NULL, "id" serial NOT NULL,
"directory" TEXT, "directory" TEXT,
"type" VARCHAR(255), "type" VARCHAR(255),
"exists" BOOLEAN default 't',
"removed" BOOLEAN default 'f', "removed" BOOLEAN default 'f',
PRIMARY KEY ("id"), PRIMARY KEY ("id"),
CONSTRAINT "cc_music_dir_unique" UNIQUE ("directory") CONSTRAINT "cc_music_dir_unique" UNIQUE ("directory")

View file

@ -48,6 +48,12 @@ remove_watched_dir = 'remove-watched-dir/format/json/api_key/%%api_key%%/path/%%
# URL to tell Airtime we want to add watched directory # URL to tell Airtime we want to add watched directory
set_storage_dir = 'set-storage-dir/format/json/api_key/%%api_key%%/path/%%path%%' set_storage_dir = 'set-storage-dir/format/json/api_key/%%api_key%%/path/%%path%%'
# URL to tell Airtime about file system mount change
update_fs_mount = 'update-file-system-mount/format/json/api_key/%%api_key%%'
# URL to tell Airtime about file system mount change
handle_watched_dir_missing = 'handle-watched-dir-missing/format/json/api_key/%%api_key%%/dir/%%dir%%'
############################# #############################
## Config for Recorder ## Config for Recorder
############################# #############################

View file

@ -20,6 +20,7 @@ import os
from urlparse import urlparse from urlparse import urlparse
import base64 import base64
from configobj import ConfigObj from configobj import ConfigObj
import string
AIRTIME_VERSION = "2.0.0" AIRTIME_VERSION = "2.0.0"
@ -582,12 +583,56 @@ class AirTimeApiClient(ApiClientInterface):
url = url.replace("%%msg%%", encoded_msg) url = url.replace("%%msg%%", encoded_msg)
url = url.replace("%%stream_id%%", stream_id) url = url.replace("%%stream_id%%", stream_id)
url = url.replace("%%boot_time%%", time) url = url.replace("%%boot_time%%", time)
logger.debug(url)
req = urllib2.Request(url) req = urllib2.Request(url)
response = urllib2.urlopen(req).read() response = urllib2.urlopen(req).read()
except Exception, e: except Exception, e:
logger.error("Exception: %s", e) logger.error("Exception: %s", e)
"""
This function updates status of mounted file system information on airtime
"""
def update_file_system_mount(self, mount_list):
logger = logging.getLogger()
try:
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["update_fs_mount"])
url = url.replace("%%api_key%%", self.config["api_key"])
data_string = string.join(mount_list, ',')
map = [("mount_list", data_string)]
data = urllib.urlencode(map)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req).read()
logger.info("update file system mount: %s", response)
except Exception, e:
import traceback
top = traceback.format_exc()
logger.error('Exception: %s', e)
logger.error("traceback: %s", top)
"""
When watched dir is missing(unplugged or something) on boot up, this function will get called
and will call approperiate function on Airtime.
"""
def handle_watched_dir_missing(self, dir):
logger = logging.getLogger()
try:
url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["handle_watched_dir_missing"])
url = url.replace("%%api_key%%", self.config["api_key"])
url = url.replace("%%dir%%", base64.b64encode(dir))
req = urllib2.Request(url)
response = urllib2.urlopen(req).read()
logger.info("update file system mount: %s", response)
except Exception, e:
import traceback
top = traceback.format_exc()
logger.error('Exception: %s', e)
logger.error("traceback: %s", top)
################################################################################ ################################################################################
# OpenBroadcast API Client # OpenBroadcast API Client
################################################################################ ################################################################################

View file

@ -62,7 +62,7 @@ try:
mmc = MediaMonitorCommon(config, wm=wm) mmc = MediaMonitorCommon(config, wm=wm)
pe = AirtimeProcessEvent(queue=multi_queue, airtime_config=config, wm=wm, mmc=mmc, api_client=api_client) pe = AirtimeProcessEvent(queue=multi_queue, airtime_config=config, wm=wm, mmc=mmc, api_client=api_client)
bootstrap = AirtimeMediaMonitorBootstrap(logger, pe, api_client, mmc) bootstrap = AirtimeMediaMonitorBootstrap(logger, pe, api_client, mmc, wm)
bootstrap.scan() bootstrap.scan()
notifier = AirtimeNotifier(wm, pe, read_freq=0, timeout=0, airtime_config=config, api_client=api_client, bootstrap=bootstrap, mmc=mmc) notifier = AirtimeNotifier(wm, pe, read_freq=0, timeout=0, airtime_config=config, api_client=api_client, bootstrap=bootstrap, mmc=mmc)

View file

@ -1,5 +1,6 @@
import os import os
import time import time
import pyinotify
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from api_clients import api_client from api_clients import api_client
@ -13,11 +14,16 @@ class AirtimeMediaMonitorBootstrap():
pe -- reference to an instance of ProcessEvent pe -- reference to an instance of ProcessEvent
api_clients -- reference of api_clients to communicate with airtime-server api_clients -- reference of api_clients to communicate with airtime-server
""" """
def __init__(self, logger, pe, api_client, mmc): def __init__(self, logger, pe, api_client, mmc, wm):
self.logger = logger self.logger = logger
self.pe = pe self.pe = pe
self.api_client = api_client self.api_client = api_client
self.mmc = mmc self.mmc = mmc
self.wm = wm
# add /etc on watch list so we can detect mount
self.mount_file = "/etc"
self.logger.info("Adding %s on watch list...", self.mount_file)
self.wm.add_watch(self.mount_file, pyinotify.ALL_EVENTS, rec=False, auto_add=False)
"""On bootup we want to scan all directories and look for files that """On bootup we want to scan all directories and look for files that
weren't there or files that changed before media-monitor process weren't there or files that changed before media-monitor process
@ -79,6 +85,10 @@ class AirtimeMediaMonitorBootstrap():
if len(file_path.strip(" \n")) > 0: if len(file_path.strip(" \n")) > 0:
all_files_set.add(file_path[len(dir):]) all_files_set.add(file_path[len(dir):])
# if dir doesn't exists, update db
if not os.path.exists(dir):
self.pe.handle_watched_dir_missing(dir)
if os.path.exists(self.mmc.timestamp_file): if os.path.exists(self.mmc.timestamp_file):
"""find files that have been modified since the last time media-monitor process started.""" """find files that have been modified since the last time media-monitor process started."""
time_diff_sec = time.time() - os.path.getmtime(self.mmc.timestamp_file) time_diff_sec = time.time() - os.path.getmtime(self.mmc.timestamp_file)

View file

@ -38,6 +38,8 @@ class AirtimeProcessEvent(ProcessEvent):
self.mmc = mmc self.mmc = mmc
self.api_client = api_client self.api_client = api_client
self.create_dict = {} self.create_dict = {}
self.mount_file_dir = "/etc";
self.mount_file = "/etc/mtab";
def add_filepath_to_ignore(self, filepath): def add_filepath_to_ignore(self, filepath):
self.ignore_event.add(filepath) self.ignore_event.add(filepath)
@ -74,6 +76,8 @@ class AirtimeProcessEvent(ProcessEvent):
def process_IN_DELETE_SELF(self, event): def process_IN_DELETE_SELF(self, event):
if event.path in self.mount_file_dir:
return
self.logger.info("event: %s", event) self.logger.info("event: %s", event)
path = event.path + '/' path = event.path + '/'
if event.dir: if event.dir:
@ -90,6 +94,8 @@ class AirtimeProcessEvent(ProcessEvent):
self.logger.info("Removing the watch folder failed: %s", res['msg']['error']) self.logger.info("Removing the watch folder failed: %s", res['msg']['error'])
def process_IN_CREATE(self, event): def process_IN_CREATE(self, event):
if event.path in self.mount_file_dir:
return
self.logger.info("event: %s", event) self.logger.info("event: %s", event)
if not event.dir: if not event.dir:
# record the timestamp of the time on IN_CREATE event # record the timestamp of the time on IN_CREATE event
@ -101,6 +107,8 @@ class AirtimeProcessEvent(ProcessEvent):
# we used to use IN_CREATE event, but the IN_CREATE event gets fired before the # we used to use IN_CREATE event, but the IN_CREATE event gets fired before the
# copy was done. Hence, IN_CLOSE_WRITE is the correct one to handle. # copy was done. Hence, IN_CLOSE_WRITE is the correct one to handle.
def process_IN_CLOSE_WRITE(self, event): def process_IN_CLOSE_WRITE(self, event):
if event.path in self.mount_file_dir:
return
self.logger.info("event: %s", event) self.logger.info("event: %s", event)
self.logger.info("create_dict: %s", self.create_dict) self.logger.info("create_dict: %s", self.create_dict)
@ -145,6 +153,9 @@ class AirtimeProcessEvent(ProcessEvent):
self.handle_modified_file(event.dir, event.pathname, event.name) self.handle_modified_file(event.dir, event.pathname, event.name)
def handle_modified_file(self, dir, pathname, name): def handle_modified_file(self, dir, pathname, name):
# if /etc/mtab is modified
if pathname in self.mount_file:
self.handle_mount_change()
# update timestamp on create_dict for the entry with pathname as the key # update timestamp on create_dict for the entry with pathname as the key
if pathname in self.create_dict: if pathname in self.create_dict:
self.create_dict[pathname] = time.time() self.create_dict[pathname] = time.time()
@ -153,11 +164,37 @@ class AirtimeProcessEvent(ProcessEvent):
if self.mmc.is_audio_file(name): if self.mmc.is_audio_file(name):
self.file_events.append({'filepath': pathname, 'mode': self.config.MODE_MODIFY}) self.file_events.append({'filepath': pathname, 'mode': self.config.MODE_MODIFY})
# if change is detected on /etc/mtab, we check what mount(file system) was added/removed
# and act accordingly
def handle_mount_change(self):
mount_list = [];
# parse /etc/mtab
fh = open(self.mount_file, 'r')
while 1:
line = fh.readline()
if not line:
break
line_info = line.split(' ')
# the line format is like following:
# /dev/sdg1 /media/809D-D2A1 vfat rw,nosuid,nodev,uhelper=udisks..........
# so we always get [1] after split to get the mount point
mount_list.append(line_info[1])
fh.close()
self.logger.info("Mount List: %s", mount_list)
# send current mount information to Airtime
self.api_client.update_file_system_mount(mount_list);
def handle_watched_dir_missing(self, dir):
self.api_client.handle_watched_dir_missing(dir);
#if a file is moved somewhere, this callback is run. With details about #if a file is moved somewhere, this callback is run. With details about
#where the file is being moved from. The corresponding process_IN_MOVED_TO #where the file is being moved from. The corresponding process_IN_MOVED_TO
#callback is only called if the destination of the file is also in a watched #callback is only called if the destination of the file is also in a watched
#directory. #directory.
def process_IN_MOVED_FROM(self, event): def process_IN_MOVED_FROM(self, event):
if event.path in self.mount_file:
return
self.logger.info("process_IN_MOVED_FROM: %s", event) self.logger.info("process_IN_MOVED_FROM: %s", event)
if not event.dir: if not event.dir:
if event.pathname in self.temp_files: if event.pathname in self.temp_files:
@ -171,6 +208,10 @@ class AirtimeProcessEvent(ProcessEvent):
def process_IN_MOVED_TO(self, event): def process_IN_MOVED_TO(self, event):
self.logger.info("process_IN_MOVED_TO: %s", event) self.logger.info("process_IN_MOVED_TO: %s", event)
# if /etc/mtab is modified
filename = self.mount_file_dir +"/mtab"
if event.pathname in filename:
self.handle_mount_change()
#if stuff dropped in stor via a UI move must change file permissions. #if stuff dropped in stor via a UI move must change file permissions.
self.mmc.set_needed_file_permissions(event.pathname, event.dir) self.mmc.set_needed_file_permissions(event.pathname, event.dir)
if not event.dir: if not event.dir:
@ -221,6 +262,8 @@ class AirtimeProcessEvent(ProcessEvent):
def process_IN_DELETE(self, event): def process_IN_DELETE(self, event):
if event.path in self.mount_file_dir:
return
self.logger.info("process_IN_DELETE: %s", event) self.logger.info("process_IN_DELETE: %s", event)
self.handle_removed_file(event.dir, event.pathname) self.handle_removed_file(event.dir, event.pathname)