diff options
-rw-r--r-- | third_party/leveldatabase/env_chromium.cc | 500 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium.h | 66 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium_stdio.cc | 380 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium_stdio.h | 73 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium_unittest.cc | 40 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium_win.cc | 362 | ||||
-rw-r--r-- | third_party/leveldatabase/env_chromium_win.h | 79 | ||||
-rw-r--r-- | third_party/leveldatabase/leveldatabase.gyp | 8 |
8 files changed, 480 insertions, 1028 deletions
diff --git a/third_party/leveldatabase/env_chromium.cc b/third_party/leveldatabase/env_chromium.cc index 17927cd..3857be1 100644 --- a/third_party/leveldatabase/env_chromium.cc +++ b/third_party/leveldatabase/env_chromium.cc @@ -2,19 +2,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. See the AUTHORS file for names of contributors. +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include <deque> + +#include "base/at_exit.h" #include "base/debug/trace_event.h" #include "base/file_util.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" #include "base/lazy_instance.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" +#include "base/platform_file.h" +#include "base/posix/eintr_wrapper.h" #include "base/strings/utf_string_conversions.h" -#include "env_chromium_stdio.h" +#include "base/synchronization/lock.h" +#include "base/sys_info.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread.h" +#include "chromium_logger.h" +#include "env_chromium.h" +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "port/port.h" #include "third_party/re2/re2/re2.h" +#include "util/logging.h" #if defined(OS_WIN) #include <io.h> -#include "base/command_line.h" #include "base/win/win_util.h" -#include "env_chromium_win.h" +#endif + +#if defined(OS_POSIX) +#include <dirent.h> +#include <fcntl.h> +#include <sys/resource.h> +#include <sys/time.h> #endif using namespace leveldb; @@ -27,9 +54,163 @@ const base::FilePath::CharType backup_table_extension[] = FILE_PATH_LITERAL(".bak"); const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); +#if (defined(OS_POSIX) && !defined(OS_LINUX)) || defined(OS_WIN) +// The following are glibc-specific + +size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) { + return fread(ptr, size, n, file); +} + +size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *file) { + return fwrite(ptr, size, n, file); +} + +int fflush_unlocked(FILE *file) { + return fflush(file); +} + +#if !defined(OS_ANDROID) +int fdatasync(int fildes) { +#if defined(OS_WIN) + return _commit(fildes); +#else + return HANDLE_EINTR(fsync(fildes)); +#endif +} +#endif + +#endif + +// Wide-char safe fopen wrapper. +FILE* fopen_internal(const char* fname, const char* mode) { +#if defined(OS_WIN) + return _wfopen(base::UTF8ToUTF16(fname).c_str(), + base::ASCIIToUTF16(mode).c_str()); +#else + return fopen(fname, mode); +#endif +} + +base::FilePath CreateFilePath(const std::string& file_path) { +#if defined(OS_WIN) + return base::FilePath(base::UTF8ToUTF16(file_path)); +#else + return base::FilePath(file_path); +#endif +} + static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] = FILE_PATH_LITERAL("leveldb-test-"); +const char* PlatformFileErrorString(const ::base::PlatformFileError& error) { + switch (error) { + case ::base::PLATFORM_FILE_ERROR_FAILED: + return "No further details."; + case ::base::PLATFORM_FILE_ERROR_IN_USE: + return "File currently in use."; + case ::base::PLATFORM_FILE_ERROR_EXISTS: + return "File already exists."; + case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: + return "File not found."; + case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: + return "Access denied."; + case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: + return "Too many files open."; + case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: + return "Out of memory."; + case ::base::PLATFORM_FILE_ERROR_NO_SPACE: + return "No space left on drive."; + case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: + return "Not a directory."; + case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: + return "Invalid operation."; + case ::base::PLATFORM_FILE_ERROR_SECURITY: + return "Security error."; + case ::base::PLATFORM_FILE_ERROR_ABORT: + return "File operation aborted."; + case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: + return "The supplied path was not a file."; + case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: + return "The file was not empty."; + case ::base::PLATFORM_FILE_ERROR_INVALID_URL: + return "Invalid URL."; + case ::base::PLATFORM_FILE_ERROR_IO: + return "OS or hardware error."; + case ::base::PLATFORM_FILE_OK: + return "OK."; + case ::base::PLATFORM_FILE_ERROR_MAX: + NOTREACHED(); + } + NOTIMPLEMENTED(); + return "Unknown error."; +} + +class ChromiumSequentialFile: public SequentialFile { + private: + std::string filename_; + FILE* file_; + const UMALogger* uma_logger_; + + public: + ChromiumSequentialFile(const std::string& fname, FILE* f, + const UMALogger* uma_logger) + : filename_(fname), file_(f), uma_logger_(uma_logger) { } + virtual ~ChromiumSequentialFile() { fclose(file_); } + + virtual Status Read(size_t n, Slice* result, char* scratch) { + Status s; + size_t r = fread_unlocked(scratch, 1, n, file_); + *result = Slice(scratch, r); + if (r < n) { + if (feof(file_)) { + // We leave status as ok if we hit the end of the file + } else { + // A partial read with an error: return a non-ok status + s = MakeIOError(filename_, strerror(errno), kSequentialFileRead, errno); + uma_logger_->RecordErrorAt(kSequentialFileRead); + } + } + return s; + } + + virtual Status Skip(uint64_t n) { + if (fseek(file_, n, SEEK_CUR)) { + int saved_errno = errno; + uma_logger_->RecordErrorAt(kSequentialFileSkip); + return MakeIOError( + filename_, strerror(saved_errno), kSequentialFileSkip, saved_errno); + } + return Status::OK(); + } +}; + +class ChromiumRandomAccessFile: public RandomAccessFile { + private: + std::string filename_; + ::base::PlatformFile file_; + const UMALogger* uma_logger_; + + public: + ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file, + const UMALogger* uma_logger) + : filename_(fname), file_(file), uma_logger_(uma_logger) { } + virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const { + Status s; + int r = ::base::ReadPlatformFile(file_, offset, scratch, n); + *result = Slice(scratch, (r < 0) ? 0 : r); + if (r < 0) { + // An error: return a non-ok status + s = MakeIOError( + filename_, "Could not perform read", kRandomAccessFileRead); + uma_logger_->RecordErrorAt(kRandomAccessFileRead); + } + return s; + } +}; + class ChromiumFileLock : public FileLock { public: ::base::PlatformFile file_; @@ -80,33 +261,17 @@ class Retrier { RetrierProvider* provider_; }; -class IDBEnvStdio : public ChromiumEnvStdio { +class IDBEnv : public ChromiumEnv { public: - IDBEnvStdio() : ChromiumEnvStdio() { + IDBEnv() : ChromiumEnv() { name_ = "LevelDBEnv.IDB"; make_backup_ = true; } }; -#if defined(OS_WIN) -class IDBEnvWin : public ChromiumEnvWin { - public: - IDBEnvWin() : ChromiumEnvWin() { - name_ = "LevelDBEnv.IDB"; - make_backup_ = true; - } -}; -#endif +::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; -#if defined(OS_WIN) -::base::LazyInstance<IDBEnvWin>::Leaky idb_env = - LAZY_INSTANCE_INITIALIZER; -#else -::base::LazyInstance<IDBEnvStdio>::Leaky idb_env = - LAZY_INSTANCE_INITIALIZER; -#endif - -::base::LazyInstance<ChromiumEnvStdio>::Leaky default_env = +::base::LazyInstance<ChromiumEnv>::Leaky default_env = LAZY_INSTANCE_INITIALIZER; } // unnamed namespace @@ -329,24 +494,122 @@ std::string FilePathToString(const base::FilePath& file_path) { #endif } -base::FilePath ChromiumEnv::CreateFilePath(const std::string& file_path) { -#if defined(OS_WIN) - return base::FilePath(base::UTF8ToUTF16(file_path)); -#else - return base::FilePath(file_path); +ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, + FILE* f, + const UMALogger* uma_logger, + WriteTracker* tracker, + bool make_backup) + : filename_(fname), + file_(f), + uma_logger_(uma_logger), + tracker_(tracker), + file_type_(kOther), + make_backup_(make_backup) { + base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); + if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) + file_type_ = kManifest; + else if (path.MatchesExtension(table_extension)) + file_type_ = kTable; + if (file_type_ != kManifest) + tracker_->DidCreateNewFile(filename_); + parent_dir_ = FilePathToString(CreateFilePath(fname).DirName()); +} + +ChromiumWritableFile::~ChromiumWritableFile() { + if (file_ != NULL) { + // Ignoring any potential errors + fclose(file_); + } +} + +Status ChromiumWritableFile::SyncParent() { + Status s; +#if !defined(OS_WIN) + TRACE_EVENT0("leveldb", "SyncParent"); + + int parent_fd = + HANDLE_EINTR(open(parent_dir_.c_str(), O_RDONLY)); + if (parent_fd < 0) { + int saved_errno = errno; + return MakeIOError( + parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); + } + if (HANDLE_EINTR(fsync(parent_fd)) != 0) { + int saved_errno = errno; + s = MakeIOError( + parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); + }; + close(parent_fd); #endif + return s; +} + +Status ChromiumWritableFile::Append(const Slice& data) { + if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { + Status s = SyncParent(); + if (!s.ok()) + return s; + tracker_->DidSyncDir(filename_); + } + + size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); + if (r != data.size()) { + int saved_errno = errno; + uma_logger_->RecordOSError(kWritableFileAppend, saved_errno); + return MakeIOError( + filename_, strerror(saved_errno), kWritableFileAppend, saved_errno); + } + return Status::OK(); +} + +Status ChromiumWritableFile::Close() { + Status result; + if (fclose(file_) != 0) { + result = MakeIOError(filename_, strerror(errno), kWritableFileClose, errno); + uma_logger_->RecordErrorAt(kWritableFileClose); + } + file_ = NULL; + return result; +} + +Status ChromiumWritableFile::Flush() { + Status result; + if (HANDLE_EINTR(fflush_unlocked(file_))) { + int saved_errno = errno; + result = MakeIOError( + filename_, strerror(saved_errno), kWritableFileFlush, saved_errno); + uma_logger_->RecordOSError(kWritableFileFlush, saved_errno); + } + return result; } -bool ChromiumEnv::MakeBackup(const std::string& fname) { +static bool MakeBackup(const std::string& fname) { base::FilePath original_table_name = CreateFilePath(fname); base::FilePath backup_table_name = original_table_name.ReplaceExtension(backup_table_extension); return base::CopyFile(original_table_name, backup_table_name); } -bool ChromiumEnv::HasTableExtension(const base::FilePath& path) -{ - return path.MatchesExtension(table_extension); +Status ChromiumWritableFile::Sync() { + TRACE_EVENT0("leveldb", "ChromiumEnv::Sync"); + Status result; + int error = 0; + + if (HANDLE_EINTR(fflush_unlocked(file_))) + error = errno; + // Sync even if fflush gave an error; perhaps the data actually got out, + // even though something went wrong. + if (fdatasync(fileno(file_)) && !error) + error = errno; + // Report the first error we found. + if (error) { + result = MakeIOError(filename_, strerror(error), kWritableFileSync, error); + uma_logger_->RecordErrorAt(kWritableFileSync); + } else if (make_backup_ && file_type_ == kTable) { + bool success = MakeBackup(filename_); + uma_logger_->RecordBackupResult(success); + } + return result; } ChromiumEnv::ChromiumEnv() @@ -363,51 +626,71 @@ ChromiumEnv::~ChromiumEnv() { // a unit test that is deleted. } -bool ChromiumEnv::FileExists(const std::string& fname) { - return ::base::PathExists(CreateFilePath(fname)); +Status ChromiumEnv::NewSequentialFile(const std::string& fname, + SequentialFile** result) { + FILE* f = fopen_internal(fname.c_str(), "rb"); + if (f == NULL) { + *result = NULL; + int saved_errno = errno; + RecordOSError(kNewSequentialFile, saved_errno); + return MakeIOError( + fname, strerror(saved_errno), kNewSequentialFile, saved_errno); + } else { + *result = new ChromiumSequentialFile(fname, f, this); + return Status::OK(); + } } -const char* ChromiumEnv::PlatformFileErrorString(const ::base::PlatformFileError& error) { - switch (error) { - case ::base::PLATFORM_FILE_ERROR_FAILED: - return "No further details."; - case ::base::PLATFORM_FILE_ERROR_IN_USE: - return "File currently in use."; - case ::base::PLATFORM_FILE_ERROR_EXISTS: - return "File already exists."; - case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: - return "File not found."; - case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: - return "Access denied."; - case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: - return "Too many files open."; - case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: - return "Out of memory."; - case ::base::PLATFORM_FILE_ERROR_NO_SPACE: - return "No space left on drive."; - case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: - return "Not a directory."; - case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: - return "Invalid operation."; - case ::base::PLATFORM_FILE_ERROR_SECURITY: - return "Security error."; - case ::base::PLATFORM_FILE_ERROR_ABORT: - return "File operation aborted."; - case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: - return "The supplied path was not a file."; - case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: - return "The file was not empty."; - case ::base::PLATFORM_FILE_ERROR_INVALID_URL: - return "Invalid URL."; - case ::base::PLATFORM_FILE_ERROR_IO: - return "OS or hardware error."; - case ::base::PLATFORM_FILE_OK: - return "OK."; - case ::base::PLATFORM_FILE_ERROR_MAX: - NOTREACHED(); +void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) { +#if defined(OS_POSIX) + struct rlimit nofile; + if (getrlimit(RLIMIT_NOFILE, &nofile)) + return; + GetMaxFDHistogram(type)->Add(nofile.rlim_cur); +#endif +} + +Status ChromiumEnv::NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) { + int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; + bool created; + ::base::PlatformFileError error_code; + ::base::PlatformFile file = ::base::CreatePlatformFile( + CreateFilePath(fname), flags, &created, &error_code); + if (error_code == ::base::PLATFORM_FILE_OK) { + *result = new ChromiumRandomAccessFile(fname, file, this); + RecordOpenFilesLimit("Success"); + return Status::OK(); } - NOTIMPLEMENTED(); - return "Unknown error."; + if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED) + RecordOpenFilesLimit("TooManyOpened"); + else + RecordOpenFilesLimit("OtherError"); + *result = NULL; + RecordOSError(kNewRandomAccessFile, error_code); + return MakeIOError(fname, + PlatformFileErrorString(error_code), + kNewRandomAccessFile, + error_code); +} + +Status ChromiumEnv::NewWritableFile(const std::string& fname, + WritableFile** result) { + *result = NULL; + FILE* f = fopen_internal(fname.c_str(), "wb"); + if (f == NULL) { + int saved_errno = errno; + RecordErrorAt(kNewWritableFile); + return MakeIOError( + fname, strerror(saved_errno), kNewWritableFile, saved_errno); + } else { + *result = new ChromiumWritableFile(fname, f, this, this, make_backup_); + return Status::OK(); + } +} + +bool ChromiumEnv::FileExists(const std::string& fname) { + return ::base::PathExists(CreateFilePath(fname)); } base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { @@ -463,6 +746,62 @@ void ChromiumEnv::RestoreIfNecessary(const std::string& dir, } } +namespace { +#if defined(OS_WIN) +static base::PlatformFileError GetDirectoryEntries( + const base::FilePath& dir_param, + std::vector<base::FilePath>* result) { + result->clear(); + base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*")); + WIN32_FIND_DATA find_data; + HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data); + if (find_handle == INVALID_HANDLE_VALUE) { + DWORD last_error = GetLastError(); + if (last_error == ERROR_FILE_NOT_FOUND) + return base::PLATFORM_FILE_OK; + return base::LastErrorToPlatformFileError(last_error); + } + do { + base::FilePath filepath(find_data.cFileName); + base::FilePath::StringType basename = filepath.BaseName().value(); + if (basename == FILE_PATH_LITERAL(".") || + basename == FILE_PATH_LITERAL("..")) + continue; + result->push_back(filepath.BaseName()); + } while (FindNextFile(find_handle, &find_data)); + DWORD last_error = GetLastError(); + base::PlatformFileError return_value = base::PLATFORM_FILE_OK; + if (last_error != ERROR_NO_MORE_FILES) + return_value = base::LastErrorToPlatformFileError(last_error); + FindClose(find_handle); + return return_value; +} +#else +static base::PlatformFileError GetDirectoryEntries( + const base::FilePath& dir_filepath, + std::vector<base::FilePath>* result) { + const std::string dir_string = FilePathToString(dir_filepath); + result->clear(); + DIR* dir = opendir(dir_string.c_str()); + if (!dir) + return base::ErrnoToPlatformFileError(errno); + struct dirent dent_buf; + struct dirent* dent; + int readdir_result; + while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) { + if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) + continue; + result->push_back(CreateFilePath(dent->d_name)); + } + int saved_errno = errno; + closedir(dir); + if (readdir_result != 0) + return base::ErrnoToPlatformFileError(saved_errno); + return base::PLATFORM_FILE_OK; +} +#endif +} + Status ChromiumEnv::GetChildren(const std::string& dir_string, std::vector<std::string>* result) { std::vector<base::FilePath> entries; @@ -670,6 +1009,19 @@ Status ChromiumEnv::GetTestDirectory(std::string* path) { return Status::OK(); } +Status ChromiumEnv::NewLogger(const std::string& fname, Logger** result) { + FILE* f = fopen_internal(fname.c_str(), "w"); + if (f == NULL) { + *result = NULL; + int saved_errno = errno; + RecordOSError(kNewLogger, saved_errno); + return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); + } else { + *result = new ChromiumLogger(f); + return Status::OK(); + } +} + uint64_t ChromiumEnv::NowMicros() { return ::base::TimeTicks::Now().ToInternalValue(); } diff --git a/third_party/leveldatabase/env_chromium.h b/third_party/leveldatabase/env_chromium.h index 916cb7d..d6f9c24 100644 --- a/third_party/leveldatabase/env_chromium.h +++ b/third_party/leveldatabase/env_chromium.h @@ -11,7 +11,10 @@ #include "base/metrics/histogram.h" #include "base/platform_file.h" +#include "base/synchronization/condition_variable.h" #include "leveldb/env.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" #include "port/port_chromium.h" #include "util/mutexlock.h" @@ -98,18 +101,51 @@ class WriteTracker { virtual void DidSyncDir(const std::string& fname) = 0; }; +class ChromiumWritableFile : public leveldb::WritableFile { + public: + ChromiumWritableFile(const std::string& fname, + FILE* f, + const UMALogger* uma_logger, + WriteTracker* tracker, + bool make_backup); + virtual ~ChromiumWritableFile(); + virtual leveldb::Status Append(const leveldb::Slice& data); + virtual leveldb::Status Close(); + virtual leveldb::Status Flush(); + virtual leveldb::Status Sync(); + + private: + enum Type { + kManifest, + kTable, + kOther + }; + leveldb::Status SyncParent(); + + std::string filename_; + FILE* file_; + const UMALogger* uma_logger_; + WriteTracker* tracker_; + Type file_type_; + std::string parent_dir_; + bool make_backup_; +}; + class ChromiumEnv : public leveldb::Env, public UMALogger, public RetrierProvider, public WriteTracker { public: - static bool MakeBackup(const std::string& fname); - static base::FilePath CreateFilePath(const std::string& file_path); - static const char* PlatformFileErrorString( - const ::base::PlatformFileError& error); - static bool HasTableExtension(const base::FilePath& path); + ChromiumEnv(); virtual ~ChromiumEnv(); + virtual leveldb::Status NewSequentialFile(const std::string& fname, + leveldb::SequentialFile** result); + virtual leveldb::Status NewRandomAccessFile( + const std::string& fname, + leveldb::RandomAccessFile** result); + virtual leveldb::Status NewWritableFile(const std::string& fname, + leveldb::WritableFile** result); virtual bool FileExists(const std::string& fname); virtual leveldb::Status GetChildren(const std::string& dir, std::vector<std::string>* result); @@ -125,24 +161,15 @@ class ChromiumEnv : public leveldb::Env, virtual void Schedule(void (*function)(void*), void* arg); virtual void StartThread(void (*function)(void* arg), void* arg); virtual leveldb::Status GetTestDirectory(std::string* path); + virtual leveldb::Status NewLogger(const std::string& fname, + leveldb::Logger** result); virtual uint64_t NowMicros(); virtual void SleepForMicroseconds(int micros); protected: - ChromiumEnv(); - virtual void DidCreateNewFile(const std::string& fname); virtual bool DoesDirNeedSync(const std::string& fname); virtual void DidSyncDir(const std::string& fname); - virtual base::PlatformFileError GetDirectoryEntries( - const base::FilePath& dir_param, - std::vector<base::FilePath>* result) const = 0; - virtual void RecordErrorAt(MethodID method) const; - virtual void RecordOSError(MethodID method, int saved_errno) const; - virtual void RecordOSError(MethodID method, - base::PlatformFileError error) const; - base::HistogramBase* GetMaxFDHistogram(const std::string& type) const; - base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const; std::string name_; bool make_backup_; @@ -175,12 +202,19 @@ class ChromiumEnv : public leveldb::Env, reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); } + virtual void RecordErrorAt(MethodID method) const; + virtual void RecordOSError(MethodID method, int saved_errno) const; + virtual void RecordOSError(MethodID method, + base::PlatformFileError error) const; virtual void RecordBackupResult(bool result) const; void RestoreIfNecessary(const std::string& dir, std::vector<std::string>* children); base::FilePath RestoreFromBackup(const base::FilePath& base_name); + void RecordOpenFilesLimit(const std::string& type); void RecordLockFileAncestors(int num_missing_ancestors) const; + base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const; base::HistogramBase* GetMethodIOErrorHistogram() const; + base::HistogramBase* GetMaxFDHistogram(const std::string& type) const; base::HistogramBase* GetLockFileAncestorHistogram() const; // RetrierProvider implementation. diff --git a/third_party/leveldatabase/env_chromium_stdio.cc b/third_party/leveldatabase/env_chromium_stdio.cc deleted file mode 100644 index 9b1a57f..0000000 --- a/third_party/leveldatabase/env_chromium_stdio.cc +++ /dev/null @@ -1,380 +0,0 @@ -// Copyright (c) 2011-2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include <errno.h> - -#include "base/debug/trace_event.h" -#include "base/metrics/histogram.h" -#include "base/posix/eintr_wrapper.h" -#include "base/strings/utf_string_conversions.h" -#include "chromium_logger.h" -#include "env_chromium_stdio.h" - -#if defined(OS_WIN) -#include <io.h> -#include "base/win/win_util.h" -#endif - -#if defined(OS_POSIX) -#include <dirent.h> -#include <fcntl.h> -#include <sys/resource.h> -#endif - -using namespace leveldb; - -namespace leveldb_env { - -namespace { - -#if (defined(OS_POSIX) && !defined(OS_LINUX)) || defined(OS_WIN) -// The following are glibc-specific - -size_t fread_unlocked(void* ptr, size_t size, size_t n, FILE* file) { - return fread(ptr, size, n, file); -} - -size_t fwrite_unlocked(const void* ptr, size_t size, size_t n, FILE* file) { - return fwrite(ptr, size, n, file); -} - -int fflush_unlocked(FILE* file) { return fflush(file); } - -#if !defined(OS_ANDROID) -int fdatasync(int fildes) { -#if defined(OS_WIN) - return _commit(fildes); -#else - return HANDLE_EINTR(fsync(fildes)); -#endif -} -#endif - -#endif - -// Wide-char safe fopen wrapper. -FILE* fopen_internal(const char* fname, const char* mode) { -#if defined(OS_WIN) - return _wfopen(base::UTF8ToUTF16(fname).c_str(), - base::ASCIIToUTF16(mode).c_str()); -#else - return fopen(fname, mode); -#endif -} - -class ChromiumSequentialFile : public SequentialFile { - private: - std::string filename_; - FILE* file_; - const UMALogger* uma_logger_; - - public: - ChromiumSequentialFile(const std::string& fname, - FILE* f, - const UMALogger* uma_logger) - : filename_(fname), file_(f), uma_logger_(uma_logger) {} - virtual ~ChromiumSequentialFile() { fclose(file_); } - - virtual Status Read(size_t n, Slice* result, char* scratch) { - Status s; - size_t r = fread_unlocked(scratch, 1, n, file_); - *result = Slice(scratch, r); - if (r < n) { - if (feof(file_)) { - // We leave status as ok if we hit the end of the file - } else { - // A partial read with an error: return a non-ok status - s = MakeIOError(filename_, strerror(errno), kSequentialFileRead, errno); - uma_logger_->RecordErrorAt(kSequentialFileRead); - } - } - return s; - } - - virtual Status Skip(uint64_t n) { - if (fseek(file_, n, SEEK_CUR)) { - int saved_errno = errno; - uma_logger_->RecordErrorAt(kSequentialFileSkip); - return MakeIOError( - filename_, strerror(saved_errno), kSequentialFileSkip, saved_errno); - } - return Status::OK(); - } -}; - -class ChromiumRandomAccessFile : public RandomAccessFile { - private: - std::string filename_; - ::base::PlatformFile file_; - const UMALogger* uma_logger_; - - public: - ChromiumRandomAccessFile(const std::string& fname, - ::base::PlatformFile file, - const UMALogger* uma_logger) - : filename_(fname), file_(file), uma_logger_(uma_logger) {} - virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) - const { - Status s; - int r = ::base::ReadPlatformFile(file_, offset, scratch, n); - *result = Slice(scratch, (r < 0) ? 0 : r); - if (r < 0) { - // An error: return a non-ok status - s = MakeIOError( - filename_, "Could not perform read", kRandomAccessFileRead); - uma_logger_->RecordErrorAt(kRandomAccessFileRead); - } - return s; - } -}; - -} // unnamed namespace - -ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, - FILE* f, - const UMALogger* uma_logger, - WriteTracker* tracker, - bool make_backup) - : filename_(fname), - file_(f), - uma_logger_(uma_logger), - tracker_(tracker), - file_type_(kOther), - make_backup_(make_backup) { - base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); - if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) - file_type_ = kManifest; - else if (ChromiumEnv::HasTableExtension(path)) - file_type_ = kTable; - if (file_type_ != kManifest) - tracker_->DidCreateNewFile(filename_); - parent_dir_ = FilePathToString(ChromiumEnv::CreateFilePath(fname).DirName()); -} - -ChromiumWritableFile::~ChromiumWritableFile() { - if (file_ != NULL) { - // Ignoring any potential errors - fclose(file_); - } -} - -Status ChromiumWritableFile::SyncParent() { - Status s; -#if !defined(OS_WIN) - TRACE_EVENT0("leveldb", "SyncParent"); - - int parent_fd = HANDLE_EINTR(open(parent_dir_.c_str(), O_RDONLY)); - if (parent_fd < 0) { - int saved_errno = errno; - return MakeIOError( - parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); - } - if (HANDLE_EINTR(fsync(parent_fd)) != 0) { - int saved_errno = errno; - s = MakeIOError( - parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); - }; - close(parent_fd); -#endif - return s; -} - -Status ChromiumWritableFile::Append(const Slice& data) { - if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { - Status s = SyncParent(); - if (!s.ok()) - return s; - tracker_->DidSyncDir(filename_); - } - - size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); - if (r != data.size()) { - int saved_errno = errno; - uma_logger_->RecordOSError(kWritableFileAppend, saved_errno); - return MakeIOError( - filename_, strerror(saved_errno), kWritableFileAppend, saved_errno); - } - return Status::OK(); -} - -Status ChromiumWritableFile::Close() { - Status result; - if (fclose(file_) != 0) { - result = MakeIOError(filename_, strerror(errno), kWritableFileClose, errno); - uma_logger_->RecordErrorAt(kWritableFileClose); - } - file_ = NULL; - return result; -} - -Status ChromiumWritableFile::Flush() { - Status result; - if (HANDLE_EINTR(fflush_unlocked(file_))) { - int saved_errno = errno; - result = MakeIOError( - filename_, strerror(saved_errno), kWritableFileFlush, saved_errno); - uma_logger_->RecordOSError(kWritableFileFlush, saved_errno); - } - return result; -} - -Status ChromiumWritableFile::Sync() { - TRACE_EVENT0("leveldb", "ChromiumEnvStdio::Sync"); - Status result; - int error = 0; - - if (HANDLE_EINTR(fflush_unlocked(file_))) - error = errno; - // Sync even if fflush gave an error; perhaps the data actually got out, - // even though something went wrong. - if (fdatasync(fileno(file_)) && !error) - error = errno; - // Report the first error we found. - if (error) { - result = MakeIOError(filename_, strerror(error), kWritableFileSync, error); - uma_logger_->RecordErrorAt(kWritableFileSync); - } else if (make_backup_ && file_type_ == kTable) { - bool success = ChromiumEnv::MakeBackup(filename_); - uma_logger_->RecordBackupResult(success); - } - return result; -} - -ChromiumEnvStdio::ChromiumEnvStdio() {} - -ChromiumEnvStdio::~ChromiumEnvStdio() {} - -Status ChromiumEnvStdio::NewSequentialFile(const std::string& fname, - SequentialFile** result) { - FILE* f = fopen_internal(fname.c_str(), "rb"); - if (f == NULL) { - *result = NULL; - int saved_errno = errno; - RecordOSError(kNewSequentialFile, saved_errno); - return MakeIOError( - fname, strerror(saved_errno), kNewSequentialFile, saved_errno); - } else { - *result = new ChromiumSequentialFile(fname, f, this); - return Status::OK(); - } -} - -void ChromiumEnvStdio::RecordOpenFilesLimit(const std::string& type) { -#if defined(OS_POSIX) - struct rlimit nofile; - if (getrlimit(RLIMIT_NOFILE, &nofile)) - return; - GetMaxFDHistogram(type)->Add(nofile.rlim_cur); -#endif -} - -Status ChromiumEnvStdio::NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result) { - int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; - bool created; - ::base::PlatformFileError error_code; - ::base::PlatformFile file = ::base::CreatePlatformFile( - ChromiumEnv::CreateFilePath(fname), flags, &created, &error_code); - if (error_code == ::base::PLATFORM_FILE_OK) { - *result = new ChromiumRandomAccessFile(fname, file, this); - RecordOpenFilesLimit("Success"); - return Status::OK(); - } - if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED) - RecordOpenFilesLimit("TooManyOpened"); - else - RecordOpenFilesLimit("OtherError"); - *result = NULL; - RecordOSError(kNewRandomAccessFile, error_code); - return MakeIOError(fname, - PlatformFileErrorString(error_code), - kNewRandomAccessFile, - error_code); -} - -Status ChromiumEnvStdio::NewWritableFile(const std::string& fname, - WritableFile** result) { - *result = NULL; - FILE* f = fopen_internal(fname.c_str(), "wb"); - if (f == NULL) { - int saved_errno = errno; - RecordErrorAt(kNewWritableFile); - return MakeIOError( - fname, strerror(saved_errno), kNewWritableFile, saved_errno); - } else { - *result = new ChromiumWritableFile(fname, f, this, this, make_backup_); - return Status::OK(); - } -} - -#if defined(OS_WIN) -base::PlatformFileError ChromiumEnvStdio::GetDirectoryEntries( - const base::FilePath& dir_param, - std::vector<base::FilePath>* result) const { - result->clear(); - base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*")); - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data); - if (find_handle == INVALID_HANDLE_VALUE) { - DWORD last_error = GetLastError(); - if (last_error == ERROR_FILE_NOT_FOUND) - return base::PLATFORM_FILE_OK; - return base::LastErrorToPlatformFileError(last_error); - } - do { - base::FilePath filepath(find_data.cFileName); - base::FilePath::StringType basename = filepath.BaseName().value(); - if (basename == FILE_PATH_LITERAL(".") || - basename == FILE_PATH_LITERAL("..")) - continue; - result->push_back(filepath.BaseName()); - } while (FindNextFile(find_handle, &find_data)); - DWORD last_error = GetLastError(); - base::PlatformFileError return_value = base::PLATFORM_FILE_OK; - if (last_error != ERROR_NO_MORE_FILES) - return_value = base::LastErrorToPlatformFileError(last_error); - FindClose(find_handle); - return return_value; -} -#else -base::PlatformFileError ChromiumEnvStdio::GetDirectoryEntries( - const base::FilePath& dir_filepath, - std::vector<base::FilePath>* result) const { - const std::string dir_string = FilePathToString(dir_filepath); - result->clear(); - DIR* dir = opendir(dir_string.c_str()); - if (!dir) - return base::ErrnoToPlatformFileError(errno); - struct dirent dent_buf; - struct dirent* dent; - int readdir_result; - while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) { - if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) - continue; - result->push_back(ChromiumEnv::CreateFilePath(dent->d_name)); - } - int saved_errno = errno; - closedir(dir); - if (readdir_result != 0) - return base::ErrnoToPlatformFileError(saved_errno); - return base::PLATFORM_FILE_OK; -} -#endif - -Status ChromiumEnvStdio::NewLogger(const std::string& fname, Logger** result) { - FILE* f = fopen_internal(fname.c_str(), "w"); - if (f == NULL) { - *result = NULL; - int saved_errno = errno; - RecordOSError(kNewLogger, saved_errno); - return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); - } else { - *result = new ChromiumLogger(f); - return Status::OK(); - } -} - -} // namespace leveldb_env diff --git a/third_party/leveldatabase/env_chromium_stdio.h b/third_party/leveldatabase/env_chromium_stdio.h deleted file mode 100644 index e60a1b8..0000000 --- a/third_party/leveldatabase/env_chromium_stdio.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_STDIO_H_ -#define THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_STDIO_H_ - -#include "env_chromium.h" - -namespace leveldb_env { - -class ChromiumWritableFile : public leveldb::WritableFile { - public: - ChromiumWritableFile(const std::string& fname, - FILE* f, - const UMALogger* uma_logger, - WriteTracker* tracker, - bool make_backup); - virtual ~ChromiumWritableFile(); - virtual leveldb::Status Append(const leveldb::Slice& data); - virtual leveldb::Status Close(); - virtual leveldb::Status Flush(); - virtual leveldb::Status Sync(); - - private: - enum Type { - kManifest, - kTable, - kOther - }; - leveldb::Status SyncParent(); - - std::string filename_; - FILE* file_; - const UMALogger* uma_logger_; - WriteTracker* tracker_; - Type file_type_; - std::string parent_dir_; - bool make_backup_; -}; - -class ChromiumEnvStdio : public ChromiumEnv { - public: - ChromiumEnvStdio(); - virtual ~ChromiumEnvStdio(); - - virtual leveldb::Status NewSequentialFile(const std::string& fname, - leveldb::SequentialFile** result); - virtual leveldb::Status NewRandomAccessFile( - const std::string& fname, - leveldb::RandomAccessFile** result); - virtual leveldb::Status NewWritableFile(const std::string& fname, - leveldb::WritableFile** result); - virtual leveldb::Status NewLogger(const std::string& fname, - leveldb::Logger** result); - - protected: - virtual base::PlatformFileError GetDirectoryEntries( - const base::FilePath& dir_param, - std::vector<base::FilePath>* result) const; - - private: - // BGThread() is the body of the background thread - void BGThread(); - static void BGThreadWrapper(void* arg) { - reinterpret_cast<ChromiumEnvStdio*>(arg)->BGThread(); - } - void RecordOpenFilesLimit(const std::string& type); -}; - -} // namespace leveldb_env - -#endif diff --git a/third_party/leveldatabase/env_chromium_unittest.cc b/third_party/leveldatabase/env_chromium_unittest.cc index d15a445..05669f1 100644 --- a/third_party/leveldatabase/env_chromium_unittest.cc +++ b/third_party/leveldatabase/env_chromium_unittest.cc @@ -7,10 +7,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/test/test_suite.h" -#include "env_chromium_stdio.h" -#if defined(OS_WIN) -#include "env_chromium_win.h" -#endif +#include "env_chromium.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/leveldatabase/env_idb.h" #include "third_party/leveldatabase/src/include/leveldb/db.h" @@ -57,21 +54,6 @@ TEST(ErrorEncoding, Errno) { EXPECT_EQ(some_errno, error); } -#if defined(OS_WIN) -TEST(ErrorEncoding, ErrnoWin32) { - const MethodID in_method = kWritableFileFlush; - const DWORD some_errno = ERROR_FILE_NOT_FOUND; - const Status s = - MakeIOErrorWin("Somefile.txt", "message", in_method, some_errno); - MethodID method; - int error; - EXPECT_EQ(METHOD_AND_ERRNO, - ParseMethodAndError(s.ToString().c_str(), &method, &error)); - EXPECT_EQ(in_method, method); - EXPECT_EQ(some_errno, error); -} -#endif - TEST(ErrorEncoding, NoEncodedMessage) { Status s = Status::IOError("Some message", "from leveldb itself"); MethodID method = kRandomAccessFileRead; @@ -81,8 +63,7 @@ TEST(ErrorEncoding, NoEncodedMessage) { EXPECT_EQ(4, error); } -template <typename T> -class MyEnv : public T { +class MyEnv : public ChromiumEnv { public: MyEnv() : directory_syncs_(0) {} int directory_syncs() { return directory_syncs_; } @@ -97,21 +78,8 @@ class MyEnv : public T { int directory_syncs_; }; -template <typename T> -class ChromiumEnvMultiPlatformTests : public ::testing::Test { - public: -}; - -#if defined(OS_WIN) -typedef ::testing::Types<ChromiumEnvStdio, ChromiumEnvWin> ChromiumEnvMultiPlatformTestsTypes; -#else -typedef ::testing::Types<ChromiumEnvStdio> ChromiumEnvMultiPlatformTestsTypes; -#endif -TYPED_TEST_CASE(ChromiumEnvMultiPlatformTests, ChromiumEnvMultiPlatformTestsTypes); - -TYPED_TEST(ChromiumEnvMultiPlatformTests, DirectorySyncing) { - MyEnv<TypeParam> env; - +TEST(ChromiumEnv, DirectorySyncing) { + MyEnv env; base::ScopedTempDir dir; dir.CreateUniqueTempDir(); base::FilePath dir_path = dir.path(); diff --git a/third_party/leveldatabase/env_chromium_win.cc b/third_party/leveldatabase/env_chromium_win.cc deleted file mode 100644 index 29bc874..0000000 --- a/third_party/leveldatabase/env_chromium_win.cc +++ /dev/null @@ -1,362 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#include "base/debug/trace_event.h" -#include "base/files/file_path.h" -#include "base/strings/utf_string_conversions.h" -#include "base/win/win_util.h" -#include "chromium_logger.h" -#include "env_chromium_stdio.h" -#include "env_chromium_win.h" - -using namespace leveldb; - -namespace leveldb_env { - -namespace { - -static std::string GetWindowsErrorMessage(DWORD err) { - LPTSTR errorText(NULL); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - err, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) & errorText, - 0, - NULL); - if (errorText != NULL) { - std::string message(base::UTF16ToUTF8(errorText)); - // FormatMessage adds CR/LF to messages so we remove it. - TrimWhitespace(message, TRIM_TRAILING, &message); - LocalFree(errorText); - return message; - } else { - return std::string(); - } -} - -class ChromiumSequentialFileWin : public SequentialFile { - private: - std::string filename_; - HANDLE file_; - const UMALogger* uma_logger_; - - public: - ChromiumSequentialFileWin(const std::string& fname, - HANDLE f, - const UMALogger* uma_logger) - : filename_(fname), file_(f), uma_logger_(uma_logger) { - DCHECK(file_ != INVALID_HANDLE_VALUE); - } - virtual ~ChromiumSequentialFileWin() { - DCHECK(file_ != INVALID_HANDLE_VALUE); - CloseHandle(file_); - file_ = INVALID_HANDLE_VALUE; - } - - virtual Status Read(size_t n, Slice* result, char* scratch) { - Status s; - DWORD bytes_read(0); - DCHECK(file_ != INVALID_HANDLE_VALUE); - if (ReadFile(file_, scratch, n, &bytes_read, NULL)) { - *result = Slice(scratch, bytes_read); - } else { - DWORD err = GetLastError(); - s = MakeIOErrorWin( - filename_, GetWindowsErrorMessage(err), kSequentialFileRead, err); - uma_logger_->RecordErrorAt(kSequentialFileRead); - if (bytes_read > 0) - *result = Slice(scratch, bytes_read); - } - return s; - } - - virtual Status Skip(uint64_t n) { - LARGE_INTEGER li; - li.QuadPart = n; - if (SetFilePointer(file_, li.LowPart, &li.HighPart, FILE_CURRENT) == - INVALID_SET_FILE_POINTER) { - DWORD err = GetLastError(); - uma_logger_->RecordErrorAt(kSequentialFileSkip); - return MakeIOErrorWin( - filename_, GetWindowsErrorMessage(err), kSequentialFileSkip, err); - } - return Status::OK(); - } -}; - -class ChromiumRandomAccessFileWin : public RandomAccessFile { - private: - std::string filename_; - ::base::PlatformFile file_; - const UMALogger* uma_logger_; - - public: - ChromiumRandomAccessFileWin(const std::string& fname, - ::base::PlatformFile file, - const UMALogger* uma_logger) - : filename_(fname), file_(file), uma_logger_(uma_logger) {} - virtual ~ChromiumRandomAccessFileWin() { ::base::ClosePlatformFile(file_); } - - virtual Status Read(uint64_t offset, size_t n, Slice* result, char* scratch) - const { - Status s; - int r = ::base::ReadPlatformFile(file_, offset, scratch, n); - *result = Slice(scratch, (r < 0) ? 0 : r); - if (r < 0) { - // An error: return a non-ok status - s = MakeIOError( - filename_, "Could not perform read", kRandomAccessFileRead); - uma_logger_->RecordErrorAt(kRandomAccessFileRead); - } - return s; - } -}; - -} // unnamed namespace - -Status MakeIOErrorWin(Slice filename, - const std::string& message, - MethodID method, - DWORD error) { - char buf[512]; - if (snprintf(buf, - sizeof(buf), - "%s (ChromeMethodErrno: %d::%s::%u)", - message.c_str(), - method, - MethodIDToString(method), - error) >= 0) { - return Status::IOError(filename, buf); - } else { - return Status::IOError(filename, "<unknown>"); - } -} - -ChromiumWritableFileWin::ChromiumWritableFileWin( - const std::string& fname, - HANDLE f, - const UMALogger* uma_logger, - WriteTracker* tracker, - bool make_backup) - : filename_(fname), - file_(f), - uma_logger_(uma_logger), - tracker_(tracker), - file_type_(kOther), - make_backup_(make_backup) { - DCHECK(f != INVALID_HANDLE_VALUE); - base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); - if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) - file_type_ = kManifest; - else if (ChromiumEnv::HasTableExtension(path)) - file_type_ = kTable; - if (file_type_ != kManifest) - tracker_->DidCreateNewFile(filename_); - parent_dir_ = FilePathToString(ChromiumEnv::CreateFilePath(fname).DirName()); -} - -ChromiumWritableFileWin::~ChromiumWritableFileWin() { - if (file_ != INVALID_HANDLE_VALUE) { - // Ignoring any potential errors - - CloseHandle(file_); - file_ = INVALID_HANDLE_VALUE; - } -} - -Status ChromiumWritableFileWin::SyncParent() { - // On Windows no need to sync parent directory. It's metadata will be - // updated via the creation of the new file, without an explicit sync. - return Status(); -} - -Status ChromiumWritableFileWin::Append(const Slice& data) { - if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { - Status s = SyncParent(); - if (!s.ok()) - return s; - tracker_->DidSyncDir(filename_); - } - - DWORD written(0); - if (!WriteFile(file_, data.data(), data.size(), &written, NULL)) { - DWORD err = GetLastError(); - uma_logger_->RecordOSError(kWritableFileAppend, - base::LastErrorToPlatformFileError(err)); - return MakeIOErrorWin( - filename_, GetWindowsErrorMessage(err), kWritableFileAppend, err); - } - return Status::OK(); -} - -Status ChromiumWritableFileWin::Close() { - Status result; - DCHECK(file_ != INVALID_HANDLE_VALUE); - if (!CloseHandle(file_)) { - DWORD err = GetLastError(); - result = MakeIOErrorWin( - filename_, GetWindowsErrorMessage(err), kWritableFileClose, err); - uma_logger_->RecordErrorAt(kWritableFileClose); - } - file_ = INVALID_HANDLE_VALUE; - return result; -} - -Status ChromiumWritableFileWin::Flush() { - Status result; - if (!FlushFileBuffers(file_)) { - DWORD err = GetLastError(); - result = MakeIOErrorWin( - filename_, GetWindowsErrorMessage(err), kWritableFileFlush, err); - uma_logger_->RecordOSError(kWritableFileFlush, - base::LastErrorToPlatformFileError(err)); - } - return result; -} - -Status ChromiumWritableFileWin::Sync() { - TRACE_EVENT0("leveldb", "ChromiumEnvWin::Sync"); - Status result; - DWORD error = ERROR_SUCCESS; - - DCHECK(file_ != INVALID_HANDLE_VALUE); - if (!FlushFileBuffers(file_)) - error = GetLastError(); - if (error != ERROR_SUCCESS) { - result = MakeIOErrorWin( - filename_, GetWindowsErrorMessage(error), kWritableFileSync, error); - uma_logger_->RecordErrorAt(kWritableFileSync); - } else if (make_backup_ && file_type_ == kTable) { - bool success = ChromiumEnv::MakeBackup(filename_); - uma_logger_->RecordBackupResult(success); - } - return result; -} - -ChromiumEnvWin::ChromiumEnvWin() {} - -ChromiumEnvWin::~ChromiumEnvWin() {} - -Status ChromiumEnvWin::NewSequentialFile(const std::string& fname, - SequentialFile** result) { - HANDLE f = CreateFile(base::UTF8ToUTF16(fname).c_str(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (f == INVALID_HANDLE_VALUE) { - *result = NULL; - DWORD err = GetLastError(); - RecordOSError(kNewSequentialFile, err); - return MakeIOErrorWin( - fname, GetWindowsErrorMessage(err), kNewSequentialFile, err); - } else { - *result = new ChromiumSequentialFileWin(fname, f, this); - return Status::OK(); - } -} - -void ChromiumEnvWin::RecordOpenFilesLimit(const std::string& type) { - // The Windows POSIX implementation (which this class doesn't use) - // has an open file limit, but when using the Win32 API this is limited by - // available memory, so no value to report. -} - -Status ChromiumEnvWin::NewRandomAccessFile(const std::string& fname, - RandomAccessFile** result) { - int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; - bool created; - ::base::PlatformFileError error_code; - ::base::PlatformFile file = ::base::CreatePlatformFile( - ChromiumEnv::CreateFilePath(fname), flags, &created, &error_code); - if (error_code == ::base::PLATFORM_FILE_OK) { - *result = new ChromiumRandomAccessFileWin(fname, file, this); - RecordOpenFilesLimit("Success"); - return Status::OK(); - } - if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED) - RecordOpenFilesLimit("TooManyOpened"); - else - RecordOpenFilesLimit("OtherError"); - *result = NULL; - RecordOSError(kNewRandomAccessFile, error_code); - return MakeIOErrorWin(fname, - PlatformFileErrorString(error_code), - kNewRandomAccessFile, - error_code); -} - -Status ChromiumEnvWin::NewWritableFile(const std::string& fname, - WritableFile** result) { - *result = NULL; - HANDLE f = CreateFile(base::UTF8ToUTF16(fname).c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (f == INVALID_HANDLE_VALUE) { - DWORD err = GetLastError(); - RecordErrorAt(kNewWritableFile); - return MakeIOErrorWin( - fname, GetWindowsErrorMessage(err), kNewWritableFile, err); - } else { - *result = new ChromiumWritableFileWin(fname, f, this, this, make_backup_); - return Status::OK(); - } -} - -base::PlatformFileError ChromiumEnvWin::GetDirectoryEntries( - const base::FilePath& dir_param, - std::vector<base::FilePath>* result) const { - result->clear(); - base::FilePath dir_filepath = dir_param.Append(FILE_PATH_LITERAL("*")); - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile(dir_filepath.value().c_str(), &find_data); - if (find_handle == INVALID_HANDLE_VALUE) { - DWORD last_error = GetLastError(); - if (last_error == ERROR_FILE_NOT_FOUND) - return base::PLATFORM_FILE_OK; - return base::LastErrorToPlatformFileError(last_error); - } - do { - base::FilePath filepath(find_data.cFileName); - base::FilePath::StringType basename = filepath.BaseName().value(); - if (basename == FILE_PATH_LITERAL(".") || - basename == FILE_PATH_LITERAL("..")) - continue; - result->push_back(filepath.BaseName()); - } while (FindNextFile(find_handle, &find_data)); - DWORD last_error = GetLastError(); - base::PlatformFileError return_value = base::PLATFORM_FILE_OK; - if (last_error != ERROR_NO_MORE_FILES) - return_value = base::LastErrorToPlatformFileError(last_error); - FindClose(find_handle); - return return_value; -} - -Status ChromiumEnvWin::NewLogger(const std::string& fname, Logger** result) { - FILE* f = _wfopen(base::UTF8ToUTF16(fname).c_str(), L"w"); - if (f == NULL) { - *result = NULL; - int saved_errno = errno; - RecordOSError(kNewLogger, saved_errno); - return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); - } else { - *result = new ChromiumLogger(f); - return Status::OK(); - } -} - -void ChromiumEnvWin::RecordOSError(MethodID method, DWORD error) const { - RecordErrorAt(method); - GetOSErrorHistogram(method, ERANGE + 1)->Add(error); -} - -} // namespace leveldb_env diff --git a/third_party/leveldatabase/env_chromium_win.h b/third_party/leveldatabase/env_chromium_win.h deleted file mode 100644 index 0bc35f6..0000000 --- a/third_party/leveldatabase/env_chromium_win.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2013 The LevelDB Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. See the AUTHORS file for names of contributors. - -#ifndef THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_WIN_H_ -#define THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_WIN_H_ - -#include "env_chromium.h" - -namespace leveldb_env { - -leveldb::Status MakeIOErrorWin(leveldb::Slice filename, - const std::string& message, - MethodID method, - DWORD err); - -class ChromiumWritableFileWin : public leveldb::WritableFile { - public: - ChromiumWritableFileWin(const std::string& fname, - HANDLE f, - const UMALogger* uma_logger, - WriteTracker* tracker, - bool make_backup); - virtual ~ChromiumWritableFileWin(); - virtual leveldb::Status Append(const leveldb::Slice& data); - virtual leveldb::Status Close(); - virtual leveldb::Status Flush(); - virtual leveldb::Status Sync(); - - private: - enum Type { - kManifest, - kTable, - kOther - }; - leveldb::Status SyncParent(); - - std::string filename_; - HANDLE file_; - const UMALogger* uma_logger_; - WriteTracker* tracker_; - Type file_type_; - std::string parent_dir_; - bool make_backup_; -}; - -class ChromiumEnvWin : public ChromiumEnv { - public: - ChromiumEnvWin(); - virtual ~ChromiumEnvWin(); - - virtual leveldb::Status NewSequentialFile(const std::string& fname, - leveldb::SequentialFile** result); - virtual leveldb::Status NewRandomAccessFile( - const std::string& fname, - leveldb::RandomAccessFile** result); - virtual leveldb::Status NewWritableFile(const std::string& fname, - leveldb::WritableFile** result); - virtual leveldb::Status NewLogger(const std::string& fname, - leveldb::Logger** result); - - protected: - virtual base::PlatformFileError GetDirectoryEntries( - const base::FilePath& dir_param, - std::vector<base::FilePath>* result) const; - - private: - // BGThread() is the body of the background thread - void BGThread(); - static void BGThreadWrapper(void* arg) { - reinterpret_cast<ChromiumEnvWin*>(arg)->BGThread(); - } - void RecordOpenFilesLimit(const std::string& type); - virtual void RecordOSError(MethodID method, DWORD err) const; -}; - -} // namespace leveldb_env - -#endif diff --git a/third_party/leveldatabase/leveldatabase.gyp b/third_party/leveldatabase/leveldatabase.gyp index 0f46313..f3510f6 100644 --- a/third_party/leveldatabase/leveldatabase.gyp +++ b/third_party/leveldatabase/leveldatabase.gyp @@ -49,12 +49,6 @@ '../../third_party/snappy/snappy.gyp:snappy', ], }], - ['OS=="win"', { - 'sources': [ - 'env_chromium_win.cc', - 'env_chromium_win.h', - ], - }], ], 'direct_dependent_settings': { 'include_dirs': [ @@ -78,8 +72,6 @@ # they don't build. 'env_chromium.cc', 'env_chromium.h', - 'env_chromium_stdio.cc', - 'env_chromium_stdio.h', 'env_idb.h', 'port/port_chromium.cc', 'port/port_chromium.h', |