Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VideoInfoScanner slightly optimized #1191

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 62 additions & 35 deletions xbmc/video/VideoInfoScanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,9 @@ namespace VIDEO
m_pObserver = pObserver;
}

bool CVideoInfoScanner::DoScan(const CStdString& strDirectory)
bool CVideoInfoScanner::DoScan(const CFileItemPtr& file)
{
CStdString strDirectory = file->GetPath();
if (m_pObserver)
{
m_pObserver->OnDirectoryChanged(strDirectory);
Expand Down Expand Up @@ -233,7 +234,7 @@ namespace VIDEO
if (m_pObserver)
m_pObserver->OnStateChanged(content == CONTENT_MOVIES ? FETCHING_MOVIE_INFO : FETCHING_MUSICVIDEO_INFO);

CStdString fastHash = GetFastHash(strDirectory);
CStdString fastHash = GetFastHash(file);
if (m_database.GetPathHash(strDirectory, dbHash) && !fastHash.IsEmpty() && fastHash == dbHash)
{ // fast hashes match - no need to process anything
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' due to no change (fasthash)", strDirectory.c_str());
Expand All @@ -243,32 +244,41 @@ namespace VIDEO
if (!bSkip)
{ // need to fetch the folder
CDirectory::GetDirectory(strDirectory, items, g_settings.m_videoExtensions);
items.Stack();
// compute hash
GetPathHash(items, hash);
if (hash != dbHash && !hash.IsEmpty())
{
if (dbHash.IsEmpty())
CLog::Log(LOGDEBUG, "VideoInfoScanner: Scanning dir '%s' as not in the database", strDirectory.c_str());
else
CLog::Log(LOGDEBUG, "VideoInfoScanner: Rescanning dir '%s' due to change (%s != %s)", strDirectory.c_str(), dbHash.c_str(), hash.c_str());
}
else
{ // they're the same or the hash is empty (dir empty/dir not retrievable)
if (hash.IsEmpty() && !dbHash.IsEmpty())
if (!foundDirectly || settings.parent_name_root || !settings.parent_name)
{ // folder may contain movies
items.Stack();
// compute hash
GetPathHash(items, hash);
if (hash != dbHash && !hash.IsEmpty())
{
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' as it's empty or doesn't exist - adding to clean list", strDirectory.c_str());
m_pathsToClean.insert(m_database.GetPathId(strDirectory));
if (dbHash.IsEmpty())
CLog::Log(LOGDEBUG, "VideoInfoScanner: Scanning dir '%s' as not in the database", strDirectory.c_str());
else
CLog::Log(LOGDEBUG, "VideoInfoScanner: Rescanning dir '%s' due to change (%s != %s)", strDirectory.c_str(), dbHash.c_str(), hash.c_str());
}
else
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' due to no change", strDirectory.c_str());
{ // they're the same or the hash is empty (dir empty/dir not retrievable)
if (hash.IsEmpty() && !dbHash.IsEmpty())
{
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' as it's empty or doesn't exist - adding to clean list", strDirectory.c_str());
m_pathsToClean.insert(m_database.GetPathId(strDirectory));
}
else
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' due to no change", strDirectory.c_str());
bSkip = true;
if (m_pObserver)
m_pObserver->OnDirectoryScanned(strDirectory);
}
// update the hash to a fast hash if needed
// it's okay to fast hash movies in seperate dirs (that are not scanned recursively)
if (!fastHash.IsEmpty() && ((settings.parent_name && settings.recurse <= 1) || CanFastHash(items)))
hash = fastHash;
}
else
{
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' because we don't expect to find movie info in a root dir that contain movies in seperate folders", strDirectory.c_str());
bSkip = true;
if (m_pObserver)
m_pObserver->OnDirectoryScanned(strDirectory);
}
// update the hash to a fast hash if needed
if (CanFastHash(items) && !fastHash.IsEmpty())
hash = fastHash;
}
}
else if (content == CONTENT_TVSHOWS)
Expand Down Expand Up @@ -336,7 +346,7 @@ namespace VIDEO
// do not recurse for tv shows - we have already looked recursively for episodes
if (pItem->m_bIsFolder && !pItem->IsParentFolder() && !pItem->IsPlayList() && settings.recurse > 0 && content != CONTENT_TVSHOWS)
{
if (!DoScan(pItem->GetPath()))
if (!DoScan(pItem))
{
m_bStop = true;
}
Expand All @@ -345,6 +355,13 @@ namespace VIDEO
return !m_bStop;
}

bool CVideoInfoScanner::DoScan(const CStdString& strDirectory)
{
// wrap the strDirectory in a CFileItemPtr so we can start using the recursive DoScan() method
CFileItemPtr filePtr = CFileItemPtr(new CFileItem(strDirectory, true));
return DoScan(filePtr);
}

bool CVideoInfoScanner::RetrieveVideoInfo(CFileItemList& items, bool bDirNames, CONTENT_TYPE content, bool useLocal, CScraperUrl* pURL, bool fetchEpisodes, CGUIDialogProgress* pDlgProgress)
{
if (pDlgProgress)
Expand Down Expand Up @@ -1551,19 +1568,29 @@ namespace VIDEO
return items.GetFolderCount() == 0;
}

CStdString CVideoInfoScanner::GetFastHash(const CStdString &directory) const
{
struct __stat64 buffer;
if (XFILE::CFile::Stat(directory, &buffer) == 0)
CStdString CVideoInfoScanner::GetFastHash(const CFileItemPtr& file) const
{ // attempt to use the time we've already retrieved
CStdString hash;
time_t timet;
file->m_dateTime.GetAsTime(timet);
if (timet)
{
int64_t time = buffer.st_mtime;
if (!time)
time = buffer.st_ctime;
if (time)
hash.Format("fast%"PRIu32, timet);
return hash;
}
else
{ // fall back to doing a stat() call
struct __stat64 buffer;
if (XFILE::CFile::Stat(file->GetPath(), &buffer) == 0)
{
CStdString hash;
hash.Format("fast%"PRId64, time);
return hash;
int64_t time = buffer.st_mtime;
if (!time)
time = buffer.st_ctime;
if (time)
{
hash.Format("fast%"PRId64, time);
return hash;
}
}
}
return "";
Expand Down
8 changes: 5 additions & 3 deletions xbmc/video/VideoInfoScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ namespace VIDEO

protected:
virtual void Process();
bool DoScan(const CFileItemPtr& file);
bool DoScan(const CStdString& strDirectory);

INFO_RET RetrieveInfoForTvShow(CFileItemPtr pItem, bool bDirNames, ADDON::ScraperPtr &scraper, bool useLocal, CScraperUrl* pURL, bool fetchEpisodes, CGUIDialogProgress* pDlgProgress);
Expand Down Expand Up @@ -197,13 +198,14 @@ namespace VIDEO
static int GetPathHash(const CFileItemList &items, CStdString &hash);

/*! \brief Retrieve a "fast" hash of the given directory (if available)
Performs a stat() on the directory, and uses modified time to create a "fast"
hash of the folder. If no modified time is available, the create time is used,
Uses the date of the directory to create a "fast" hash. If the directory has no date
a stat() is performed on the directory, and the modified time is used to create a
"fast" hash of the folder. If no modified time is available, the create time is used,
and if neither are available, an empty hash is returned.
\param directory folder to hash
\return the hash of the folder of the form "fast<datetime>"
*/
CStdString GetFastHash(const CStdString &directory) const;
CStdString GetFastHash(const CFileItemPtr &file) const;

/*! \brief Decide whether a folder listing could use the "fast" hash
Fast hashing can be done whenever the folder contains no scannable subfolders, as the
Expand Down