summaryrefslogtreecommitdiffstats
path: root/webkit/support/simple_database_system.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/support/simple_database_system.cc')
-rw-r--r--webkit/support/simple_database_system.cc257
1 files changed, 163 insertions, 94 deletions
diff --git a/webkit/support/simple_database_system.cc b/webkit/support/simple_database_system.cc
index 6c00d6c..62bd03e 100644
--- a/webkit/support/simple_database_system.cc
+++ b/webkit/support/simple_database_system.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -7,6 +7,8 @@
#include "base/auto_reset.h"
#include "base/file_util.h"
#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
+#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/utf_string_conversions.h"
#include "third_party/sqlite/sqlite3.h"
@@ -27,91 +29,138 @@ SimpleDatabaseSystem* SimpleDatabaseSystem::GetInstance() {
}
SimpleDatabaseSystem::SimpleDatabaseSystem()
- : waiting_for_dbs_to_close_(false) {
+ : db_thread_("SimpleDBThread"),
+ open_connections_(new webkit_database::DatabaseConnectionsWrapper) {
+ DCHECK(!instance_);
+ instance_ = this;
CHECK(temp_dir_.CreateUniqueTempDir());
db_tracker_ = new DatabaseTracker(temp_dir_.path(), false, NULL);
db_tracker_->AddObserver(this);
- DCHECK(!instance_);
- instance_ = this;
+ db_thread_.Start();
+ db_thread_proxy_ = db_thread_.message_loop_proxy();
}
SimpleDatabaseSystem::~SimpleDatabaseSystem() {
- db_tracker_->RemoveObserver(this);
+ base::WaitableEvent done_event(false, false);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::ThreadCleanup,
+ &done_event));
+ done_event.Wait();
instance_ = NULL;
}
+void SimpleDatabaseSystem::databaseOpened(const WebKit::WebDatabase& database) {
+ string16 origin_identifier = database.securityOrigin().databaseIdentifier();
+ string16 database_name = database.name();
+ open_connections_->AddOpenConnection(origin_identifier, database_name);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::DatabaseOpened,
+ origin_identifier,
+ database_name, database.displayName(),
+ database.estimatedSize()));
+}
+
+void SimpleDatabaseSystem::databaseModified(
+ const WebKit::WebDatabase& database) {
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::DatabaseModified,
+ database.securityOrigin().databaseIdentifier(),
+ database.name()));
+}
+
+void SimpleDatabaseSystem::databaseClosed(const WebKit::WebDatabase& database) {
+ string16 origin_identifier = database.securityOrigin().databaseIdentifier();
+ string16 database_name = database.name();
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::DatabaseClosed,
+ origin_identifier, database_name));
+}
+
base::PlatformFile SimpleDatabaseSystem::OpenFile(
const string16& vfs_file_name, int desired_flags) {
- base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
- FilePath file_name = GetFullFilePathForVfsFile(vfs_file_name);
- if (file_name.empty()) {
- VfsBackend::OpenTempFileInDirectory(
- db_tracker_->DatabaseDirectory(), desired_flags, &file_handle);
- } else {
- VfsBackend::OpenFile(file_name, desired_flags, &file_handle);
- }
-
- return file_handle;
+ base::PlatformFile result = base::kInvalidPlatformFileValue;
+ base::WaitableEvent done_event(false, false);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::VfsOpenFile,
+ vfs_file_name, desired_flags,
+ &result, &done_event));
+ done_event.Wait();
+ return result;
}
int SimpleDatabaseSystem::DeleteFile(
const string16& vfs_file_name, bool sync_dir) {
- // We try to delete the file multiple times, because that's what the default
- // VFS does (apparently deleting a file can sometimes fail on Windows).
- // We sleep for 10ms between retries for the same reason.
- const int kNumDeleteRetries = 3;
- int num_retries = 0;
- int error_code = SQLITE_OK;
- FilePath file_name = GetFullFilePathForVfsFile(vfs_file_name);
- do {
- error_code = VfsBackend::DeleteFile(file_name, sync_dir);
- } while ((++num_retries < kNumDeleteRetries) &&
- (error_code == SQLITE_IOERR_DELETE) &&
- (base::PlatformThread::Sleep(10), 1));
+ int result = SQLITE_OK;
+ base::WaitableEvent done_event(false, false);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::VfsDeleteFile,
+ vfs_file_name, sync_dir,
+ &result, &done_event));
+ done_event.Wait();
+ return result;
+}
- return error_code;
+uint32 SimpleDatabaseSystem::GetFileAttributes(const string16& vfs_file_name) {
+ uint32 result = 0;
+ base::WaitableEvent done_event(false, false);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::VfsGetFileAttributes,
+ vfs_file_name, &result, &done_event));
+ done_event.Wait();
+ return result;
}
-long SimpleDatabaseSystem::GetFileAttributes(const string16& vfs_file_name) {
- return VfsBackend::GetFileAttributes(
- GetFullFilePathForVfsFile(vfs_file_name));
+int64 SimpleDatabaseSystem::GetFileSize(const string16& vfs_file_name) {
+ int64 result = 0;
+ base::WaitableEvent done_event(false, false);
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::VfsGetFileSize,
+ vfs_file_name, &result, &done_event));
+ done_event.Wait();
+ return result;
+}
+
+void SimpleDatabaseSystem::ClearAllDatabases() {
+ open_connections_->WaitForAllDatabasesToClose();
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::ResetTracker));
}
-long long SimpleDatabaseSystem::GetFileSize(const string16& vfs_file_name) {
- return VfsBackend::GetFileSize(GetFullFilePathForVfsFile(vfs_file_name));
+void SimpleDatabaseSystem::SetDatabaseQuota(int64 quota) {
+ if (!db_thread_proxy_->BelongsToCurrentThread()) {
+ db_thread_proxy_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &SimpleDatabaseSystem::SetDatabaseQuota,
+ quota));
+ return;
+ }
+ db_tracker_->SetDefaultQuota(quota);
}
void SimpleDatabaseSystem::DatabaseOpened(const string16& origin_identifier,
const string16& database_name,
const string16& description,
int64 estimated_size) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
int64 database_size = 0;
int64 space_available = 0;
- database_connections_.AddConnection(origin_identifier, database_name);
- db_tracker_->DatabaseOpened(origin_identifier, database_name, description,
- estimated_size, &database_size, &space_available);
- SetFullFilePathsForVfsFile(origin_identifier, database_name);
-
+ db_tracker_->DatabaseOpened(
+ origin_identifier, database_name, description,
+ estimated_size, &database_size, &space_available);
OnDatabaseSizeChanged(origin_identifier, database_name,
database_size, space_available);
}
void SimpleDatabaseSystem::DatabaseModified(const string16& origin_identifier,
const string16& database_name) {
- DCHECK(database_connections_.IsDatabaseOpened(
- origin_identifier, database_name));
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
db_tracker_->DatabaseModified(origin_identifier, database_name);
}
void SimpleDatabaseSystem::DatabaseClosed(const string16& origin_identifier,
const string16& database_name) {
- DCHECK(database_connections_.IsDatabaseOpened(
- origin_identifier, database_name));
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
db_tracker_->DatabaseClosed(origin_identifier, database_name);
- database_connections_.RemoveConnection(origin_identifier, database_name);
-
- if (waiting_for_dbs_to_close_ && database_connections_.IsEmpty())
- MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ open_connections_->RemoveOpenConnection(origin_identifier, database_name);
}
void SimpleDatabaseSystem::OnDatabaseSizeChanged(
@@ -119,75 +168,95 @@ void SimpleDatabaseSystem::OnDatabaseSizeChanged(
const string16& database_name,
int64 database_size,
int64 space_available) {
- if (database_connections_.IsOriginUsed(origin_identifier)) {
- WebKit::WebDatabase::updateDatabaseSize(
- origin_identifier, database_name, database_size, space_available);
- }
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ // We intentionally call into webkit on our background db_thread_
+ // to better emulate what happens in chrome where this method is
+ // invoked on the background ipc thread.
+ WebKit::WebDatabase::updateDatabaseSize(
+ origin_identifier, database_name, database_size, space_available);
}
void SimpleDatabaseSystem::OnDatabaseScheduledForDeletion(
const string16& origin_identifier,
const string16& database_name) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ // We intentionally call into webkit on our background db_thread_
+ // to better emulate what happens in chrome where this method is
+ // invoked on the background ipc thread.
WebKit::WebDatabase::closeDatabaseImmediately(
origin_identifier, database_name);
}
-void SimpleDatabaseSystem::databaseOpened(const WebKit::WebDatabase& database) {
- DatabaseOpened(database.securityOrigin().databaseIdentifier(),
- database.name(), database.displayName(),
- database.estimatedSize());
-}
-
-void SimpleDatabaseSystem::databaseModified(
- const WebKit::WebDatabase& database) {
- DatabaseModified(database.securityOrigin().databaseIdentifier(),
- database.name());
-}
-
-void SimpleDatabaseSystem::databaseClosed(const WebKit::WebDatabase& database) {
- DatabaseClosed(database.securityOrigin().databaseIdentifier(),
- database.name());
+void SimpleDatabaseSystem::VfsOpenFile(
+ const string16& vfs_file_name, int desired_flags,
+ base::PlatformFile* file_handle, base::WaitableEvent* done_event ) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ FilePath file_name = GetFullFilePathForVfsFile(vfs_file_name);
+ if (file_name.empty()) {
+ VfsBackend::OpenTempFileInDirectory(
+ db_tracker_->DatabaseDirectory(), desired_flags, file_handle);
+ } else {
+ VfsBackend::OpenFile(file_name, desired_flags, file_handle);
+ }
+ done_event->Signal();
}
-void SimpleDatabaseSystem::ClearAllDatabases() {
- // Wait for all databases to be closed.
- if (!database_connections_.IsEmpty()) {
- AutoReset<bool> waiting_for_dbs_auto_reset(
- &waiting_for_dbs_to_close_, true);
- MessageLoop::ScopedNestableTaskAllower nestable(MessageLoop::current());
- MessageLoop::current()->Run();
- }
+void SimpleDatabaseSystem::VfsDeleteFile(
+ const string16& vfs_file_name, bool sync_dir,
+ int* result, base::WaitableEvent* done_event) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ // We try to delete the file multiple times, because that's what the default
+ // VFS does (apparently deleting a file can sometimes fail on Windows).
+ // We sleep for 10ms between retries for the same reason.
+ const int kNumDeleteRetries = 3;
+ int num_retries = 0;
+ *result = SQLITE_OK;
+ FilePath file_name = GetFullFilePathForVfsFile(vfs_file_name);
+ do {
+ *result = VfsBackend::DeleteFile(file_name, sync_dir);
+ } while ((++num_retries < kNumDeleteRetries) &&
+ (*result == SQLITE_IOERR_DELETE) &&
+ (base::PlatformThread::Sleep(10), 1));
- db_tracker_->CloseTrackerDatabaseAndClearCaches();
- file_util::Delete(db_tracker_->DatabaseDirectory(), true);
- file_names_.clear();
+ done_event->Signal();
}
-void SimpleDatabaseSystem::SetDatabaseQuota(int64 quota) {
- db_tracker_->SetDefaultQuota(quota);
+void SimpleDatabaseSystem::VfsGetFileAttributes(
+ const string16& vfs_file_name,
+ uint32* result, base::WaitableEvent* done_event) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ *result = VfsBackend::GetFileAttributes(
+ GetFullFilePathForVfsFile(vfs_file_name));
+ done_event->Signal();
}
-void SimpleDatabaseSystem::SetFullFilePathsForVfsFile(
- const string16& origin_identifier,
- const string16& database_name) {
- string16 vfs_file_name = origin_identifier + ASCIIToUTF16("/") +
- database_name + ASCIIToUTF16("#");
- FilePath file_name =
- DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_, vfs_file_name);
-
- base::AutoLock file_names_auto_lock(file_names_lock_);
- file_names_[vfs_file_name] = file_name;
- DCHECK(file_name.Extension().empty());
- file_names_[vfs_file_name + ASCIIToUTF16("-journal")] =
- file_name.InsertBeforeExtensionASCII("-journal");
+void SimpleDatabaseSystem::VfsGetFileSize(
+ const string16& vfs_file_name,
+ int64* result, base::WaitableEvent* done_event) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ *result = VfsBackend::GetFileSize(GetFullFilePathForVfsFile(vfs_file_name));
+ done_event->Signal();
}
FilePath SimpleDatabaseSystem::GetFullFilePathForVfsFile(
const string16& vfs_file_name) {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
if (vfs_file_name.empty()) // temp file, used for vacuuming
return FilePath();
+ return DatabaseUtil::GetFullFilePathForVfsFile(
+ db_tracker_.get(), vfs_file_name);
+}
+
+void SimpleDatabaseSystem::ResetTracker() {
+ DCHECK(db_thread_proxy_->BelongsToCurrentThread());
+ db_tracker_->CloseTrackerDatabaseAndClearCaches();
+ file_util::Delete(db_tracker_->DatabaseDirectory(), true);
+}
- base::AutoLock file_names_auto_lock(file_names_lock_);
- DCHECK(file_names_.find(vfs_file_name) != file_names_.end());
- return file_names_[vfs_file_name];
+void SimpleDatabaseSystem::ThreadCleanup(base::WaitableEvent* done_event) {
+ ResetTracker();
+ db_tracker_->RemoveObserver(this);
+ db_tracker_ = NULL;
+ done_event->Signal();
}
+