blob: b65b24725af2a149d8f839578758ec1bc5f3bbde [file] [log] [blame]
// Copyright 2014 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/stl_util.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() {
}
void IndexedDBActiveBlobRegistry::AddBlobRef(int64 database_id,
int64 blob_key) {
DCHECK(backing_store_);
DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
DCHECK(!ContainsKey(deleted_dbs_, 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_);
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_);
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();
use_tracker_.clear();
backing_store_ = NULL;
}
} // namespace content