1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/cache2/CacheFileContextEvictor.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,605 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "CacheLog.h" 1.9 +#include "CacheFileContextEvictor.h" 1.10 +#include "CacheFileIOManager.h" 1.11 +#include "CacheIndex.h" 1.12 +#include "CacheIndexIterator.h" 1.13 +#include "CacheFileUtils.h" 1.14 +#include "nsIFile.h" 1.15 +#include "LoadContextInfo.h" 1.16 +#include "nsThreadUtils.h" 1.17 +#include "nsString.h" 1.18 +#include "nsISimpleEnumerator.h" 1.19 +#include "nsIDirectoryEnumerator.h" 1.20 +#include "mozilla/Base64.h" 1.21 + 1.22 + 1.23 +namespace mozilla { 1.24 +namespace net { 1.25 + 1.26 +const char kContextEvictionPrefix[] = "ce_"; 1.27 +const uint32_t kContextEvictionPrefixLength = 1.28 + sizeof(kContextEvictionPrefix) - 1; 1.29 + 1.30 +bool CacheFileContextEvictor::sDiskAlreadySearched = false; 1.31 + 1.32 +CacheFileContextEvictor::CacheFileContextEvictor() 1.33 + : mEvicting(false) 1.34 + , mIndexIsUpToDate(false) 1.35 +{ 1.36 + LOG(("CacheFileContextEvictor::CacheFileContextEvictor() [this=%p]", this)); 1.37 +} 1.38 + 1.39 +CacheFileContextEvictor::~CacheFileContextEvictor() 1.40 +{ 1.41 + LOG(("CacheFileContextEvictor::~CacheFileContextEvictor() [this=%p]", this)); 1.42 +} 1.43 + 1.44 +nsresult 1.45 +CacheFileContextEvictor::Init(nsIFile *aCacheDirectory) 1.46 +{ 1.47 + LOG(("CacheFileContextEvictor::Init()")); 1.48 + 1.49 + nsresult rv; 1.50 + 1.51 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.52 + 1.53 + CacheIndex::IsUpToDate(&mIndexIsUpToDate); 1.54 + 1.55 + mCacheDirectory = aCacheDirectory; 1.56 + 1.57 + rv = aCacheDirectory->Clone(getter_AddRefs(mEntriesDir)); 1.58 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.59 + return rv; 1.60 + } 1.61 + 1.62 + rv = mEntriesDir->AppendNative(NS_LITERAL_CSTRING(kEntriesDir)); 1.63 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.64 + return rv; 1.65 + } 1.66 + 1.67 + if (!sDiskAlreadySearched) { 1.68 + LoadEvictInfoFromDisk(); 1.69 + if ((mEntries.Length() != 0) && mIndexIsUpToDate) { 1.70 + CreateIterators(); 1.71 + StartEvicting(); 1.72 + } 1.73 + } 1.74 + 1.75 + return NS_OK; 1.76 +} 1.77 + 1.78 +uint32_t 1.79 +CacheFileContextEvictor::ContextsCount() 1.80 +{ 1.81 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.82 + 1.83 + return mEntries.Length(); 1.84 +} 1.85 + 1.86 +nsresult 1.87 +CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo) 1.88 +{ 1.89 + LOG(("CacheFileContextEvictor::AddContext() [this=%p, loadContextInfo=%p]", 1.90 + this, aLoadContextInfo)); 1.91 + 1.92 + nsresult rv; 1.93 + 1.94 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.95 + 1.96 + CacheFileContextEvictorEntry *entry = nullptr; 1.97 + for (uint32_t i = 0; i < mEntries.Length(); ++i) { 1.98 + if (mEntries[i]->mInfo->Equals(aLoadContextInfo)) { 1.99 + entry = mEntries[i]; 1.100 + break; 1.101 + } 1.102 + } 1.103 + 1.104 + if (!entry) { 1.105 + entry = new CacheFileContextEvictorEntry(); 1.106 + entry->mInfo = aLoadContextInfo; 1.107 + mEntries.AppendElement(entry); 1.108 + } 1.109 + 1.110 + entry->mTimeStamp = PR_Now() / PR_USEC_PER_MSEC; 1.111 + 1.112 + PersistEvictionInfoToDisk(aLoadContextInfo); 1.113 + 1.114 + if (mIndexIsUpToDate) { 1.115 + // Already existing context could be added again, in this case the iterator 1.116 + // would be recreated. Close the old iterator explicitely. 1.117 + if (entry->mIterator) { 1.118 + entry->mIterator->Close(); 1.119 + entry->mIterator = nullptr; 1.120 + } 1.121 + 1.122 + rv = CacheIndex::GetIterator(aLoadContextInfo, false, 1.123 + getter_AddRefs(entry->mIterator)); 1.124 + if (NS_FAILED(rv)) { 1.125 + // This could probably happen during shutdown. Remove the entry from 1.126 + // the array, but leave the info on the disk. No entry can be opened 1.127 + // during shutdown and we'll load the eviction info on next start. 1.128 + LOG(("CacheFileContextEvictor::AddContext() - Cannot get an iterator. " 1.129 + "[rv=0x%08x]", rv)); 1.130 + mEntries.RemoveElement(entry); 1.131 + return rv; 1.132 + } 1.133 + 1.134 + StartEvicting(); 1.135 + } 1.136 + 1.137 + return NS_OK; 1.138 +} 1.139 + 1.140 +nsresult 1.141 +CacheFileContextEvictor::CacheIndexStateChanged() 1.142 +{ 1.143 + LOG(("CacheFileContextEvictor::CacheIndexStateChanged() [this=%p]", this)); 1.144 + 1.145 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.146 + 1.147 + bool isUpToDate = false; 1.148 + CacheIndex::IsUpToDate(&isUpToDate); 1.149 + if (mEntries.Length() == 0) { 1.150 + // Just save the state and exit, since there is nothing to do 1.151 + mIndexIsUpToDate = isUpToDate; 1.152 + return NS_OK; 1.153 + } 1.154 + 1.155 + if (!isUpToDate && !mIndexIsUpToDate) { 1.156 + // Index is outdated and status has not changed, nothing to do. 1.157 + return NS_OK; 1.158 + } 1.159 + 1.160 + if (isUpToDate && mIndexIsUpToDate) { 1.161 + // Status has not changed, but make sure the eviction is running. 1.162 + if (mEvicting) { 1.163 + return NS_OK; 1.164 + } 1.165 + 1.166 + // We're not evicting, but we should be evicting?! 1.167 + LOG(("CacheFileContextEvictor::CacheIndexStateChanged() - Index is up to " 1.168 + "date, we have some context to evict but eviction is not running! " 1.169 + "Starting now.")); 1.170 + } 1.171 + 1.172 + mIndexIsUpToDate = isUpToDate; 1.173 + 1.174 + if (mIndexIsUpToDate) { 1.175 + CreateIterators(); 1.176 + StartEvicting(); 1.177 + } else { 1.178 + CloseIterators(); 1.179 + } 1.180 + 1.181 + return NS_OK; 1.182 +} 1.183 + 1.184 +nsresult 1.185 +CacheFileContextEvictor::WasEvicted(const nsACString &aKey, nsIFile *aFile, 1.186 + bool *_retval) 1.187 +{ 1.188 + LOG(("CacheFileContextEvictor::WasEvicted() [key=%s]", 1.189 + PromiseFlatCString(aKey).get())); 1.190 + 1.191 + nsresult rv; 1.192 + 1.193 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.194 + 1.195 + nsCOMPtr<nsILoadContextInfo> info = CacheFileUtils::ParseKey(aKey); 1.196 + MOZ_ASSERT(info); 1.197 + if (!info) { 1.198 + LOG(("CacheFileContextEvictor::WasEvicted() - Cannot parse key!")); 1.199 + *_retval = false; 1.200 + return NS_OK; 1.201 + } 1.202 + 1.203 + CacheFileContextEvictorEntry *entry = nullptr; 1.204 + for (uint32_t i = 0; i < mEntries.Length(); ++i) { 1.205 + if (info->Equals(mEntries[i]->mInfo)) { 1.206 + entry = mEntries[i]; 1.207 + break; 1.208 + } 1.209 + } 1.210 + 1.211 + if (!entry) { 1.212 + LOG(("CacheFileContextEvictor::WasEvicted() - Didn't find equal context, " 1.213 + "returning false.")); 1.214 + *_retval = false; 1.215 + return NS_OK; 1.216 + } 1.217 + 1.218 + PRTime lastModifiedTime; 1.219 + rv = aFile->GetLastModifiedTime(&lastModifiedTime); 1.220 + if (NS_FAILED(rv)) { 1.221 + LOG(("CacheFileContextEvictor::WasEvicted() - Cannot get last modified time" 1.222 + ", returning false.")); 1.223 + *_retval = false; 1.224 + return NS_OK; 1.225 + } 1.226 + 1.227 + *_retval = !(lastModifiedTime > entry->mTimeStamp); 1.228 + LOG(("CacheFileContextEvictor::WasEvicted() - returning %s. [mTimeStamp=%lld," 1.229 + " lastModifiedTime=%lld]", *_retval ? "true" : "false", 1.230 + mEntries[0]->mTimeStamp, lastModifiedTime)); 1.231 + 1.232 + return NS_OK; 1.233 +} 1.234 + 1.235 +nsresult 1.236 +CacheFileContextEvictor::PersistEvictionInfoToDisk( 1.237 + nsILoadContextInfo *aLoadContextInfo) 1.238 +{ 1.239 + LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() [this=%p, " 1.240 + "loadContextInfo=%p]", this, aLoadContextInfo)); 1.241 + 1.242 + nsresult rv; 1.243 + 1.244 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.245 + 1.246 + nsCOMPtr<nsIFile> file; 1.247 + rv = GetContextFile(aLoadContextInfo, getter_AddRefs(file)); 1.248 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.249 + return rv; 1.250 + } 1.251 + 1.252 +#ifdef PR_LOGGING 1.253 + nsAutoCString path; 1.254 + file->GetNativePath(path); 1.255 +#endif 1.256 + 1.257 + PRFileDesc *fd; 1.258 + rv = file->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE, 0600, 1.259 + &fd); 1.260 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.261 + LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() - Creating file " 1.262 + "failed! [path=%s, rv=0x%08x]", path.get(), rv)); 1.263 + return rv; 1.264 + } 1.265 + 1.266 + PR_Close(fd); 1.267 + 1.268 + LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() - Successfully " 1.269 + "created file. [path=%s]", path.get())); 1.270 + 1.271 + return NS_OK; 1.272 +} 1.273 + 1.274 +nsresult 1.275 +CacheFileContextEvictor::RemoveEvictInfoFromDisk( 1.276 + nsILoadContextInfo *aLoadContextInfo) 1.277 +{ 1.278 + LOG(("CacheFileContextEvictor::RemoveEvictInfoFromDisk() [this=%p, " 1.279 + "loadContextInfo=%p]", this, aLoadContextInfo)); 1.280 + 1.281 + nsresult rv; 1.282 + 1.283 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.284 + 1.285 + nsCOMPtr<nsIFile> file; 1.286 + rv = GetContextFile(aLoadContextInfo, getter_AddRefs(file)); 1.287 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.288 + return rv; 1.289 + } 1.290 + 1.291 +#ifdef PR_LOGGING 1.292 + nsAutoCString path; 1.293 + file->GetNativePath(path); 1.294 +#endif 1.295 + 1.296 + rv = file->Remove(false); 1.297 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.298 + LOG(("CacheFileContextEvictor::RemoveEvictionInfoFromDisk() - Removing file" 1.299 + " failed! [path=%s, rv=0x%08x]", path.get(), rv)); 1.300 + return rv; 1.301 + } 1.302 + 1.303 + LOG(("CacheFileContextEvictor::RemoveEvictionInfoFromDisk() - Successfully " 1.304 + "removed file. [path=%s]", path.get())); 1.305 + 1.306 + return NS_OK; 1.307 +} 1.308 + 1.309 +nsresult 1.310 +CacheFileContextEvictor::LoadEvictInfoFromDisk() 1.311 +{ 1.312 + LOG(("CacheFileContextEvictor::LoadEvictInfoFromDisk() [this=%p]", this)); 1.313 + 1.314 + nsresult rv; 1.315 + 1.316 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.317 + 1.318 + sDiskAlreadySearched = true; 1.319 + 1.320 + nsCOMPtr<nsISimpleEnumerator> enumerator; 1.321 + rv = mCacheDirectory->GetDirectoryEntries(getter_AddRefs(enumerator)); 1.322 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.323 + return rv; 1.324 + } 1.325 + 1.326 + nsCOMPtr<nsIDirectoryEnumerator> dirEnum = do_QueryInterface(enumerator, &rv); 1.327 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.328 + return rv; 1.329 + } 1.330 + 1.331 + while (true) { 1.332 + nsCOMPtr<nsIFile> file; 1.333 + rv = dirEnum->GetNextFile(getter_AddRefs(file)); 1.334 + if (!file) { 1.335 + break; 1.336 + } 1.337 + 1.338 + bool isDir = false; 1.339 + file->IsDirectory(&isDir); 1.340 + if (isDir) { 1.341 + continue; 1.342 + } 1.343 + 1.344 + nsAutoCString leaf; 1.345 + rv = file->GetNativeLeafName(leaf); 1.346 + if (NS_FAILED(rv)) { 1.347 + LOG(("CacheFileContextEvictor::LoadEvictInfoFromDisk() - " 1.348 + "GetNativeLeafName() failed! Skipping file.")); 1.349 + continue; 1.350 + } 1.351 + 1.352 + if (leaf.Length() < kContextEvictionPrefixLength) { 1.353 + continue; 1.354 + } 1.355 + 1.356 + if (!StringBeginsWith(leaf, NS_LITERAL_CSTRING(kContextEvictionPrefix))) { 1.357 + continue; 1.358 + } 1.359 + 1.360 + nsAutoCString encoded; 1.361 + encoded = Substring(leaf, kContextEvictionPrefixLength); 1.362 + encoded.ReplaceChar('-', '/'); 1.363 + 1.364 + nsAutoCString decoded; 1.365 + rv = Base64Decode(encoded, decoded); 1.366 + if (NS_FAILED(rv)) { 1.367 + LOG(("CacheFileContextEvictor::LoadEvictInfoFromDisk() - Base64 decoding " 1.368 + "failed. Removing the file. [file=%s]", leaf.get())); 1.369 + file->Remove(false); 1.370 + continue; 1.371 + } 1.372 + 1.373 + nsCOMPtr<nsILoadContextInfo> info = CacheFileUtils::ParseKey(decoded); 1.374 + 1.375 + if (!info) { 1.376 + LOG(("CacheFileContextEvictor::LoadEvictInfoFromDisk() - Cannot parse " 1.377 + "context key, removing file. [contextKey=%s, file=%s]", 1.378 + decoded.get(), leaf.get())); 1.379 + file->Remove(false); 1.380 + continue; 1.381 + } 1.382 + 1.383 + PRTime lastModifiedTime; 1.384 + rv = file->GetLastModifiedTime(&lastModifiedTime); 1.385 + if (NS_FAILED(rv)) { 1.386 + continue; 1.387 + } 1.388 + 1.389 + CacheFileContextEvictorEntry *entry = new CacheFileContextEvictorEntry(); 1.390 + entry->mInfo = info; 1.391 + entry->mTimeStamp = lastModifiedTime; 1.392 + mEntries.AppendElement(entry); 1.393 + } 1.394 + 1.395 + return NS_OK; 1.396 +} 1.397 + 1.398 +nsresult 1.399 +CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo, 1.400 + nsIFile **_retval) 1.401 +{ 1.402 + nsresult rv; 1.403 + 1.404 + nsAutoCString leafName; 1.405 + leafName.Assign(NS_LITERAL_CSTRING(kContextEvictionPrefix)); 1.406 + 1.407 + nsAutoCString keyPrefix; 1.408 + CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, keyPrefix); 1.409 + 1.410 + // TODO: This hack is needed because current CacheFileUtils::ParseKey() can 1.411 + // parse only the whole key and not just the key prefix generated by 1.412 + // CacheFileUtils::CreateKeyPrefix(). This should be removed once bug #968593 1.413 + // is fixed. 1.414 + keyPrefix.Append(":foo"); 1.415 + 1.416 + nsAutoCString data64; 1.417 + rv = Base64Encode(keyPrefix, data64); 1.418 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.419 + return rv; 1.420 + } 1.421 + 1.422 + // Replace '/' with '-' since '/' cannot be part of the filename. 1.423 + data64.ReplaceChar('/', '-'); 1.424 + 1.425 + leafName.Append(data64); 1.426 + 1.427 + nsCOMPtr<nsIFile> file; 1.428 + rv = mCacheDirectory->Clone(getter_AddRefs(file)); 1.429 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.430 + return rv; 1.431 + } 1.432 + 1.433 + rv = file->AppendNative(leafName); 1.434 + if (NS_WARN_IF(NS_FAILED(rv))) { 1.435 + return rv; 1.436 + } 1.437 + 1.438 + file.swap(*_retval); 1.439 + return NS_OK; 1.440 +} 1.441 + 1.442 +void 1.443 +CacheFileContextEvictor::CreateIterators() 1.444 +{ 1.445 + LOG(("CacheFileContextEvictor::CreateIterators() [this=%p]", this)); 1.446 + 1.447 + CloseIterators(); 1.448 + 1.449 + nsresult rv; 1.450 + 1.451 + for (uint32_t i = 0; i < mEntries.Length(); ) { 1.452 + rv = CacheIndex::GetIterator(mEntries[i]->mInfo, false, 1.453 + getter_AddRefs(mEntries[i]->mIterator)); 1.454 + if (NS_FAILED(rv)) { 1.455 + LOG(("CacheFileContextEvictor::CreateIterators() - Cannot get an iterator" 1.456 + ". [rv=0x%08x]", rv)); 1.457 + mEntries.RemoveElementAt(i); 1.458 + continue; 1.459 + } 1.460 + 1.461 + ++i; 1.462 + } 1.463 +} 1.464 + 1.465 +void 1.466 +CacheFileContextEvictor::CloseIterators() 1.467 +{ 1.468 + LOG(("CacheFileContextEvictor::CloseIterators() [this=%p]", this)); 1.469 + 1.470 + for (uint32_t i = 0; i < mEntries.Length(); ++i) { 1.471 + if (mEntries[i]->mIterator) { 1.472 + mEntries[i]->mIterator->Close(); 1.473 + mEntries[i]->mIterator = nullptr; 1.474 + } 1.475 + } 1.476 +} 1.477 + 1.478 +void 1.479 +CacheFileContextEvictor::StartEvicting() 1.480 +{ 1.481 + LOG(("CacheFileContextEvictor::StartEvicting() [this=%p]", this)); 1.482 + 1.483 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.484 + 1.485 + if (mEvicting) { 1.486 + LOG(("CacheFileContextEvictor::StartEvicting() - already evicintg.")); 1.487 + return; 1.488 + } 1.489 + 1.490 + if (mEntries.Length() == 0) { 1.491 + LOG(("CacheFileContextEvictor::StartEvicting() - no context to evict.")); 1.492 + return; 1.493 + } 1.494 + 1.495 + nsCOMPtr<nsIRunnable> ev; 1.496 + ev = NS_NewRunnableMethod(this, &CacheFileContextEvictor::EvictEntries); 1.497 + 1.498 + nsRefPtr<CacheIOThread> ioThread = CacheFileIOManager::IOThread(); 1.499 + 1.500 + nsresult rv = ioThread->Dispatch(ev, CacheIOThread::EVICT); 1.501 + if (NS_FAILED(rv)) { 1.502 + LOG(("CacheFileContextEvictor::StartEvicting() - Cannot dispatch event to " 1.503 + "IO thread. [rv=0x%08x]", rv)); 1.504 + } 1.505 + 1.506 + mEvicting = true; 1.507 +} 1.508 + 1.509 +nsresult 1.510 +CacheFileContextEvictor::EvictEntries() 1.511 +{ 1.512 + LOG(("CacheFileContextEvictor::EvictEntries()")); 1.513 + 1.514 + nsresult rv; 1.515 + 1.516 + MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); 1.517 + 1.518 + mEvicting = false; 1.519 + 1.520 + if (!mIndexIsUpToDate) { 1.521 + LOG(("CacheFileContextEvictor::EvictEntries() - Stopping evicting due to " 1.522 + "outdated index.")); 1.523 + return NS_OK; 1.524 + } 1.525 + 1.526 + while (true) { 1.527 + if (CacheIOThread::YieldAndRerun()) { 1.528 + LOG(("CacheFileContextEvictor::EvictEntries() - Breaking loop for higher " 1.529 + "level events.")); 1.530 + mEvicting = true; 1.531 + return NS_OK; 1.532 + } 1.533 + 1.534 + if (mEntries.Length() == 0) { 1.535 + LOG(("CacheFileContextEvictor::EvictEntries() - Stopping evicting, there " 1.536 + "is no context to evict.")); 1.537 + return NS_OK; 1.538 + } 1.539 + 1.540 + SHA1Sum::Hash hash; 1.541 + rv = mEntries[0]->mIterator->GetNextHash(&hash); 1.542 + if (rv == NS_ERROR_NOT_AVAILABLE) { 1.543 + LOG(("CacheFileContextEvictor::EvictEntries() - No more entries left in " 1.544 + "iterator. [iterator=%p, info=%p]", mEntries[0]->mIterator.get(), 1.545 + mEntries[0]->mInfo.get())); 1.546 + RemoveEvictInfoFromDisk(mEntries[0]->mInfo); 1.547 + mEntries.RemoveElementAt(0); 1.548 + continue; 1.549 + } else if (NS_FAILED(rv)) { 1.550 + LOG(("CacheFileContextEvictor::EvictEntries() - Iterator failed to " 1.551 + "provide next hash (shutdown?), keeping eviction info on disk." 1.552 + " [iterator=%p, info=%p]", mEntries[0]->mIterator.get(), 1.553 + mEntries[0]->mInfo.get())); 1.554 + mEntries.RemoveElementAt(0); 1.555 + continue; 1.556 + } 1.557 + 1.558 + LOG(("CacheFileContextEvictor::EvictEntries() - Processing hash. " 1.559 + "[hash=%08x%08x%08x%08x%08x, iterator=%p, info=%p]", LOGSHA1(&hash), 1.560 + mEntries[0]->mIterator.get(), mEntries[0]->mInfo.get())); 1.561 + 1.562 + nsRefPtr<CacheFileHandle> handle; 1.563 + CacheFileIOManager::gInstance->mHandles.GetHandle(&hash, false, 1.564 + getter_AddRefs(handle)); 1.565 + if (handle) { 1.566 + // We doom any active handle in CacheFileIOManager::EvictByContext(), so 1.567 + // this must be a new one. Skip it. 1.568 + LOG(("CacheFileContextEvictor::EvictEntries() - Skipping entry since we " 1.569 + "found an active handle. [handle=%p]", handle.get())); 1.570 + continue; 1.571 + } 1.572 + 1.573 + nsAutoCString leafName; 1.574 + CacheFileIOManager::HashToStr(&hash, leafName); 1.575 + 1.576 + PRTime lastModifiedTime; 1.577 + nsCOMPtr<nsIFile> file; 1.578 + rv = mEntriesDir->Clone(getter_AddRefs(file)); 1.579 + if (NS_SUCCEEDED(rv)) { 1.580 + rv = file->AppendNative(leafName); 1.581 + } 1.582 + if (NS_SUCCEEDED(rv)) { 1.583 + rv = file->GetLastModifiedTime(&lastModifiedTime); 1.584 + } 1.585 + if (NS_FAILED(rv)) { 1.586 + LOG(("CacheFileContextEvictor::EvictEntries() - Cannot get last modified " 1.587 + "time, skipping entry.")); 1.588 + continue; 1.589 + } 1.590 + 1.591 + if (lastModifiedTime > mEntries[0]->mTimeStamp) { 1.592 + LOG(("CacheFileContextEvictor::EvictEntries() - Skipping newer entry. " 1.593 + "[mTimeStamp=%lld, lastModifiedTime=%lld]", mEntries[0]->mTimeStamp, 1.594 + lastModifiedTime)); 1.595 + continue; 1.596 + } 1.597 + 1.598 + LOG(("CacheFileContextEvictor::EvictEntries - Removing entry.")); 1.599 + file->Remove(false); 1.600 + CacheIndex::RemoveEntry(&hash); 1.601 + } 1.602 + 1.603 + NS_NOTREACHED("We should never get here"); 1.604 + return NS_OK; 1.605 +} 1.606 + 1.607 +} // net 1.608 +} // mozilla