Skip to content

Commit

Permalink
shell_integration on Windows: Avoid too many RETRIEVE_FILE_STATUS fol…
Browse files Browse the repository at this point in the history
…lowing UPDATE_VIEW owncloud#3122

Do not request the status of all entries in the cache. Instead force
explorer to request the ones that it deems necessary by keeping the old
statuses in a separate dictionary which are only used while the new status
arrives.
  • Loading branch information
jturcotte committed May 6, 2015
1 parent 7767979 commit 0d5d2c5
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
33 changes: 23 additions & 10 deletions shell_integration/windows/OCUtil/RemotePathChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ void RemotePathChecker::workerThreadLoop()
++it;
}
}
// Assume that we won't need this at this point, UNREGISTER_PATH is rare
_oldCache.clear();
}
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_PATH | SHCNF_FLUSHNOWAIT, responsePath.data(), NULL);
} else if (StringUtil::begins_with(response, wstring(L"STATUS:")) ||
Expand Down Expand Up @@ -132,20 +134,25 @@ void RemotePathChecker::workerThreadLoop()
}
else if (StringUtil::begins_with(response, wstring(L"UPDATE_VIEW"))) {
std::unique_lock<std::mutex> lock(_mutex);
auto cache = _cache; // Make a copy of the cache under the mutex
// Keep the old states to continue having something to display while the new state is
// requested from the client, triggered by clearing _cache.
_oldCache.insert(_cache.cbegin(), _cache.cend());

// Swap to make a copy of the cache under the mutex and clear the one stored.
std::unordered_map<std::wstring, FileState> cache;
swap(cache, _cache);
lock.unlock();
// Request a status for all the items in the cache.
for (auto it = cache.begin(); it != cache.end(); ++it) {
if (!socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + it->first + L'\n').data())) {
break;
}
}
}
// Let explorer know about the invalidated cache entries, it will re-request the ones it needs.
for (auto it = cache.begin(); it != cache.end(); ++it) {
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH | SHCNF_FLUSHNOWAIT, it->first.data(), NULL);
}
}
}

if (socket.Event() == INVALID_HANDLE_VALUE) {
std::unique_lock<std::mutex> lock(_mutex);
_cache.clear();
_oldCache.clear();
_watchedDirectories.clear();
_connected = connected = false;
}
Expand Down Expand Up @@ -198,11 +205,17 @@ bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
return true;
}

// Re-request the status while we display what we have in _oldCache
_pending.push(filePath);

it = _oldCache.find(path);
bool foundInOldCache = it != _oldCache.end();
if (foundInOldCache)
*state = it->second;

lock.unlock();
SetEvent(_newQueries);
return false;

return foundInOldCache;
}

RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstring &str)
Expand Down
1 change: 1 addition & 0 deletions shell_integration/windows/OCUtil/RemotePathChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class __declspec(dllexport) RemotePathChecker {
std::queue<std::wstring> _pending;

std::unordered_map<std::wstring, FileState> _cache;
std::unordered_map<std::wstring, FileState> _oldCache;
std::vector<std::wstring> _watchedDirectories;
bool _connected;

Expand Down

0 comments on commit 0d5d2c5

Please sign in to comment.