diff options
author | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-22 20:41:20 +0000 |
---|---|---|
committer | dumi@chromium.org <dumi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-22 20:41:20 +0000 |
commit | da34ae09d568bf23b586b49f9ee13d730a3d71c9 (patch) | |
tree | 51177ece300917952d5a1d3c1a32ece5fe70aa0e /webkit/database | |
parent | 35eea2e6ac7a392b22efe089c7c2675be4142237 (diff) | |
download | chromium_src-da34ae09d568bf23b586b49f9ee13d730a3d71c9.zip chromium_src-da34ae09d568bf23b586b49f9ee13d730a3d71c9.tar.gz chromium_src-da34ae09d568bf23b586b49f9ee13d730a3d71c9.tar.bz2 |
Refactor the DB code to make it accessible from test_shell.
BUG=21442
TEST=none
Review URL: http://codereview.chromium.org/203074
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26855 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/database')
-rw-r--r-- | webkit/database/vfs_backend.cc | 210 | ||||
-rw-r--r-- | webkit/database/vfs_backend.h | 33 |
2 files changed, 243 insertions, 0 deletions
diff --git a/webkit/database/vfs_backend.cc b/webkit/database/vfs_backend.cc new file mode 100644 index 0000000..cc06215 --- /dev/null +++ b/webkit/database/vfs_backend.cc @@ -0,0 +1,210 @@ +// Copyright (c) 2009 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 "webkit/database/vfs_backend.h" + +#if defined(USE_SYSTEM_SQLITE) +#include <sqlite3.h> +#else +#include "third_party/sqlite/preprocessed/sqlite3.h" +#endif + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/process.h" + +namespace webkit_database { + +bool VfsBackend::OpenFileFlagsAreConsistent( + const FilePath& file_name, const FilePath& db_dir, int desired_flags) { + // Is this a request for a temp file? + // We should be able to delete temp files when they're closed + // and create them as needed + if ((file_name == db_dir) && + (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) || + !(desired_flags & SQLITE_OPEN_CREATE))) { + return false; + } + + const int file_type = desired_flags & 0x00007F00; + const bool is_exclusive = (desired_flags & SQLITE_OPEN_EXCLUSIVE) != 0; + const bool is_delete = (desired_flags & SQLITE_OPEN_DELETEONCLOSE) != 0; + const bool is_create = (desired_flags & SQLITE_OPEN_CREATE) != 0; + const bool is_read_only = (desired_flags & SQLITE_OPEN_READONLY) != 0; + const bool is_read_write = (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; +} + +void VfsBackend::OpenFile( + const FilePath& file_name, const FilePath& db_dir, int desired_flags, + base::ProcessHandle handle, base::PlatformFile* target_handle, + base::PlatformFile* target_dir_handle) { + // Verify the flags for consistency and create the database + // directory if it doesn't exist. + if (OpenFileFlagsAreConsistent(file_name, db_dir, desired_flags) && + file_util::CreateDirectory(db_dir)) { + int flags = 0; + flags |= base::PLATFORM_FILE_READ; + if (desired_flags & SQLITE_OPEN_READWRITE) { + flags |= base::PLATFORM_FILE_WRITE; + } + + if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) { + flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_EXCLUSIVE_WRITE; + } + + if (desired_flags & SQLITE_OPEN_CREATE) { + flags |= base::PLATFORM_FILE_OPEN_ALWAYS; + } else { + flags |= base::PLATFORM_FILE_OPEN; + } + + if (desired_flags & SQLITE_OPEN_EXCLUSIVE) { + flags |= base::PLATFORM_FILE_EXCLUSIVE_READ | + base::PLATFORM_FILE_EXCLUSIVE_WRITE; + } + + if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) { + flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN | + base::PLATFORM_FILE_DELETE_ON_CLOSE; + } + + // If this is a request for a handle to a temp file, get a unique file name + FilePath db_file_name; + if (file_name == db_dir) { + if (!file_util::CreateTemporaryFileInDir(db_dir, &db_file_name)) { + db_file_name = FilePath(); + } + } else { + db_file_name = file_name; + } + + // Try to open/create the DB file. + base::PlatformFile file_handle = + (db_file_name.empty() ? base::kInvalidPlatformFileValue : + base::CreatePlatformFile(db_file_name.ToWStringHack(), flags, NULL)); + if (file_handle != base::kInvalidPlatformFileValue) { +#if defined(OS_WIN) + // Duplicate the file handle. + if (!DuplicateHandle(GetCurrentProcess(), file_handle, + handle, target_handle, 0, false, + DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { + // 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 = desired_flags & 0x00007F00; + bool creating_new_file = (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( + 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 + } + } +} + +int VfsBackend::DeleteFile( + const FilePath& file_name, const FilePath& db_dir, bool sync_dir) { + if (!file_util::PathExists(file_name)) { + return SQLITE_OK; + } + if (!file_util::Delete(file_name, false)) { + return SQLITE_IOERR_DELETE; + } + + int error_code = SQLITE_OK; +#if defined(OS_POSIX) + if (sync_dir) { + base::PlatformFile dir_fd = base::CreatePlatformFile( + 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 + return error_code; +} + +uint32 VfsBackend::GetFileAttributes(const FilePath& file_name) { +#if defined(OS_WIN) + uint32 attributes = ::GetFileAttributes(file_name.value().c_str()); +#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 + return attributes; +} + +int64 VfsBackend::GetFileSize(const FilePath& file_name) { + int64 size = 0; + return (file_util::GetFileSize(file_name, &size) ? size : 0); +} + +} // namespace database diff --git a/webkit/database/vfs_backend.h b/webkit/database/vfs_backend.h new file mode 100644 index 0000000..536ffd8 --- /dev/null +++ b/webkit/database/vfs_backend.h @@ -0,0 +1,33 @@ +// Copyright (c) 2009 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. + +#ifndef WEBKIT_DATABASE_VFS_BACKEND_H_ +#define WEBKIT_DATABASE_VFS_BACKEND_H_ + +#include "base/platform_file.h" +#include "base/process.h" + +class FilePath; + +namespace webkit_database { + +class VfsBackend { + public: + static void OpenFile( + const FilePath& file_name, const FilePath& db_dir, int desired_flags, + base::ProcessHandle handle, base::PlatformFile* target_handle, + base::PlatformFile* target_dir_handle); + static int DeleteFile( + const FilePath& file_name, const FilePath& db_dir, bool sync_dir); + static uint32 GetFileAttributes(const FilePath& file_name); + static int64 GetFileSize(const FilePath& file_name); + + private: + static bool OpenFileFlagsAreConsistent( + const FilePath& file_name, const FilePath& db_dir, int desired_flags); +}; + +} // namespace webkit_database + +#endif // WEBKIT_DATABASE_VFS_BACKEND_H_ |