Permalink
Browse files

VideoInfoScanner slightly optimized

Using assumptions about the user-specified settings the VideoInfoScanner
has been optimized in an attempt to reduce roundtrips when scanning a
movie collection which is mounted from a network location.
  • Loading branch information...
1 parent d92792f commit 8a117f9757703a690e5f1ff24c9bd4aa269e4384 dez-dk committed Jul 20, 2012
Showing with 67 additions and 38 deletions.
  1. +62 −35 xbmc/video/VideoInfoScanner.cpp
  2. +5 −3 xbmc/video/VideoInfoScanner.h
View
97 xbmc/video/VideoInfoScanner.cpp
@@ -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);
@@ -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());
@@ -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)
@@ -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;
}
@@ -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)
@@ -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 "";
View
8 xbmc/video/VideoInfoScanner.h
@@ -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);
@@ -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

0 comments on commit 8a117f9

Please sign in to comment.