Skip to content

Commit

Permalink
Request file change times en block instead of one by one
Browse files Browse the repository at this point in the history
Signed-off-by: Sven Strickroth <email@cs-ware.de>
  • Loading branch information
csware committed May 30, 2017
1 parent 3736652 commit d8e317b
Showing 1 changed file with 65 additions and 34 deletions.
99 changes: 65 additions & 34 deletions src/TGitCache/CachedDirectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -784,48 +784,79 @@ void CCachedDirectory::RefreshStatus(bool bRecursive)
// Make sure that our own status is up-to-date
GetStatusForMember(m_directoryPath,bRecursive);

AutoLocker lock(m_critSec);
// We also need to check if all our file members have the right date on them
CacheEntryMap::iterator itMembers;
std::set<CTGitPath> refreshedpaths;
CTGitPathList updatePathList;
CTGitPathList crawlPathList;
CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) L": RefreshStatus for %s\n", m_directoryPath.GetWinPath());

ULONGLONG now = GetTickCount64();
if (m_entryCache.empty())
return;
for (itMembers = m_entryCache.begin(); itMembers != m_entryCache.end(); ++itMembers)
{
if (itMembers->first)
// get the file write times with FindFirstFile/FindNextFile since those
// APIs only access the folder, not each file individually.
// This reduces the disk access a *lot*.
std::map<CString, ULONGLONG> filetimes;
WIN32_FIND_DATA FindFileData;
CAutoFindFile hFind = ::FindFirstFileEx(m_directoryPath.GetWinPathString() + L"\\*.*", FindExInfoBasic, &FindFileData, FindExSearchNameMatch, nullptr, FIND_FIRST_EX_LARGE_FETCH);
if (hFind)
{
CTGitPath filePath(m_directoryPath);
filePath.AppendPathString(itMembers->first);
std::set<CTGitPath>::iterator refr_it;
if ((!filePath.IsEquivalentToWithoutCase(m_directoryPath))&&
(((refr_it = refreshedpaths.lower_bound(filePath)) == refreshedpaths.end()) || !filePath.IsEquivalentToWithoutCase(*refr_it)))
do
{
if ((itMembers->second.HasExpired(now))||(!itMembers->second.DoesFileTimeMatch(filePath.GetLastWriteTime())))
{
lock.Unlock();
// We need to request this item as well
GetStatusForMember(filePath,bRecursive);
// GetStatusForMember now has recreated the m_entryCache map.
// So start the loop again, but add this path to the refreshed paths set
// to make sure we don't refresh this path again. This is to make sure
// that we don't end up in an endless loop.
lock.Lock();
refreshedpaths.insert(refr_it, filePath);
itMembers = m_entryCache.begin();
if (m_entryCache.empty())
return;
if (wcscmp(FindFileData.cFileName, L"..") == 0 || wcscmp(FindFileData.cFileName, L".") == 0)
continue;
}
else if ((bRecursive)&&(itMembers->second.IsDirectory()))
{
// crawl all sub folders too! Otherwise a change deep inside the
// tree which has changed won't get propagated up the tree.
CGitStatusCache::Instance().AddFolderForCrawling(filePath);
}

ULARGE_INTEGER ft;
ft.LowPart = FindFileData.ftLastWriteTime.dwLowDateTime;
ft.HighPart = FindFileData.ftLastWriteTime.dwHighDateTime;

filetimes[FindFileData.cFileName] = ft.QuadPart;
} while (::FindNextFile(hFind, &FindFileData));

hFind.CloseHandle(); // explicit close handle to shorten its life time
}

AutoLocker lock(m_critSec);
// We also need to check if all our file members have the right date on them
for (auto itMembers = m_entryCache.cbegin(); itMembers != m_entryCache.cend(); ++itMembers)
{
if (!itMembers->first || itMembers->first.IsEmpty())
continue;

CTGitPath filePath(GetFullPathString(itMembers->first));
if (filePath.IsEquivalentToWithoutCase(m_directoryPath))
continue;

// we only have file members in our entry cache
//ATLASSERT(!itMembers->second.IsDirectory());

auto ftIt = filetimes.find(itMembers->first);
if (ftIt == filetimes.end())
continue;

ULONGLONG ft = ftIt->second;
if (itMembers->second.HasExpired(now) || !itMembers->second.DoesFileTimeMatch(ft))
{
// We need to request this item as well
updatePathList.AddPath(filePath);
}
}

if (bRecursive)
{
// crawl all sub folders too! Otherwise a change deep inside the
// tree which has changed won't get propagated up the tree.
for (auto it = m_childDirectories.cbegin(); it != m_childDirectories.cend(); ++it)
{
CTGitPath path;
path.SetFromWin(it->first, true);
crawlPathList.AddPath(path);
}
}
}

for (int i = 0; i < updatePathList.GetCount(); ++i)
GetStatusForMember(updatePathList[i], bRecursive);

for (int i = 0; i < crawlPathList.GetCount(); ++i)
CGitStatusCache::Instance().AddFolderForCrawling(crawlPathList[i]);
}

void CCachedDirectory::RefreshMostImportant()
Expand Down

0 comments on commit d8e317b

Please sign in to comment.