| Index: content/browser/indexed_db/indexed_db_active_blob_registry.cc
|
| diff --git a/content/browser/indexed_db/indexed_db_active_blob_registry.cc b/content/browser/indexed_db/indexed_db_active_blob_registry.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..37474043d7a13f5a3ae118f53d00380b8a2ab3bc
|
| --- /dev/null
|
| +++ b/content/browser/indexed_db/indexed_db_active_blob_registry.cc
|
| @@ -0,0 +1,145 @@
|
| +// Copyright (c) 2013 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.
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/task_runner.h"
|
| +#include "content/browser/indexed_db/indexed_db_active_blob_registry.h"
|
| +#include "content/browser/indexed_db/indexed_db_backing_store.h"
|
| +#include "content/browser/indexed_db/indexed_db_factory.h"
|
| +#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
|
| +
|
| +namespace content {
|
| +
|
| +IndexedDBActiveBlobRegistry::IndexedDBActiveBlobRegistry(
|
| + IndexedDBBackingStore* backing_store)
|
| + : backing_store_(backing_store), weak_factory_(this) {}
|
| +
|
| +IndexedDBActiveBlobRegistry::~IndexedDBActiveBlobRegistry() {
|
| + DCHECK(use_tracker_.empty());
|
| +}
|
| +
|
| +void IndexedDBActiveBlobRegistry::AddBlobRef(int64 database_id,
|
| + int64 blob_key) {
|
| + DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
|
| + DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
|
| + DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
|
| + DCHECK(deleted_dbs_.end() == deleted_dbs_.find(database_id));
|
| + bool need_ref = use_tracker_.empty();
|
| + SingleDBMap& single_db_map = use_tracker_[database_id];
|
| + SingleDBMap::iterator iter = single_db_map.find(blob_key);
|
| + if (iter == single_db_map.end()) {
|
| + single_db_map[blob_key] = false;
|
| + if (need_ref) {
|
| + backing_store_->factory()->ReportOutstandingBlobs(
|
| + backing_store_->origin_url(), true);
|
| + }
|
| + } else {
|
| + DCHECK(!need_ref);
|
| + DCHECK(!iter->second); // You can't add a reference once it's been deleted.
|
| + }
|
| +}
|
| +
|
| +void IndexedDBActiveBlobRegistry::ReleaseBlobRef(int64 database_id,
|
| + int64 blob_key) {
|
| + DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
|
| + DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
|
| + DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
|
| + AllDBsMap::iterator db_pair = use_tracker_.find(database_id);
|
| + if (db_pair == use_tracker_.end()) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + SingleDBMap& single_db = db_pair->second;
|
| + SingleDBMap::iterator blob_pair = single_db.find(blob_key);
|
| + if (blob_pair == single_db.end()) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + bool delete_in_backend = false;
|
| + DeletedDBSet::iterator db_to_delete = deleted_dbs_.find(database_id);
|
| + bool db_marked_for_deletion = db_to_delete != deleted_dbs_.end();
|
| + // Don't bother deleting the file if we're going to delete its whole
|
| + // database directory soon.
|
| + delete_in_backend = blob_pair->second && !db_marked_for_deletion;
|
| + single_db.erase(blob_pair);
|
| + if (single_db.empty()) {
|
| + use_tracker_.erase(db_pair);
|
| + if (db_marked_for_deletion) {
|
| + delete_in_backend = true;
|
| + blob_key = DatabaseMetaDataKey::kAllBlobsKey;
|
| + deleted_dbs_.erase(db_to_delete);
|
| + }
|
| + }
|
| + if (delete_in_backend)
|
| + backing_store_->ReportBlobUnused(database_id, blob_key);
|
| + if (use_tracker_.empty()) {
|
| + backing_store_->factory()->ReportOutstandingBlobs(
|
| + backing_store_->origin_url(), false);
|
| + }
|
| +}
|
| +
|
| +bool IndexedDBActiveBlobRegistry::MarkDeletedCheckIfUsed(int64 database_id,
|
| + int64 blob_key) {
|
| + DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
|
| + DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
|
| + AllDBsMap::iterator db_pair = use_tracker_.find(database_id);
|
| + if (db_pair == use_tracker_.end())
|
| + return false;
|
| +
|
| + if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
|
| + deleted_dbs_.insert(database_id);
|
| + return true;
|
| + }
|
| +
|
| + SingleDBMap& single_db = db_pair->second;
|
| + SingleDBMap::iterator iter = single_db.find(blob_key);
|
| + if (iter == single_db.end())
|
| + return false;
|
| +
|
| + iter->second = true;
|
| + return true;
|
| +}
|
| +
|
| +void IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe(
|
| + scoped_refptr<base::TaskRunner> task_runner,
|
| + base::WeakPtr<IndexedDBActiveBlobRegistry> weak_ptr,
|
| + int64 database_id,
|
| + int64 blob_key,
|
| + const base::FilePath& unused) {
|
| + task_runner->PostTask(FROM_HERE,
|
| + base::Bind(&IndexedDBActiveBlobRegistry::ReleaseBlobRef,
|
| + weak_ptr,
|
| + database_id,
|
| + blob_key));
|
| +}
|
| +
|
| +webkit_blob::ShareableFileReference::FinalReleaseCallback
|
| +IndexedDBActiveBlobRegistry::GetFinalReleaseCallback(int64 database_id,
|
| + int64 blob_key) {
|
| + return base::Bind(
|
| + &IndexedDBActiveBlobRegistry::ReleaseBlobRefThreadSafe,
|
| + scoped_refptr<base::TaskRunner>(backing_store_->task_runner()),
|
| + weak_factory_.GetWeakPtr(),
|
| + database_id,
|
| + blob_key);
|
| +}
|
| +
|
| +base::Closure IndexedDBActiveBlobRegistry::GetAddBlobRefCallback(
|
| + int64 database_id,
|
| + int64 blob_key) {
|
| + return base::Bind(&IndexedDBActiveBlobRegistry::AddBlobRef,
|
| + weak_factory_.GetWeakPtr(),
|
| + database_id,
|
| + blob_key);
|
| +}
|
| +
|
| +void IndexedDBActiveBlobRegistry::ForceShutdown() {
|
| + weak_factory_.InvalidateWeakPtrs();
|
| + if (!use_tracker_.empty()) {
|
| + use_tracker_.clear();
|
| + }
|
| +}
|
| +
|
| +} // namespace content
|
|
|