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 Original file line Diff line number Diff line change
Expand Up @@ -190,8 +190,9 @@ namespace VIDEO
m_pObserver = pObserver; m_pObserver = pObserver;
} }


bool CVideoInfoScanner::DoScan(const CStdString& strDirectory) bool CVideoInfoScanner::DoScan(const CFileItemPtr& file)
{ {
CStdString strDirectory = file->GetPath();
if (m_pObserver) if (m_pObserver)
{ {
m_pObserver->OnDirectoryChanged(strDirectory); m_pObserver->OnDirectoryChanged(strDirectory);
Expand Down Expand Up @@ -233,7 +234,7 @@ namespace VIDEO
if (m_pObserver) if (m_pObserver)
m_pObserver->OnStateChanged(content == CONTENT_MOVIES ? FETCHING_MOVIE_INFO : FETCHING_MUSICVIDEO_INFO); 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) if (m_database.GetPathHash(strDirectory, dbHash) && !fastHash.IsEmpty() && fastHash == dbHash)
{ // fast hashes match - no need to process anything { // fast hashes match - no need to process anything
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' due to no change (fasthash)", strDirectory.c_str()); 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) if (!bSkip)
{ // need to fetch the folder { // need to fetch the folder
CDirectory::GetDirectory(strDirectory, items, g_settings.m_videoExtensions); CDirectory::GetDirectory(strDirectory, items, g_settings.m_videoExtensions);
items.Stack(); if (!foundDirectly || settings.parent_name_root || !settings.parent_name)
// compute hash { // folder may contain movies
GetPathHash(items, hash); items.Stack();
if (hash != dbHash && !hash.IsEmpty()) // compute hash
{ GetPathHash(items, hash);
if (dbHash.IsEmpty()) if (hash != dbHash && !hash.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())
{ {
CLog::Log(LOGDEBUG, "VideoInfoScanner: Skipping dir '%s' as it's empty or doesn't exist - adding to clean list", strDirectory.c_str()); if (dbHash.IsEmpty())
m_pathsToClean.insert(m_database.GetPathId(strDirectory)); 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 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; 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) 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 // 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 (pItem->m_bIsFolder && !pItem->IsParentFolder() && !pItem->IsPlayList() && settings.recurse > 0 && content != CONTENT_TVSHOWS)
{ {
if (!DoScan(pItem->GetPath())) if (!DoScan(pItem))
{ {
m_bStop = true; m_bStop = true;
} }
Expand All @@ -345,6 +355,13 @@ namespace VIDEO
return !m_bStop; 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) bool CVideoInfoScanner::RetrieveVideoInfo(CFileItemList& items, bool bDirNames, CONTENT_TYPE content, bool useLocal, CScraperUrl* pURL, bool fetchEpisodes, CGUIDialogProgress* pDlgProgress)
{ {
if (pDlgProgress) if (pDlgProgress)
Expand Down Expand Up @@ -1551,19 +1568,29 @@ namespace VIDEO
return items.GetFolderCount() == 0; return items.GetFolderCount() == 0;
} }


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


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


INFO_RET RetrieveInfoForTvShow(CFileItemPtr pItem, bool bDirNames, ADDON::ScraperPtr &scraper, bool useLocal, CScraperUrl* pURL, bool fetchEpisodes, CGUIDialogProgress* pDlgProgress); 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); static int GetPathHash(const CFileItemList &items, CStdString &hash);


/*! \brief Retrieve a "fast" hash of the given directory (if available) /*! \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" Uses the date of the directory to create a "fast" hash. If the directory has no date
hash of the folder. If no modified time is available, the create time is used, 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. and if neither are available, an empty hash is returned.
\param directory folder to hash \param directory folder to hash
\return the hash of the folder of the form "fast<datetime>" \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 /*! \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 Fast hashing can be done whenever the folder contains no scannable subfolders, as the
Expand Down