void AvatarManager::RemoveOldAvatarCacheEntries() { string cacheDir; { boost::mutex::scoped_lock lock(m_cacheDirMutex); cacheDir = m_cacheDir; } try { path cachePath(cacheDir); cacheDir = cachePath.directory_string(); // Never delete anything if we do not have a special cache dir set. if (!cacheDir.empty()) { boost::mutex::scoped_lock lock(m_cachedAvatarsMutex); // First pass: Remove files which no longer exist. // Count files and record age. AvatarList removeList; TimeAvatarMap timeMap; { AvatarMap::const_iterator i = m_cachedAvatars.begin(); AvatarMap::const_iterator end = m_cachedAvatars.end(); while (i != end) { bool keepFile = false; path filePath(i->second); string fileString(filePath.file_string()); // Only consider files which are definitely in the cache dir. if (fileString.size() > cacheDir.size() && fileString.substr(0, cacheDir.size()) == cacheDir) { // Only consider files with MD5 as file name. MD5Buf tmpBuf; if (exists(filePath) && tmpBuf.FromString(basename(filePath))) { timeMap.insert(TimeAvatarMap::value_type(last_write_time(filePath), i->first)); keepFile = true; } } if (!keepFile) removeList.push_back(i->first); ++i; } } { AvatarList::const_iterator i = removeList.begin(); AvatarList::const_iterator end = removeList.end(); while (i != end) { m_cachedAvatars.erase(*i); ++i; } removeList.clear(); } // Remove and physically delete files in one of the // following cases: // 1. More than MAX_NUMBER_OF_FILES files are present // - delete until only MAX_NUMBER_OF_FILES/2 are left. // 2. Files are older than 30 days. if (m_cachedAvatars.size() > MAX_NUMBER_OF_FILES) { while (!timeMap.empty() && m_cachedAvatars.size() > MAX_NUMBER_OF_FILES / 2) { TimeAvatarMap::iterator i = timeMap.begin(); AvatarMap::iterator pos = m_cachedAvatars.find(i->second); if (pos != m_cachedAvatars.end()) { path tmpPath(pos->second); remove(tmpPath); m_cachedAvatars.erase(pos); } timeMap.erase(i); } } // Get reference time. time_t curTime = time(NULL); while (!timeMap.empty() && !m_cachedAvatars.empty()) { TimeAvatarMap::iterator i = timeMap.begin(); if (curTime - i->first < (int)MAX_AVATAR_CACHE_AGE) break; AvatarMap::iterator pos = m_cachedAvatars.find(i->second); if (pos != m_cachedAvatars.end()) { path tmpPath(pos->second); remove(tmpPath); m_cachedAvatars.erase(pos); } timeMap.erase(i); } } } catch (...) { LOG_ERROR("Exception caught while cleaning up cache."); } }