def is_trailer_from_cache(cls, path): # type: (str) -> bool """ :param path: :return: """ cache_path_prefix = Settings.get_downloaded_trailer_cache_path() if path.startswith(cache_path_prefix): return True return False
def get_stats_for_caches(self) -> Dict[str, UsageData]: """ Get disk usage information for the caches. Returns a map of UsageData for each cache. Primarily used by garbage collection and reporting. :return: """ local_class = CacheManager TRAILER_PATTERN = re.compile(r'^.*-trailer\..*$') JSON_PATTERN = re.compile(r'^.*\.json$') TFH_PATTERN = re.compile(r'^.*-movie\..*$') TRAILER_TYPE = 'trailer' JSON_TYPE = 'json' # When the Trailer Cache and Data Cache (.json) are the same if (Settings.get_downloaded_trailer_cache_path() == Settings.get_remote_db_cache_path()): usage_data_map = DiskUtils.get_stats_for_path( Settings.get_downloaded_trailer_cache_path(), { 'trailer': (TRAILER_PATTERN, TRAILER_TYPE), 'json': (JSON_PATTERN, JSON_TYPE), 'tfh': (TFH_PATTERN, TRAILER_TYPE) }) else: # When Trailer Cache and Data Cache are different directories. usage_data_map = DiskUtils.get_stats_for_path( Settings.get_downloaded_trailer_cache_path(), { 'trailer': (TRAILER_PATTERN, TRAILER_TYPE), 'tfh': (TFH_PATTERN, TRAILER_TYPE) }) json_usage_data = DiskUtils.get_stats_for_path( Settings.get_remote_db_cache_path(), {'json': (JSON_PATTERN, JSON_TYPE)}) usage_data_map['json'] = json_usage_data['json'] return usage_data_map
def record_played_trailer(self, trailer, use_movie_path=False, msg=''): # type: (Dict[str, Any], bool, str) -> None """ :param trailer: :param use_movie_path: :param msg: :return: """ if self.playlist_format: use_movie_path = True name = trailer.get(Movie.TITLE, 'unknown Title') year = '(' + str(trailer.get(Movie.YEAR, 'unknown Year')) + ')' movie_type = trailer.get(Movie.TYPE, 'Unknown MovieType') movie_path = trailer.get(Movie.FILE, None) if movie_path is None: if use_movie_path: # Nothing to do if there is no movie path return movie_path = 'Unknown movie path' trailer_path = trailer.get(Movie.TRAILER, '') cache_path_prefix = Settings.get_downloaded_trailer_cache_path() trailer_path = trailer_path.replace(cache_path_prefix, '<cache_path>') missing_detail_msg = Messages.get_msg(Messages.MISSING_DETAIL) if trailer_path == missing_detail_msg: trailer_path = '' if name is None: name = 'name is None' if year is None: year = 'year is None' if movie_type is None: movie_type = 'movie_type is None' path = trailer_path if use_movie_path: path = movie_path formatted_title = Messages.get_formated_title(trailer) with Playlist._playlist_lock: # file closed if self._file is None: return if self.playlist_format: line = Playlist.PLAYLIST_ENTRY_PREFIX + name + '\n' line += path + '\n' else: line = name + ' ' + year + ' # path: ' + formatted_title + ' ' +\ path + ' ' + msg + '\n' self._file.writelines(line)
def is_trailer_from_cache(path): cache_path_prefix = Settings.get_downloaded_trailer_cache_path() if path.startswith(cache_path_prefix): return True return False
def get_stats_for_path( cls, top: str, patterns: Dict[str, Tuple[Pattern[str], str]]) -> Dict[str, UsageData]: """ Gets disk usage information for a subtree of the filesystem :param top: :param patterns: :return: """ usage_data = None fileMap = {} usage_data_map = {} try: free = 0 total = 0 used = 0 size_on_disk = 0 block_size = None # Available in Python >= 3.3 # shutil.disk_usage(top) # _ntuple_diskusage = collections.namedtuple('usage', 'total used free') # units in bytes disk_usage = cls.disk_usage(top) if disk_usage is not None: free = disk_usage['free'] total = disk_usage['total'] used = disk_usage['used'] block_size = disk_usage['blocksize'] #statvfs = os.statvfs(top) #block_size = statvfs.f_bsize #free = int(statvfs.f_bavail * statvfs.f_frsize / megaByte) #total = int(statvfs.f_blocks * statvfs.f_frsize / megaByte) # used = int((statvfs.f_blocks - statvfs.f_bfree) * # statvfs.f_frsize / megaByte) # st.f_blocks is # blocks in filesystem # f_bavail free blocks for non-super user # f_bsize # preferred block size # f_frsize # fundamental file system block size # f_blocks total blocks in filesystem # f_bfree total # free blocks in filesystem for cache_name, (pattern, cache_type) in patterns.items(): usage_data = UsageData(cache_name, pattern) usage_data.set_free_size(free) usage_data.set_total_size(total) usage_data.set_used_space(used) usage_data.set_block_size(block_size) usage_data_map[cache_name] = usage_data db_cache_file_expiration_days = \ Settings.get_expire_remote_db_cache_entry_days() db_cache_file_expiration_seconds =\ db_cache_file_expiration_days * 24 * 60 * 60 db_cache_path_top = Settings.get_remote_db_cache_path() trailer_cache_file_expiration_days = Settings.get_expire_trailer_cache_days( ) trailer_cache_file_expiration_seconds = \ trailer_cache_file_expiration_days * 24 * 60 * 60 trailer_cache_path_top = Settings.get_downloaded_trailer_cache_path( ) now = datetime.datetime.now() found_directories = set() for root, dirs, files in os.walk(top): for filename in files: for cache_name, (pattern, cache_type) in patterns.items(): Monitor.throw_exception_if_abort_requested() usage_data = usage_data_map[cache_name] if pattern.match(filename): path = os.path.join(root, filename) mod_time = now try: if not os.path.isdir(path): st = os.stat(path) mod_time = datetime.datetime.fromtimestamp( st.st_mtime) size_in_blocks = st.st_size size_on_disk = ( (size_in_blocks - 1) / block_size + 1) * block_size else: found_directories.add(path) except OSError as e: continue # File doesn't exist except Exception as e: cls._logger.exception('') continue deleted = False try: if (top == db_cache_path_top and cache_type == 'json'): if ((now - mod_time).total_seconds() > db_cache_file_expiration_seconds): if cls._logger.isEnabledFor( LazyLogger.INFO): cls._logger.info('deleting:', path) os.remove(path) deleted = True usage_data.add_to_disk_deleted( size_on_disk) break # Next file if (top == trailer_cache_path_top and cache_type == 'trailer'): if ((now - mod_time).total_seconds( ) > trailer_cache_file_expiration_seconds): if cls._logger.isEnabledFor( LazyLogger.INFO): cls._logger.info('deleting:', path) os.remove(path) deleted = True usage_data.add_to_disk_deleted( size_on_disk) break # Next file except AbortException: reraise(*sys.exc_info()) except Exception as e: cls._logger.exception('') if not deleted: file_data = FileData(path, mod_time, size_on_disk) usage_data.add_file_data(file_data) usage_data.add_to_disk_used_by_cache( size_on_disk) for directory in found_directories: try: os.rmdir(directory) except Exception as e: pass except AbortException: reraise(*sys.exc_info()) except Exception as e: cls._logger.exception('') cls._logger.exit() return usage_data_map
def get_trailer_cache_file_path_for_movie_id(cls, trailer, orig_file_name, normalized): # type: (Dict[str, Any], str, bool) -> Union[str, None] """ Generates the path for a file in the cache for a trailer for given movie. :param trailer: :param orig_file_name: :param normalized: :return: """ path = None movie_id = None source = None try: valid_sources = [Movie.LIBRARY_SOURCE, Movie.TMDB_SOURCE, Movie.ITUNES_SOURCE, Movie.TFH_SOURCE] if trailer[Movie.SOURCE] in valid_sources: movie_id = Cache.get_video_id(trailer) source = trailer[Movie.SOURCE] else: if cls._logger.isEnabledFor(LazyLogger.DEBUG): cls._logger.debug('Not valid video source title:', trailer[Movie.TITLE], 'source:', trailer[Movie.SOURCE]) if movie_id is not None: # movie_id may begin with an '_'. prefix = movie_id + '_' folder = None if source == Movie.LIBRARY_SOURCE: folder = movie_id[0] elif source == Movie.TMDB_SOURCE: x = prefix.split('_', 1) folder = 't' + x[1][0] elif source == Movie.TFH_SOURCE: x = prefix.split('_', 1) folder = 'h' + x[1][0] elif source == Movie.ITUNES_SOURCE: x = prefix.split('_', 1) folder = 'a' + movie_id[1][0] # Possible that trailer was downloaded into cache orig_file_name = re.sub( r'^' + re.escape(prefix), '', orig_file_name) if normalized: if 'normalized_' in orig_file_name: cls._logger.debug('Already normalized:', trailer.get( Movie.TITLE, 'no title'), 'orig_file_name:', orig_file_name) file_name = prefix + orig_file_name else: file_name = prefix + 'normalized_' + orig_file_name else: file_name = prefix + orig_file_name path = os.path.join(Settings.get_downloaded_trailer_cache_path(), folder, file_name) # Should not be needed path = xbmcvfs.validatePath(path) except AbortException: reraise(*sys.exc_info()) except Exception as e: title = trailer.get(Movie.TITLE, 'no title') cls._logger.exception('title:', title) path = None if cls._logger.isEnabledFor(LazyLogger.DEBUG_EXTRA_VERBOSE): cls._logger.debug_extra_verbose('Path:', path) return path