summaryrefslogtreecommitdiffstats
path: root/webkit/support/simple_database_system.cc
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-01 20:40:35 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-01 20:40:35 +0000
commit1d4dbdeaa23f3459fb710c8b2fe4d444266d952a (patch)
tree94064bd57faaba18d1ee7a9fe514628f58a6be55 /webkit/support/simple_database_system.cc
parent228d0659a51d0581c743b5b81921d43c7fd81e35 (diff)
downloadchromium_src-1d4dbdeaa23f3459fb710c8b2fe4d444266d952a.zip
chromium_src-1d4dbdeaa23f3459fb710c8b2fe4d444266d952a.tar.gz
chromium_src-1d4dbdeaa23f3459fb710c8b2fe4d444266d952a.tar.bz2
Changes to WebDatabaseObserverImpl and SimpleDatabaseSystem required to have a chance of working properly with v8 isolates. With isolates the database related interfaces will be called on multiple threads and the previous impl was not put together with that in mind.
BUG=none TEST=existing tests pass (no way to test with isolates yet) Review URL: http://codereview.chromium.org/6677088 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80218 0039d316-1c4b-4281-b951-d872f2087c98
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();
}
+