diff options
-rw-r--r-- | net/disk_cache/backend_unittest.cc | 42 | ||||
-rw-r--r-- | net/disk_cache/block_files.cc | 9 | ||||
-rw-r--r-- | net/disk_cache/cache_util_win.cc | 18 | ||||
-rw-r--r-- | net/disk_cache/entry_impl.cc | 10 | ||||
-rw-r--r-- | net/disk_cache/file_win.cc | 12 |
5 files changed, 75 insertions, 16 deletions
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 43b59e8..adfc95c 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc @@ -12,6 +12,7 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/disk_cache/backend_impl.h" +#include "net/disk_cache/cache_util.h" #include "net/disk_cache/disk_cache_test_base.h" #include "net/disk_cache/disk_cache_test_util.h" #include "net/disk_cache/histogram_macros.h" @@ -1889,3 +1890,44 @@ TEST_F(DiskCacheBackendTest, TotalBuffersSize2) { EXPECT_FALSE(cache_impl_->IsAllocAllowed(0, kOneMB)); } + +// Tests that sharing of external files works and we are able to delete the +// files when we need to. +TEST_F(DiskCacheBackendTest, FileSharing) { + SetDirectMode(); + InitCache(); + + disk_cache::Addr address(0x80000001); + ASSERT_TRUE(cache_impl_->CreateExternalFile(&address)); + FilePath name = cache_impl_->GetFileName(address); + + scoped_refptr<disk_cache::File> file(new disk_cache::File(false)); + file->Init(name); + +#if defined(OS_WIN) + DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD access = GENERIC_READ | GENERIC_WRITE; + ScopedHandle file2(CreateFile(name.value().c_str(), access, sharing, NULL, + OPEN_EXISTING, 0, NULL)); + EXPECT_FALSE(file2.IsValid()); + + sharing |= FILE_SHARE_DELETE; + file2.Set(CreateFile(name.value().c_str(), access, sharing, NULL, + OPEN_EXISTING, 0, NULL)); + EXPECT_TRUE(file2.IsValid()); +#endif + + EXPECT_TRUE(file_util::Delete(name, false)); + + // We should be able to use the file. + const int kSize = 200; + char buffer1[kSize]; + char buffer2[kSize]; + memset(buffer1, 't', kSize); + memset(buffer2, 0, kSize); + EXPECT_TRUE(file->Write(buffer1, kSize, 0)); + EXPECT_TRUE(file->Read(buffer2, kSize, 0)); + EXPECT_EQ(0, memcmp(buffer1, buffer2, kSize)); + + EXPECT_TRUE(disk_cache::DeleteCacheFile(name)); +} diff --git a/net/disk_cache/block_files.cc b/net/disk_cache/block_files.cc index 7936b8f..a0fc6b6 100644 --- a/net/disk_cache/block_files.cc +++ b/net/disk_cache/block_files.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -466,10 +466,15 @@ void BlockFiles::RemoveEmptyFile(FileType block_type) { int file_index = header->next_file; header->next_file = next_header->next_file; DCHECK(block_files_.size() >= static_cast<unsigned int>(file_index)); + + // We get a new handle to the file and release the old one so that the + // file gets unmmaped... so we can delete it. + FilePath name = Name(file_index); + scoped_refptr<File> this_file(new File(false)); + this_file->Init(name); block_files_[file_index]->Release(); block_files_[file_index] = NULL; - FilePath name = Name(file_index); int failure = DeleteCacheFile(name) ? 0 : 1; UMA_HISTOGRAM_COUNTS("DiskCache.DeleteFailed2", failure); if (failure) diff --git a/net/disk_cache/cache_util_win.cc b/net/disk_cache/cache_util_win.cc index aefce30..3e1d673 100644 --- a/net/disk_cache/cache_util_win.cc +++ b/net/disk_cache/cache_util_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -58,7 +58,21 @@ void DeleteCache(const FilePath& path, bool remove_folder) { bool DeleteCacheFile(const FilePath& name) { // We do a simple delete, without ever falling back to SHFileOperation, as the // version from base does. - return DeleteFile(name.value().c_str()) ? true : false; + if (!DeleteFile(name.value().c_str())) { + // There is an error, but we share delete access so let's see if there is a + // file to open. Note that this code assumes that we have a handle to the + // file at all times (even now), so nobody can have a handle that prevents + // us from opening the file again (unless it was deleted). + DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + DWORD access = SYNCHRONIZE; + ScopedHandle file(CreateFile(name.value().c_str(), access, sharing, NULL, + OPEN_EXISTING, 0, NULL)); + if (file.IsValid()) + return false; + + // Most likely there is no file to open... and that's what we wanted. + } + return true; } } // namespace disk_cache diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc index c8ee9b0..0655b28 100644 --- a/net/disk_cache/entry_impl.cc +++ b/net/disk_cache/entry_impl.cc @@ -945,14 +945,14 @@ void EntryImpl::DeleteData(Addr address, int index) { if (!address.is_initialized()) return; if (address.is_separate_file()) { - if (files_[index]) - files_[index] = NULL; // Releases the object. - - int failure = DeleteCacheFile(backend_->GetFileName(address)) ? 0 : 1; + int failure = !DeleteCacheFile(backend_->GetFileName(address)); CACHE_UMA(COUNTS, "DeleteFailed", 0, failure); - if (failure) + if (failure) { LOG(ERROR) << "Failed to delete " << backend_->GetFileName(address).value() << " from the cache."; + } + if (files_[index]) + files_[index] = NULL; // Releases the object. } else { backend_->DeleteBlock(address, true); } diff --git a/net/disk_cache/file_win.cc b/net/disk_cache/file_win.cc index 1ac6c24..5b01224 100644 --- a/net/disk_cache/file_win.cc +++ b/net/disk_cache/file_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -72,9 +72,9 @@ bool File::Init(const FilePath& name) { if (init_) return false; - platform_file_ = CreateFile(name.value().c_str(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + DWORD access = GENERIC_READ | GENERIC_WRITE | DELETE; + platform_file_ = CreateFile(name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (INVALID_HANDLE_VALUE == platform_file_) @@ -84,9 +84,7 @@ bool File::Init(const FilePath& name) { platform_file_, Singleton<CompletionHandler>::get()); init_ = true; - sync_platform_file_ = CreateFile(name.value().c_str(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + sync_platform_file_ = CreateFile(name.value().c_str(), access, sharing, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == sync_platform_file_) |