diff options
author | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 21:58:28 +0000 |
---|---|---|
committer | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-28 21:58:28 +0000 |
commit | ee8d4c8656fc8a8723e91e44d05fba4027c77b66 (patch) | |
tree | 7ed5dd75b40690657edd1e41b1aa78a980fd43d2 /chrome/browser | |
parent | 0189bc72c90fab03afab623d0b2d8be3d35af3e7 (diff) | |
download | chromium_src-ee8d4c8656fc8a8723e91e44d05fba4027c77b66.zip chromium_src-ee8d4c8656fc8a8723e91e44d05fba4027c77b66.tar.gz chromium_src-ee8d4c8656fc8a8723e91e44d05fba4027c77b66.tar.bz2 |
Chromium side patch for DB support on Linux.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/174232
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24807 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/renderer_host/database_dispatcher_host.cc | 210 | ||||
-rw-r--r-- | chrome/browser/renderer_host/database_dispatcher_host.h | 2 |
2 files changed, 186 insertions, 26 deletions
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.cc b/chrome/browser/renderer_host/database_dispatcher_host.cc index abf55fb..1dcf93b 100644 --- a/chrome/browser/renderer_host/database_dispatcher_host.cc +++ b/chrome/browser/renderer_host/database_dispatcher_host.cc @@ -27,6 +27,10 @@ #include "chrome/common/render_messages.h" #include "ipc/ipc_message.h" +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + const int kNumDeleteRetries = 5; const int kDelayDeleteRetryMs = 100; @@ -39,6 +43,12 @@ struct OpenFileParams { base::ProcessHandle handle; // the handle of the renderer process }; +struct DeleteFileParams { + FilePath db_dir; // directory where all DB files are stored + FilePath file_name; // DB file + bool sync_dir; // sync DB directory after the file is deleted? +}; + // Scheduled by the file Thread on the IO thread. // Sends back to the renderer process the given message. static void SendMessage(ResourceMessageFilter* sender, @@ -52,6 +62,66 @@ static void SendMessage(ResourceMessageFilter* sender, sender->Release(); } +// Make sure the flags used to open a DB file are consistent. +static bool OpenFileFlagsAreConsistent(const OpenFileParams& params) { + if (params.file_name == params.db_dir) { + return (params.desired_flags == SQLITE_OPEN_READONLY); + } + + const int file_type = params.desired_flags & 0x00007F00; + const bool is_exclusive = + (params.desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; + const bool is_delete = + (params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; + const bool is_create = + (params.desired_flags & SQLITE_OPEN_CREATE) != 0; + const bool is_read_only = + (params.desired_flags & SQLITE_OPEN_READONLY) != 0; + const bool is_read_write = + (params.desired_flags & SQLITE_OPEN_READWRITE) != 0; + + // All files should be opened either read-write or read-only. + if (!(is_read_only ^ is_read_write)) { + return false; + } + + // If a new file is created, it must also be writtable. + if (is_create && !is_read_write) { + return false; + } + + // We must be able to create a new file, if exclusive access is desired. + if (is_exclusive && !is_create) { + return false; + } + + // We cannot delete the files that we expect to already exist. + if (is_delete && !is_create) { + return false; + } + + // The main DB, main journal and master journal cannot be auto-deleted. + if (((file_type == SQLITE_OPEN_MAIN_DB) || + (file_type == SQLITE_OPEN_MAIN_JOURNAL) || + (file_type == SQLITE_OPEN_MASTER_JOURNAL)) && + is_delete) { + return false; + } + + // Make sure we're opening the DB directory or that a file type is set. + if ((file_type != SQLITE_OPEN_MAIN_DB) && + (file_type != SQLITE_OPEN_TEMP_DB) && + (file_type != SQLITE_OPEN_MAIN_JOURNAL) && + (file_type != SQLITE_OPEN_TEMP_JOURNAL) && + (file_type != SQLITE_OPEN_SUBJOURNAL) && + (file_type != SQLITE_OPEN_MASTER_JOURNAL) && + (file_type != SQLITE_OPEN_TRANSIENT_DB)) { + return false; + } + + return true; +} + // Scheduled by the IO thread on the file thread. // Opens the given database file, then schedules // a task on the IO thread's message loop to send an IPC back to @@ -61,8 +131,14 @@ static void DatabaseOpenFile(MessageLoop* io_thread_message_loop, int32 message_id, ResourceMessageFilter* sender) { base::PlatformFile target_handle = base::kInvalidPlatformFileValue; - // Create the database directory if it doesn't exist. - if (file_util::CreateDirectory(params.db_dir)) { +#if defined(OS_POSIX) + base::PlatformFile target_dir_handle = base::kInvalidPlatformFileValue; +#endif + + // Verify the flags for consistency and create the database + // directory if it doesn't exist. + if (OpenFileFlagsAreConsistent(params) && + file_util::CreateDirectory(params.db_dir)) { int flags = 0; flags |= base::PLATFORM_FILE_READ; if (params.desired_flags & SQLITE_OPEN_READWRITE) { @@ -80,16 +156,21 @@ static void DatabaseOpenFile(MessageLoop* io_thread_message_loop, flags |= base::PLATFORM_FILE_OPEN; } + if (params.desired_flags & SQLITE_OPEN_EXCLUSIVE) { + flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_EXCLUSIVE_WRITE; + } + if (params.desired_flags & SQLITE_OPEN_DELETEONCLOSE) { flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN | base::PLATFORM_FILE_DELETE_ON_CLOSE; } // Try to open/create the DB file. -#if defined(OS_WIN) base::PlatformFile file_handle = - base::CreatePlatformFile(params.file_name.value(), flags, NULL); + base::CreatePlatformFile(params.file_name.ToWStringHack(), flags, NULL); if (file_handle != base::kInvalidPlatformFileValue) { +#if defined(OS_WIN) // Duplicate the file handle. if (!DuplicateHandle(GetCurrentProcess(), file_handle, params.handle, &target_handle, 0, false, @@ -97,13 +178,39 @@ static void DatabaseOpenFile(MessageLoop* io_thread_message_loop, // file_handle is closed whether or not DuplicateHandle succeeds. target_handle = INVALID_HANDLE_VALUE; } - } +#elif defined(OS_POSIX) + target_handle = file_handle; + + int file_type = params.desired_flags & 0x00007F00; + bool creating_new_file = (params.desired_flags & SQLITE_OPEN_CREATE); + if (creating_new_file && ((file_type == SQLITE_OPEN_MASTER_JOURNAL) || + (file_type == SQLITE_OPEN_MAIN_JOURNAL))) { + // We return a handle to the containing directory because on POSIX + // systems the VFS might want to fsync it after changing a file. + // By returning it here, we avoid an extra IPC call. + target_dir_handle = base::CreatePlatformFile( + params.db_dir.ToWStringHack(), + base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL); + if (target_dir_handle == base::kInvalidPlatformFileValue) { + base::ClosePlatformFile(target_handle); + target_handle = base::kInvalidPlatformFileValue; + } + } #endif + } } - io_thread_message_loop->PostTask(FROM_HERE, - NewRunnableFunction(SendMessage, sender, - new ViewMsg_DatabaseOpenFileResponse(message_id, target_handle))); + ViewMsg_DatabaseOpenFileResponse_Params response_params = +#if defined(OS_WIN) + { target_handle }; +#elif defined(OS_POSIX) + { base::FileDescriptor(target_handle, true), + base::FileDescriptor(target_dir_handle, true) }; +#endif + + io_thread_message_loop->PostTask(FROM_HERE, + NewRunnableFunction(SendMessage, sender, + new ViewMsg_DatabaseOpenFileResponse(message_id, response_params))); } // Scheduled by the IO thread on the file thread. @@ -112,22 +219,59 @@ static void DatabaseOpenFile(MessageLoop* io_thread_message_loop, // corresponding renderer process with the error code. static void DatabaseDeleteFile( MessageLoop* io_thread_message_loop, - const FilePath& file_name, + const DeleteFileParams& params, int32 message_id, int reschedule_count, ResourceMessageFilter* sender) { - if (reschedule_count > 0 && file_util::PathExists(file_name) && - !file_util::Delete(file_name, false)) { - MessageLoop::current()->PostDelayedTask(FROM_HERE, - NewRunnableFunction(DatabaseDeleteFile, io_thread_message_loop, - file_name, message_id, reschedule_count - 1, sender), - kDelayDeleteRetryMs); - } else { + // Return an error if the file could not be deleted + // after kNumDeleteRetries times. + if (!reschedule_count) { io_thread_message_loop->PostTask(FROM_HERE, NewRunnableFunction(SendMessage, sender, new ViewMsg_DatabaseDeleteFileResponse( - message_id, reschedule_count > 0))); + message_id, SQLITE_IOERR_DELETE))); + return; + } + + // If the file does not exist, we're done. + if (!file_util::PathExists(params.file_name)) { + io_thread_message_loop->PostTask(FROM_HERE, + NewRunnableFunction(SendMessage, sender, + new ViewMsg_DatabaseDeleteFileResponse(message_id, SQLITE_OK))); + return; + } + + + // If the file could not be deleted, try again. + if (!file_util::Delete(params.file_name, false)) { + MessageLoop::current()->PostDelayedTask(FROM_HERE, + NewRunnableFunction(DatabaseDeleteFile, io_thread_message_loop, + params, message_id, reschedule_count - 1, sender), + kDelayDeleteRetryMs); + return; + } + + // File existed and it was successfully deleted + int error_code = SQLITE_OK; +#if defined(OS_POSIX) + // sync the DB directory if needed + if (params.sync_dir) { + base::PlatformFile dir_fd = base::CreatePlatformFile( + params.db_dir.ToWStringHack(), base::PLATFORM_FILE_READ, NULL); + if (dir_fd == base::kInvalidPlatformFileValue) { + error_code = SQLITE_CANTOPEN; + } else { + if (fsync(dir_fd)) { + error_code = SQLITE_IOERR_DIR_FSYNC; + } + base::ClosePlatformFile(dir_fd); + } } +#endif + + io_thread_message_loop->PostTask(FROM_HERE, + NewRunnableFunction(SendMessage, sender, + new ViewMsg_DatabaseDeleteFileResponse(message_id, error_code))); } // Scheduled by the IO thread on the file thread. @@ -141,8 +285,17 @@ static void DatabaseGetFileAttributes( ResourceMessageFilter* sender) { #if defined(OS_WIN) uint32 attributes = GetFileAttributes(file_name.value().c_str()); -#else - uint32 attributes = -1L; +#elif defined(OS_POSIX) + uint32 attributes = 0; + if (!access(file_name.value().c_str(), R_OK)) { + attributes |= static_cast<uint32>(R_OK); + } + if (!access(file_name.value().c_str(), W_OK)) { + attributes |= static_cast<uint32>(W_OK); + } + if (!attributes) { + attributes = -1; + } #endif io_thread_message_loop->PostTask(FROM_HERE, @@ -232,16 +385,22 @@ FilePath DatabaseDispatcherHost::GetDBFileFullPath(const FilePath& file_name) { void DatabaseDispatcherHost::OnDatabaseOpenFile( const FilePath& file_name, int desired_flags, int32 message_id) { - FilePath db_dir = GetDBDir(); FilePath db_file_name = GetDBFileFullPath(file_name); if (db_file_name.empty()) { + ViewMsg_DatabaseOpenFileResponse_Params response_params = +#if defined(OS_WIN) + { base::kInvalidPlatformFileValue }; +#elif defined(OS_POSIX) + { base::FileDescriptor(base::kInvalidPlatformFileValue, true), + base::FileDescriptor(base::kInvalidPlatformFileValue, true) }; +#endif resource_message_filter_->Send(new ViewMsg_DatabaseOpenFileResponse( - message_id, base::kInvalidPlatformFileValue)); + message_id, response_params)); return; } - OpenFileParams params = { db_dir, db_file_name, desired_flags, + OpenFileParams params = { GetDBDir(), db_file_name, desired_flags, resource_message_filter_->handle() }; resource_message_filter_->AddRef(); file_thread_message_loop_->PostTask(FROM_HERE, @@ -250,18 +409,19 @@ void DatabaseDispatcherHost::OnDatabaseOpenFile( } void DatabaseDispatcherHost::OnDatabaseDeleteFile( - const FilePath& file_name, int32 message_id) { + const FilePath& file_name, const bool& sync_dir, int32 message_id) { FilePath db_file_name = GetDBFileFullPath(file_name); if (db_file_name.empty()) { resource_message_filter_->Send(new ViewMsg_DatabaseDeleteFileResponse( - message_id, false)); + message_id, SQLITE_IOERR_DELETE)); return; } + DeleteFileParams params = { GetDBDir(), db_file_name, sync_dir }; resource_message_filter_->AddRef(); file_thread_message_loop_->PostTask(FROM_HERE, NewRunnableFunction(DatabaseDeleteFile, MessageLoop::current(), - db_file_name, message_id, kNumDeleteRetries, resource_message_filter_)); + params, message_id, kNumDeleteRetries, resource_message_filter_)); } void DatabaseDispatcherHost::OnDatabaseGetFileAttributes( diff --git a/chrome/browser/renderer_host/database_dispatcher_host.h b/chrome/browser/renderer_host/database_dispatcher_host.h index 90dc00d..3f5302d 100644 --- a/chrome/browser/renderer_host/database_dispatcher_host.h +++ b/chrome/browser/renderer_host/database_dispatcher_host.h @@ -28,7 +28,7 @@ class DatabaseDispatcherHost { void OnDatabaseOpenFile(const FilePath& file_name, int desired_flags, int32 message_id); // Processes the request to delete the given DB file. - void OnDatabaseDeleteFile(const FilePath& file_name, + void OnDatabaseDeleteFile(const FilePath& file_name, const bool& sync_dir, int32 message_id); // Processes the request to return the attributes of the given DB file. void OnDatabaseGetFileAttributes(const FilePath& file_name, |