Commit 0bced2c0 authored by Kenichi Ishibashi's avatar Kenichi Ishibashi Committed by Commit Bot

Improve memory management in ServiceWorkerDiskCache

This is a refactoring CL to avoid raw pointer allocations in
ServiceWorkerDiskCache. To remove raw pointers, this CL changes
CreateEntry(), OpenEntry(), DoomEntry() from //net-style maybe-async
to always-call-callback style. This CL also removes
ServiceWorkerDiskCacheEntry::Close() to make its lifetime less
surprising.

Bug: 1117369, 586174
Change-Id: Ie310446b8b55361c47b778237af1a5f6f5582bf0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2484022
Commit-Queue: Victor Costan <pwnall@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820856}
parent 82fce1db
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "net/base/cache_type.h" #include "net/base/cache_type.h"
#include "net/base/completion_once_callback.h"
#include "net/base/completion_repeating_callback.h" #include "net/base/completion_repeating_callback.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
...@@ -59,8 +60,10 @@ ServiceWorkerDiskCacheEntry::ServiceWorkerDiskCacheEntry( ...@@ -59,8 +60,10 @@ ServiceWorkerDiskCacheEntry::ServiceWorkerDiskCacheEntry(
} }
ServiceWorkerDiskCacheEntry::~ServiceWorkerDiskCacheEntry() { ServiceWorkerDiskCacheEntry::~ServiceWorkerDiskCacheEntry() {
if (cache_) if (disk_cache_entry_) {
disk_cache_entry_->Close();
cache_->RemoveOpenEntry(this); cache_->RemoveOpenEntry(this);
}
} }
int ServiceWorkerDiskCacheEntry::Read(int index, int ServiceWorkerDiskCacheEntry::Read(int index,
...@@ -94,106 +97,11 @@ int64_t ServiceWorkerDiskCacheEntry::GetSize(int index) { ...@@ -94,106 +97,11 @@ int64_t ServiceWorkerDiskCacheEntry::GetSize(int index) {
return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L; return disk_cache_entry_ ? disk_cache_entry_->GetDataSize(index) : 0L;
} }
void ServiceWorkerDiskCacheEntry::Close() {
if (disk_cache_entry_)
disk_cache_entry_->Close();
delete this;
}
void ServiceWorkerDiskCacheEntry::Abandon() { void ServiceWorkerDiskCacheEntry::Abandon() {
cache_ = nullptr;
disk_cache_entry_->Close(); disk_cache_entry_->Close();
disk_cache_entry_ = nullptr; disk_cache_entry_ = nullptr;
} }
namespace {
// Separate object to hold state for each Create, Delete, or Doom call
// while the call is in-flight and to produce an EntryImpl upon completion.
class ActiveCall : public base::RefCounted<ActiveCall> {
public:
ActiveCall(const base::WeakPtr<ServiceWorkerDiskCache>& owner,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback)
: owner_(owner), entry_(entry), callback_(std::move(callback)) {
DCHECK(owner_);
}
static net::Error CreateEntry(
const base::WeakPtr<ServiceWorkerDiskCache>& owner,
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call =
base::MakeRefCounted<ActiveCall>(owner, entry, std::move(callback));
disk_cache::EntryResult result = owner->disk_cache()->CreateEntry(
base::NumberToString(key), net::HIGHEST,
base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(std::move(result));
}
static net::Error OpenEntry(
const base::WeakPtr<ServiceWorkerDiskCache>& owner,
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback) {
scoped_refptr<ActiveCall> active_call =
base::MakeRefCounted<ActiveCall>(owner, entry, std::move(callback));
disk_cache::EntryResult result = owner->disk_cache()->OpenEntry(
base::NumberToString(key), net::HIGHEST,
base::BindOnce(&ActiveCall::OnAsyncCompletion, active_call));
return active_call->HandleImmediateReturnValue(std::move(result));
}
static net::Error DoomEntry(
const base::WeakPtr<ServiceWorkerDiskCache>& owner,
int64_t key,
net::CompletionOnceCallback callback) {
return owner->disk_cache()->DoomEntry(base::NumberToString(key),
net::HIGHEST, std::move(callback));
}
private:
friend class base::RefCounted<ActiveCall>;
~ActiveCall() = default;
net::Error HandleImmediateReturnValue(disk_cache::EntryResult result) {
net::Error rv = result.net_error();
if (rv == net::ERR_IO_PENDING) {
// OnAsyncCompletion will be called later.
return rv;
}
if (rv == net::OK) {
*entry_ =
new ServiceWorkerDiskCacheEntry(result.ReleaseEntry(), owner_.get());
}
return rv;
}
void OnAsyncCompletion(disk_cache::EntryResult result) {
int rv = result.net_error();
if (rv == net::OK) {
if (owner_) {
*entry_ = new ServiceWorkerDiskCacheEntry(result.ReleaseEntry(),
owner_.get());
} else {
result.ReleaseEntry()->Close();
rv = net::ERR_ABORTED;
}
}
std::move(callback_).Run(rv);
}
base::WeakPtr<ServiceWorkerDiskCache> owner_;
ServiceWorkerDiskCacheEntry** entry_;
net::CompletionOnceCallback callback_;
};
} // namespace
ServiceWorkerDiskCache::ServiceWorkerDiskCache() = default; ServiceWorkerDiskCache::ServiceWorkerDiskCache() = default;
ServiceWorkerDiskCache::~ServiceWorkerDiskCache() { ServiceWorkerDiskCache::~ServiceWorkerDiskCache() {
...@@ -242,71 +150,107 @@ void ServiceWorkerDiskCache::Disable() { ...@@ -242,71 +150,107 @@ void ServiceWorkerDiskCache::Disable() {
disk_cache_.reset(); disk_cache_.reset();
} }
net::Error ServiceWorkerDiskCache::CreateEntry( void ServiceWorkerDiskCache::CreateEntry(int64_t key, EntryCallback callback) {
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(entry);
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
if (is_disabled_) if (is_disabled_) {
return net::ERR_ABORTED; std::move(callback).Run(net::ERR_ABORTED, nullptr);
return;
}
if (is_initializing_or_waiting_to_initialize()) { if (is_initializing_or_waiting_to_initialize()) {
pending_calls_.emplace_back(PendingCallType::kCreate, key, entry, // Unretained use is safe here because the callback is stored in
std::move(callback)); // `pending_calls_`, which is owned by this instance.
return net::ERR_IO_PENDING; pending_calls_.emplace_back(
base::BindOnce(&ServiceWorkerDiskCache::CreateEntry,
base::Unretained(this), key, std::move(callback)));
return;
}
if (!disk_cache_) {
std::move(callback).Run(net::ERR_FAILED, nullptr);
return;
} }
if (!disk_cache_) DCHECK(!base::Contains(active_entry_calls_, key));
return net::ERR_FAILED; active_entry_calls_.emplace(key, std::move(callback));
return ActiveCall::CreateEntry(weak_factory_.GetWeakPtr(), key, entry, disk_cache::EntryResult result = disk_cache_->CreateEntry(
std::move(callback)); base::NumberToString(key), net::HIGHEST,
base::BindOnce(&ServiceWorkerDiskCache::DidGetEntryResult,
weak_factory_.GetWeakPtr(), key));
if (result.net_error() != net::ERR_IO_PENDING) {
DidGetEntryResult(key, std::move(result));
}
} }
net::Error ServiceWorkerDiskCache::OpenEntry( void ServiceWorkerDiskCache::OpenEntry(int64_t key, EntryCallback callback) {
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(entry);
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
if (is_disabled_) if (is_disabled_) {
return net::ERR_ABORTED; std::move(callback).Run(net::ERR_ABORTED, nullptr);
return;
}
if (is_initializing_or_waiting_to_initialize()) { if (is_initializing_or_waiting_to_initialize()) {
pending_calls_.emplace_back(PendingCallType::kOpen, key, entry, // Unretained use is safe here because the callback is stored in
std::move(callback)); // `pending_calls_`, which is owned by this instance.
return net::ERR_IO_PENDING; pending_calls_.emplace_back(
base::BindOnce(&ServiceWorkerDiskCache::OpenEntry,
base::Unretained(this), key, std::move(callback)));
return;
}
if (!disk_cache_) {
std::move(callback).Run(net::ERR_FAILED, nullptr);
return;
} }
if (!disk_cache_) DCHECK(!base::Contains(active_entry_calls_, key));
return net::ERR_FAILED; active_entry_calls_.emplace(key, std::move(callback));
return ActiveCall::OpenEntry(weak_factory_.GetWeakPtr(), key, entry, disk_cache::EntryResult result = disk_cache_->OpenEntry(
std::move(callback)); base::NumberToString(key), net::HIGHEST,
base::BindOnce(&ServiceWorkerDiskCache::DidGetEntryResult,
weak_factory_.GetWeakPtr(), key));
if (result.net_error() != net::ERR_IO_PENDING) {
DidGetEntryResult(key, std::move(result));
}
} }
net::Error ServiceWorkerDiskCache::DoomEntry( void ServiceWorkerDiskCache::DoomEntry(int64_t key,
int64_t key,
net::CompletionOnceCallback callback) { net::CompletionOnceCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
if (is_disabled_) if (is_disabled_) {
return net::ERR_ABORTED; std::move(callback).Run(net::ERR_ABORTED);
return;
}
if (is_initializing_or_waiting_to_initialize()) { if (is_initializing_or_waiting_to_initialize()) {
pending_calls_.emplace_back(PendingCallType::kDoom, key, nullptr, // Unretained use is safe here because the callback is stored in
std::move(callback)); // `pending_calls_`, which is owned by this instance.
return net::ERR_IO_PENDING; pending_calls_.emplace_back(
base::BindOnce(&ServiceWorkerDiskCache::DoomEntry,
base::Unretained(this), key, std::move(callback)));
return;
}
if (!disk_cache_) {
std::move(callback).Run(net::ERR_FAILED);
return;
} }
if (!disk_cache_) DCHECK(!base::Contains(active_doom_calls_, key));
return net::ERR_FAILED; active_doom_calls_.emplace(key, std::move(callback));
return ActiveCall::DoomEntry(weak_factory_.GetWeakPtr(), key, net::Error net_error = disk_cache_->DoomEntry(
std::move(callback)); base::NumberToString(key), net::HIGHEST,
base::BindOnce(&ServiceWorkerDiskCache::DidDoomEntry,
weak_factory_.GetWeakPtr(), key));
if (net_error != net::ERR_IO_PENDING) {
DidDoomEntry(key, net_error);
}
} }
base::WeakPtr<ServiceWorkerDiskCache> ServiceWorkerDiskCache::GetWeakPtr() { base::WeakPtr<ServiceWorkerDiskCache> ServiceWorkerDiskCache::GetWeakPtr() {
...@@ -314,20 +258,6 @@ base::WeakPtr<ServiceWorkerDiskCache> ServiceWorkerDiskCache::GetWeakPtr() { ...@@ -314,20 +258,6 @@ base::WeakPtr<ServiceWorkerDiskCache> ServiceWorkerDiskCache::GetWeakPtr() {
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
ServiceWorkerDiskCache::PendingCall::PendingCall(
PendingCallType call_type,
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback)
: call_type(call_type),
key(key),
entry(entry),
callback(std::move(callback)) {}
ServiceWorkerDiskCache::PendingCall::PendingCall(PendingCall&& other) = default;
ServiceWorkerDiskCache::PendingCall::~PendingCall() = default;
net::Error ServiceWorkerDiskCache::Init(net::CacheType cache_type, net::Error ServiceWorkerDiskCache::Init(net::CacheType cache_type,
const base::FilePath& cache_directory, const base::FilePath& cache_directory,
int64_t cache_size, int64_t cache_size,
...@@ -369,33 +299,37 @@ void ServiceWorkerDiskCache::OnCreateBackendComplete(int return_value) { ...@@ -369,33 +299,37 @@ void ServiceWorkerDiskCache::OnCreateBackendComplete(int return_value) {
} }
// Service pending calls that were queued up while we were initializing. // Service pending calls that were queued up while we were initializing.
for (auto& call : pending_calls_) { for (auto& call : pending_calls_)
// This is safe, because the callback will only be called once. std::move(call).Run();
net::CompletionRepeatingCallback copyable_callback =
base::AdaptCallbackForRepeating(std::move(call.callback));
return_value = net::ERR_FAILED;
switch (call.call_type) {
case PendingCallType::kCreate:
return_value = CreateEntry(call.key, call.entry, copyable_callback);
break;
case PendingCallType::kOpen:
return_value = OpenEntry(call.key, call.entry, copyable_callback);
break;
case PendingCallType::kDoom:
return_value = DoomEntry(call.key, copyable_callback);
break;
}
// disk_cache::{Create,Open,Doom}Entry() call their callbacks iff they
// return net::ERR_IO_PENDING. In this case, the callback was not called.
// However, the corresponding ServiceWorkerDiskCache wrapper returned
// net::ERR_IO_PENDING as it queued up the pending call. To follow the
// disk_cache API contract, we need to call the callback ourselves here.
if (return_value != net::ERR_IO_PENDING)
copyable_callback.Run(return_value);
}
pending_calls_.clear(); pending_calls_.clear();
} }
void ServiceWorkerDiskCache::DidGetEntryResult(int64_t key,
disk_cache::EntryResult result) {
auto it = active_entry_calls_.find(key);
DCHECK(it != active_entry_calls_.end());
EntryCallback callback = std::move(it->second);
active_entry_calls_.erase(it);
net::Error net_error = result.net_error();
std::unique_ptr<ServiceWorkerDiskCacheEntry> entry;
if (net_error == net::OK) {
entry = std::make_unique<ServiceWorkerDiskCacheEntry>(result.ReleaseEntry(),
this);
}
std::move(callback).Run(net_error, std::move(entry));
}
void ServiceWorkerDiskCache::DidDoomEntry(int64_t key, int net_error) {
auto it = active_doom_calls_.find(key);
DCHECK(it != active_doom_calls_.end());
net::CompletionOnceCallback callback = std::move(it->second);
active_doom_calls_.erase(it);
std::move(callback).Run(net_error);
}
void ServiceWorkerDiskCache::AddOpenEntry(ServiceWorkerDiskCacheEntry* entry) { void ServiceWorkerDiskCache::AddOpenEntry(ServiceWorkerDiskCacheEntry* entry) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
open_entries_.insert(entry); open_entries_.insert(entry);
......
...@@ -33,6 +33,7 @@ class CONTENT_EXPORT ServiceWorkerDiskCacheEntry { ...@@ -33,6 +33,7 @@ class CONTENT_EXPORT ServiceWorkerDiskCacheEntry {
// on destruction. |cache| must outlive the newly created entry. // on destruction. |cache| must outlive the newly created entry.
ServiceWorkerDiskCacheEntry(disk_cache::Entry* disk_cache_entry, ServiceWorkerDiskCacheEntry(disk_cache::Entry* disk_cache_entry,
ServiceWorkerDiskCache* cache); ServiceWorkerDiskCache* cache);
~ServiceWorkerDiskCacheEntry();
// See `disk_cache::Entry::ReadData()`. // See `disk_cache::Entry::ReadData()`.
int Read(int index, int Read(int index,
...@@ -48,21 +49,16 @@ class CONTENT_EXPORT ServiceWorkerDiskCacheEntry { ...@@ -48,21 +49,16 @@ class CONTENT_EXPORT ServiceWorkerDiskCacheEntry {
int buf_len, int buf_len,
net::CompletionOnceCallback callback); net::CompletionOnceCallback callback);
int64_t GetSize(int index); int64_t GetSize(int index);
// Closes the disk cache and destroyes the instance.
void Close();
// Should only be called by ServiceWorkerDiskCache. // Should only be called by ServiceWorkerDiskCache.
void Abandon(); void Abandon();
private: private:
// Call Close() instead of calling this directly.
~ServiceWorkerDiskCacheEntry();
// The disk_cache::Entry is owned by this entry and closed on destruction. // The disk_cache::Entry is owned by this entry and closed on destruction.
disk_cache::Entry* disk_cache_entry_; disk_cache::Entry* disk_cache_entry_;
// The cache that this entry belongs to. // The cache that this entry belongs to.
ServiceWorkerDiskCache* cache_; ServiceWorkerDiskCache* const cache_;
}; };
// net::DiskCache wrapper for the cache used by service worker resources. // net::DiskCache wrapper for the cache used by service worker resources.
...@@ -87,13 +83,15 @@ class CONTENT_EXPORT ServiceWorkerDiskCache { ...@@ -87,13 +83,15 @@ class CONTENT_EXPORT ServiceWorkerDiskCache {
void Disable(); void Disable();
bool is_disabled() const { return is_disabled_; } bool is_disabled() const { return is_disabled_; }
net::Error CreateEntry(int64_t key, using EntryCallback =
ServiceWorkerDiskCacheEntry** entry, base::OnceCallback<void(int rv,
net::CompletionOnceCallback callback); std::unique_ptr<ServiceWorkerDiskCacheEntry>)>;
net::Error OpenEntry(int64_t key,
ServiceWorkerDiskCacheEntry** entry, // Creates/opens/dooms a disk cache entry associated with `key`. These calls
net::CompletionOnceCallback callback); // should not overlap.
net::Error DoomEntry(int64_t key, net::CompletionOnceCallback callback); void CreateEntry(int64_t key, EntryCallback callback);
void OpenEntry(int64_t key, EntryCallback callback);
void DoomEntry(int64_t key, net::CompletionOnceCallback callback);
base::WeakPtr<ServiceWorkerDiskCache> GetWeakPtr(); base::WeakPtr<ServiceWorkerDiskCache> GetWeakPtr();
...@@ -107,30 +105,6 @@ class CONTENT_EXPORT ServiceWorkerDiskCache { ...@@ -107,30 +105,6 @@ class CONTENT_EXPORT ServiceWorkerDiskCache {
class CreateBackendCallbackShim; class CreateBackendCallbackShim;
friend class ServiceWorkerDiskCacheEntry; friend class ServiceWorkerDiskCacheEntry;
// PendingCalls allow CreateEntry, OpenEntry, and DoomEntry to be called
// immediately after construction, without waiting for the
// underlying disk_cache::Backend to be fully constructed. Early
// calls are queued up and serviced once the disk_cache::Backend is
// really ready to go.
enum class PendingCallType { kCreate, kOpen, kDoom };
struct PendingCall {
PendingCall(PendingCallType call_type,
int64_t key,
ServiceWorkerDiskCacheEntry** entry,
net::CompletionOnceCallback callback);
PendingCall(PendingCall&& other);
PendingCall(const PendingCall&) = delete;
PendingCall& operator=(const PendingCall&) = delete;
PendingCall& operator=(PendingCall&&) = delete;
~PendingCall();
const PendingCallType call_type;
const int64_t key;
ServiceWorkerDiskCacheEntry** const entry;
net::CompletionOnceCallback callback;
};
bool is_initializing_or_waiting_to_initialize() const { bool is_initializing_or_waiting_to_initialize() const {
return create_backend_callback_.get() != nullptr || return create_backend_callback_.get() != nullptr ||
is_waiting_to_initialize_; is_waiting_to_initialize_;
...@@ -144,6 +118,9 @@ class CONTENT_EXPORT ServiceWorkerDiskCache { ...@@ -144,6 +118,9 @@ class CONTENT_EXPORT ServiceWorkerDiskCache {
net::CompletionOnceCallback callback); net::CompletionOnceCallback callback);
void OnCreateBackendComplete(int return_value); void OnCreateBackendComplete(int return_value);
void DidGetEntryResult(int64_t key, disk_cache::EntryResult result);
void DidDoomEntry(int64_t key, int net_error);
// Called by ServiceWorkerDiskCacheEntry constructor. // Called by ServiceWorkerDiskCacheEntry constructor.
void AddOpenEntry(ServiceWorkerDiskCacheEntry* entry); void AddOpenEntry(ServiceWorkerDiskCacheEntry* entry);
// Called by ServiceWorkerDiskCacheEntry destructor. // Called by ServiceWorkerDiskCacheEntry destructor.
...@@ -153,7 +130,9 @@ class CONTENT_EXPORT ServiceWorkerDiskCache { ...@@ -153,7 +130,9 @@ class CONTENT_EXPORT ServiceWorkerDiskCache {
bool is_waiting_to_initialize_ = false; bool is_waiting_to_initialize_ = false;
net::CompletionOnceCallback init_callback_; net::CompletionOnceCallback init_callback_;
scoped_refptr<CreateBackendCallbackShim> create_backend_callback_; scoped_refptr<CreateBackendCallbackShim> create_backend_callback_;
std::vector<PendingCall> pending_calls_; std::vector<base::OnceClosure> pending_calls_;
std::map</*key=*/int64_t, EntryCallback> active_entry_calls_;
std::map</*key=*/int64_t, net::CompletionOnceCallback> active_doom_calls_;
std::set<ServiceWorkerDiskCacheEntry*> open_entries_; std::set<ServiceWorkerDiskCacheEntry*> open_entries_;
std::unique_ptr<disk_cache::Backend> disk_cache_; std::unique_ptr<disk_cache::Backend> disk_cache_;
......
...@@ -132,11 +132,7 @@ DiskEntryCreator::DiskEntryCreator( ...@@ -132,11 +132,7 @@ DiskEntryCreator::DiskEntryCreator(
DCHECK(disk_cache_); DCHECK(disk_cache_);
} }
DiskEntryCreator::~DiskEntryCreator() { DiskEntryCreator::~DiskEntryCreator() = default;
if (entry_) {
entry_->Close();
}
}
void DiskEntryCreator::EnsureEntryIsCreated(base::OnceClosure callback) { void DiskEntryCreator::EnsureEntryIsCreated(base::OnceClosure callback) {
DCHECK(creation_phase_ == CreationPhase::kNoAttempt || DCHECK(creation_phase_ == CreationPhase::kNoAttempt ||
...@@ -150,122 +146,84 @@ void DiskEntryCreator::EnsureEntryIsCreated(base::OnceClosure callback) { ...@@ -150,122 +146,84 @@ void DiskEntryCreator::EnsureEntryIsCreated(base::OnceClosure callback) {
} }
if (!disk_cache_) { if (!disk_cache_) {
entry_ = nullptr; entry_.reset();
RunEnsureEntryIsCreatedCallback(); RunEnsureEntryIsCreatedCallback();
return; return;
} }
ServiceWorkerDiskCacheEntry** entry_ptr = new ServiceWorkerDiskCacheEntry*;
creation_phase_ = CreationPhase::kInitialAttempt; creation_phase_ = CreationPhase::kInitialAttempt;
int rv = disk_cache_->CreateEntry( disk_cache_->CreateEntry(
resource_id_, entry_ptr, resource_id_,
base::BindOnce(&DidCreateEntryForFirstAttempt, weak_factory_.GetWeakPtr(), base::BindOnce(&DiskEntryCreator::DidCreateEntryForFirstAttempt,
entry_ptr)); weak_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING) {
DidCreateEntryForFirstAttempt(weak_factory_.GetWeakPtr(), entry_ptr, rv);
}
} }
// static
void DiskEntryCreator::DidCreateEntryForFirstAttempt( void DiskEntryCreator::DidCreateEntryForFirstAttempt(
base::WeakPtr<DiskEntryCreator> entry_creator, int rv,
ServiceWorkerDiskCacheEntry** entry, std::unique_ptr<ServiceWorkerDiskCacheEntry> entry) {
int rv) { DCHECK_EQ(creation_phase_, CreationPhase::kInitialAttempt);
if (!entry_creator) { DCHECK(!entry_);
delete entry;
return;
}
DCHECK_EQ(entry_creator->creation_phase_, CreationPhase::kInitialAttempt); if (!disk_cache_) {
DCHECK(!entry_creator->entry_); entry_.reset();
RunEnsureEntryIsCreatedCallback();
if (!entry_creator->disk_cache_) {
delete entry;
entry_creator->entry_ = nullptr;
entry_creator->RunEnsureEntryIsCreatedCallback();
return; return;
} }
if (rv != net::OK) { if (rv != net::OK) {
// The first attempt to create an entry is failed. Try to overwrite the // The first attempt to create an entry is failed. Try to overwrite the
// existing entry. // existing entry.
delete entry; creation_phase_ = CreationPhase::kDoomExisting;
entry_creator->creation_phase_ = CreationPhase::kDoomExisting; disk_cache_->DoomEntry(
rv = entry_creator->disk_cache_->DoomEntry( resource_id_, base::BindOnce(&DiskEntryCreator::DidDoomExistingEntry,
entry_creator->resource_id_, weak_factory_.GetWeakPtr()));
base::BindOnce(&DiskEntryCreator::DidDoomExistingEntry, entry_creator));
if (rv != net::ERR_IO_PENDING) {
DidDoomExistingEntry(entry_creator, rv);
}
return; return;
} }
DCHECK(entry); DCHECK(entry);
entry_creator->entry_ = *entry; entry_ = std::move(entry);
delete entry; RunEnsureEntryIsCreatedCallback();
entry_creator->RunEnsureEntryIsCreatedCallback();
} }
// static void DiskEntryCreator::DidDoomExistingEntry(int rv) {
void DiskEntryCreator::DidDoomExistingEntry( DCHECK_EQ(creation_phase_, CreationPhase::kDoomExisting);
base::WeakPtr<DiskEntryCreator> entry_creator, DCHECK(!entry_);
int rv) {
if (!entry_creator) {
return;
}
DCHECK_EQ(entry_creator->creation_phase_, CreationPhase::kDoomExisting);
DCHECK(!entry_creator->entry_);
if (!entry_creator->disk_cache_) { if (!disk_cache_) {
entry_creator->entry_ = nullptr; entry_.reset();
entry_creator->RunEnsureEntryIsCreatedCallback(); RunEnsureEntryIsCreatedCallback();
return; return;
} }
entry_creator->creation_phase_ = CreationPhase::kSecondAttempt; creation_phase_ = CreationPhase::kSecondAttempt;
auto** entry_ptr = new ServiceWorkerDiskCacheEntry*; disk_cache_->CreateEntry(
rv = entry_creator->disk_cache_->CreateEntry( resource_id_,
entry_creator->resource_id_, entry_ptr,
base::BindOnce(&DiskEntryCreator::DidCreateEntryForSecondAttempt, base::BindOnce(&DiskEntryCreator::DidCreateEntryForSecondAttempt,
entry_creator, entry_ptr)); weak_factory_.GetWeakPtr()));
if (rv != net::ERR_IO_PENDING) {
DidCreateEntryForSecondAttempt(entry_creator, entry_ptr, rv);
}
} }
// static
void DiskEntryCreator::DidCreateEntryForSecondAttempt( void DiskEntryCreator::DidCreateEntryForSecondAttempt(
base::WeakPtr<DiskEntryCreator> entry_creator, int rv,
ServiceWorkerDiskCacheEntry** entry, std::unique_ptr<ServiceWorkerDiskCacheEntry> entry) {
int rv) { DCHECK_EQ(creation_phase_, CreationPhase::kSecondAttempt);
if (!entry_creator) {
delete entry;
return;
}
DCHECK_EQ(entry_creator->creation_phase_, CreationPhase::kSecondAttempt);
if (!entry_creator->disk_cache_) { if (!disk_cache_) {
delete entry; entry_.reset();
entry_creator->entry_ = nullptr; RunEnsureEntryIsCreatedCallback();
entry_creator->RunEnsureEntryIsCreatedCallback();
return; return;
} }
if (rv != net::OK) { if (rv != net::OK) {
// The second attempt is also failed. Give up creating an entry. // The second attempt is also failed. Give up creating an entry.
delete entry; entry_.reset();
entry_creator->entry_ = nullptr; RunEnsureEntryIsCreatedCallback();
entry_creator->RunEnsureEntryIsCreatedCallback();
return; return;
} }
DCHECK(!entry_creator->entry_); DCHECK(!entry_);
DCHECK(entry); DCHECK(entry);
entry_creator->entry_ = *entry; entry_ = std::move(entry);
entry_creator->RunEnsureEntryIsCreatedCallback(); RunEnsureEntryIsCreatedCallback();
delete entry;
} }
void DiskEntryCreator::RunEnsureEntryIsCreatedCallback() { void DiskEntryCreator::RunEnsureEntryIsCreatedCallback() {
...@@ -281,52 +239,35 @@ DiskEntryOpener::DiskEntryOpener( ...@@ -281,52 +239,35 @@ DiskEntryOpener::DiskEntryOpener(
DCHECK(disk_cache_); DCHECK(disk_cache_);
} }
DiskEntryOpener::~DiskEntryOpener() { DiskEntryOpener::~DiskEntryOpener() = default;
if (entry_) {
entry_->Close();
}
}
void DiskEntryOpener::EnsureEntryIsOpen(base::OnceClosure callback) { void DiskEntryOpener::EnsureEntryIsOpen(base::OnceClosure callback) {
DCHECK(!ensure_entry_is_opened_callback_);
ensure_entry_is_opened_callback_ = std::move(callback);
int rv;
ServiceWorkerDiskCacheEntry** entry_ptr = nullptr;
if (entry_) { if (entry_) {
rv = net::OK; std::move(callback).Run();
} else if (!disk_cache_) { return;
rv = net::ERR_FAILED;
} else {
entry_ptr = new ServiceWorkerDiskCacheEntry*;
rv = disk_cache_->OpenEntry(
resource_id_, entry_ptr,
base::BindOnce(&DiskEntryOpener::DidOpenEntry,
weak_factory_.GetWeakPtr(), entry_ptr));
}
if (rv != net::ERR_IO_PENDING) {
DidOpenEntry(weak_factory_.GetWeakPtr(), entry_ptr, rv);
} }
}
// static if (!disk_cache_) {
void DiskEntryOpener::DidOpenEntry(base::WeakPtr<DiskEntryOpener> entry_opener, std::move(callback).Run();
ServiceWorkerDiskCacheEntry** entry,
int rv) {
if (!entry_opener) {
delete entry;
return; return;
} }
if (!entry_opener->entry_ && rv == net::OK) { disk_cache_->OpenEntry(
resource_id_,
base::BindOnce(&DiskEntryOpener::DidOpenEntry, weak_factory_.GetWeakPtr(),
std::move(callback)));
}
void DiskEntryOpener::DidOpenEntry(
base::OnceClosure callback,
int rv,
std::unique_ptr<ServiceWorkerDiskCacheEntry> entry) {
if (!entry_ && rv == net::OK) {
DCHECK(entry); DCHECK(entry);
entry_opener->entry_ = *entry; entry_ = std::move(entry);
} }
delete entry;
DCHECK(entry_opener->ensure_entry_is_opened_callback_); std::move(callback).Run();
std::move(entry_opener->ensure_entry_is_opened_callback_).Run();
} }
class ServiceWorkerResourceReaderImpl::DataReader { class ServiceWorkerResourceReaderImpl::DataReader {
......
...@@ -26,7 +26,7 @@ class DiskEntryCreator { ...@@ -26,7 +26,7 @@ class DiskEntryCreator {
// Can be nullptr when a disk cache error occurs. // Can be nullptr when a disk cache error occurs.
ServiceWorkerDiskCacheEntry* entry() { ServiceWorkerDiskCacheEntry* entry() {
DCHECK_EQ(creation_phase_, CreationPhase::kDone); DCHECK_EQ(creation_phase_, CreationPhase::kDone);
return entry_; return entry_.get();
} }
// Calls the callback when entry() is created and can be used. // Calls the callback when entry() is created and can be used.
...@@ -52,27 +52,20 @@ class DiskEntryCreator { ...@@ -52,27 +52,20 @@ class DiskEntryCreator {
kDone, kDone,
}; };
// Callbacks of EnsureEntryIsCreated(). These are static to manage the // Callbacks of EnsureEntryIsCreated().
// ownership of ServiceWorkerDiskCacheEntry correctly. void DidCreateEntryForFirstAttempt(
// TODO(crbug.com/586174): Refactor service worker's disk cache to use int rv,
// disk_cache::EntryResult to make these callbacks non-static. std::unique_ptr<ServiceWorkerDiskCacheEntry> entry);
static void DidCreateEntryForFirstAttempt( void DidDoomExistingEntry(int rv);
base::WeakPtr<DiskEntryCreator> entry_creator, void DidCreateEntryForSecondAttempt(
ServiceWorkerDiskCacheEntry** entry, int rv,
int rv); std::unique_ptr<ServiceWorkerDiskCacheEntry> entry);
static void DidDoomExistingEntry(
base::WeakPtr<DiskEntryCreator> entry_creator,
int rv);
static void DidCreateEntryForSecondAttempt(
base::WeakPtr<DiskEntryCreator> entry_creator,
ServiceWorkerDiskCacheEntry** entry,
int rv);
void RunEnsureEntryIsCreatedCallback(); void RunEnsureEntryIsCreatedCallback();
const int64_t resource_id_; const int64_t resource_id_;
base::WeakPtr<ServiceWorkerDiskCache> disk_cache_; base::WeakPtr<ServiceWorkerDiskCache> disk_cache_;
ServiceWorkerDiskCacheEntry* entry_ = nullptr; std::unique_ptr<ServiceWorkerDiskCacheEntry> entry_;
CreationPhase creation_phase_ = CreationPhase::kNoAttempt; CreationPhase creation_phase_ = CreationPhase::kNoAttempt;
...@@ -93,7 +86,7 @@ class DiskEntryOpener { ...@@ -93,7 +86,7 @@ class DiskEntryOpener {
DiskEntryOpener& operator=(const DiskEntryOpener&) = delete; DiskEntryOpener& operator=(const DiskEntryOpener&) = delete;
// Can be nullptr when a disk cache error occurs. // Can be nullptr when a disk cache error occurs.
ServiceWorkerDiskCacheEntry* entry() { return entry_; } ServiceWorkerDiskCacheEntry* entry() { return entry_.get(); }
// Calls the callback when entry() is opened and can be used. // Calls the callback when entry() is opened and can be used.
// //
...@@ -103,18 +96,13 @@ class DiskEntryOpener { ...@@ -103,18 +96,13 @@ class DiskEntryOpener {
void EnsureEntryIsOpen(base::OnceClosure callback); void EnsureEntryIsOpen(base::OnceClosure callback);
private: private:
// TODO(crbug.com/586174): Refactor service worker's disk cache to use void DidOpenEntry(base::OnceClosure callback,
// disk_cache::EntryResult to make this callback non-static. int rv,
static void DidOpenEntry(base::WeakPtr<DiskEntryOpener> entry_creator, std::unique_ptr<ServiceWorkerDiskCacheEntry> entry);
ServiceWorkerDiskCacheEntry** entry,
int rv);
const int64_t resource_id_; const int64_t resource_id_;
base::WeakPtr<ServiceWorkerDiskCache> disk_cache_; base::WeakPtr<ServiceWorkerDiskCache> disk_cache_;
ServiceWorkerDiskCacheEntry* entry_ = nullptr; std::unique_ptr<ServiceWorkerDiskCacheEntry> entry_;
// Stored as a data member to handle //net-style maybe-async methods.
base::OnceClosure ensure_entry_is_opened_callback_;
base::WeakPtrFactory<DiskEntryOpener> weak_factory_{this}; base::WeakPtrFactory<DiskEntryOpener> weak_factory_{this};
}; };
......
...@@ -1449,11 +1449,9 @@ void ServiceWorkerStorage::ContinuePurgingResources() { ...@@ -1449,11 +1449,9 @@ void ServiceWorkerStorage::ContinuePurgingResources() {
void ServiceWorkerStorage::PurgeResource(int64_t id) { void ServiceWorkerStorage::PurgeResource(int64_t id) {
DCHECK(is_purge_pending_); DCHECK(is_purge_pending_);
int rv = disk_cache()->DoomEntry( disk_cache()->DoomEntry(
id, base::BindOnce(&ServiceWorkerStorage::OnResourcePurged, id, base::BindOnce(&ServiceWorkerStorage::OnResourcePurged,
weak_factory_.GetWeakPtr(), id)); weak_factory_.GetWeakPtr(), id));
if (rv != net::ERR_IO_PENDING)
OnResourcePurged(id, rv);
} }
void ServiceWorkerStorage::OnResourcePurged(int64_t id, int rv) { void ServiceWorkerStorage::OnResourcePurged(int64_t id, int rv) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment