env_chromium.cc revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The LevelDB Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. See the AUTHORS file for names of contributors. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <deque> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/debug/trace_event.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromium_logger.h" 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "env_chromium.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/env.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/slice.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "port/port.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/re2/re2/re2.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/logging.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h> 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX) 408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <dirent.h> 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h> 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/resource.h> 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/time.h> 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using namespace leveldb; 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace leveldb_env { 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::FilePath::CharType backup_table_extension[] = 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FILE_PATH_LITERAL(".bak"); 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb"); 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if (defined(OS_POSIX) && !defined(OS_LINUX)) || defined(OS_WIN) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following are glibc-specific 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fread(ptr, size, n, file); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *file) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fwrite(ptr, size, n, file); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int fflush_unlocked(FILE *file) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fflush(file); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fdatasync(int fildes) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _commit(fildes); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return HANDLE_EINTR(fsync(fildes)); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wide-char safe fopen wrapper. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* fopen_internal(const char* fname, const char* mode) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return _wfopen(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return fopen(fname, mode); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath CreateFilePath(const std::string& file_path) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(UTF8ToUTF16(file_path)); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(file_path); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[] 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) = FILE_PATH_LITERAL("leveldb-test-"); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* PlatformFileErrorString(const ::base::PlatformFileError& error) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_FAILED: 106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return "No further details."; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_IN_USE: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File currently in use."; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_EXISTS: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File already exists."; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_FOUND: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File not found."; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Access denied."; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Too many files open."; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NO_MEMORY: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Out of memory."; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NO_SPACE: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "No space left on drive."; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Not a directory."; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Invalid operation."; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_SECURITY: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Security error."; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_ABORT: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "File operation aborted."; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "The supplied path was not a file."; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "The file was not empty."; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_INVALID_URL: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Invalid URL."; 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_IO: 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return "OS or hardware error."; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ::base::PLATFORM_FILE_OK: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "OK."; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ::base::PLATFORM_FILE_ERROR_MAX: 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "Unknown error."; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumSequentialFile: public SequentialFile { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE* file_; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const UMALogger* uma_logger_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChromiumSequentialFile(const std::string& fname, FILE* f, 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const UMALogger* uma_logger) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : filename_(fname), file_(f), uma_logger_(uma_logger) { } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChromiumSequentialFile() { fclose(file_); } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Read(size_t n, Slice* result, char* scratch) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status s; 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t r = fread_unlocked(scratch, 1, n, file_); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = Slice(scratch, r); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < n) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (feof(file_)) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We leave status as ok if we hit the end of the file 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A partial read with an error: return a non-ok status 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) s = MakeIOError(filename_, strerror(errno), kSequentialFileRead, errno); 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uma_logger_->RecordErrorAt(kSequentialFileRead); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Skip(uint64_t n) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fseek(file_, n, SEEK_CUR)) { 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int saved_errno = errno; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uma_logger_->RecordErrorAt(kSequentialFileSkip); 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return MakeIOError( 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch filename_, strerror(saved_errno), kSequentialFileSkip, saved_errno); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumRandomAccessFile: public RandomAccessFile { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string filename_; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformFile file_; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const UMALogger* uma_logger_; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file, 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const UMALogger* uma_logger) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : filename_(fname), file_(file), uma_logger_(uma_logger) { } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual Status Read(uint64_t offset, size_t n, Slice* result, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* scratch) const { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Status s; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = ::base::ReadPlatformFile(file_, offset, scratch, n); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = Slice(scratch, (r < 0) ? 0 : r); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An error: return a non-ok status 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) s = MakeIOError( 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) filename_, "Could not perform read", kRandomAccessFileRead); 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uma_logger_->RecordErrorAt(kRandomAccessFileRead); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return s; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ChromiumFileLock : public FileLock { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformFile file_; 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string name_; 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class Retrier { 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Retrier(MethodID method, RetrierProvider* provider) 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : start_(base::TimeTicks::Now()), 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) limit_(start_ + base::TimeDelta::FromMilliseconds( 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) provider->MaxRetryTimeMillis())), 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_(start_), 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) time_to_sleep_(base::TimeDelta::FromMilliseconds(10)), 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) success_(true), 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) method_(method), 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_error_(base::PLATFORM_FILE_OK), 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) provider_(provider) {} 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ~Retrier() { 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (success_) { 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) provider_->GetRetryTimeHistogram(method_)->AddTime(last_ - start_); 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (last_error_ != base::PLATFORM_FILE_OK) { 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(last_error_ < 0); 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) provider_->GetRecoveredFromErrorHistogram(method_)->Add(-last_error_); 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool ShouldKeepTrying(base::PlatformFileError last_error) { 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_NE(last_error, base::PLATFORM_FILE_OK); 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_error_ = last_error; 242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (last_ < limit_) { 243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformThread::Sleep(time_to_sleep_); 244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_ = base::TimeTicks::Now(); 245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) success_ = false; 248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeTicks start_; 253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeTicks limit_; 254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeTicks last_; 255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeDelta time_to_sleep_; 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool success_; 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodID method_; 258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError last_error_; 259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RetrierProvider* provider_; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class IDBEnv : public ChromiumEnv { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IDBEnv() : ChromiumEnv() { 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) name_ = "LevelDBEnv.IDB"; 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) make_backup_ = true; 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)::base::LazyInstance<IDBEnv>::Leaky idb_env = LAZY_INSTANCE_INITIALIZER; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)::base::LazyInstance<ChromiumEnv>::Leaky default_env = 273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // unnamed namespace 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char* MethodIDToString(MethodID method) { 2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) switch (method) { 2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kSequentialFileRead: 2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "SequentialFileRead"; 2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kSequentialFileSkip: 2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "SequentialFileSkip"; 2837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kRandomAccessFileRead: 2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "RandomAccessFileRead"; 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kWritableFileAppend: 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "WritableFileAppend"; 2877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kWritableFileClose: 2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "WritableFileClose"; 2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kWritableFileFlush: 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "WritableFileFlush"; 2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kWritableFileSync: 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "WritableFileSync"; 2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kNewSequentialFile: 2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "NewSequentialFile"; 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kNewRandomAccessFile: 2967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "NewRandomAccessFile"; 2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kNewWritableFile: 2987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "NewWritableFile"; 2997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kDeleteFile: 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "DeleteFile"; 3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kCreateDir: 3027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "CreateDir"; 3037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kDeleteDir: 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "DeleteDir"; 3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kGetFileSize: 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "GetFileSize"; 3077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kRenameFile: 3087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "RenameFile"; 3097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kLockFile: 3107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "LockFile"; 3117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kUnlockFile: 3127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "UnlockFile"; 3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kGetTestDirectory: 3147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "GetTestDirectory"; 3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kNewLogger: 3167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "NewLogger"; 3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kSyncParent: 3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "SyncParent"; 3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) case kGetChildren: 3208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return "GetChildren"; 3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case kNumEntries: 3227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NOTREACHED(); 3237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "kNumEntries"; 3247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) NOTREACHED(); 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return "Unknown"; 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename, 330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const char* message, 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodID method, 332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int saved_errno) { 333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) char buf[512]; 334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snprintf(buf, 335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizeof(buf), 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "%s (ChromeMethodErrno: %d::%s::%d)", 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message, 338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) method, 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodIDToString(method), 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) saved_errno); 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::IOError(filename, buf); 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename, 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const char* message, 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodID method, 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError error) { 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(error < 0); 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) char buf[512]; 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snprintf(buf, 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizeof(buf), 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "%s (ChromeMethodPFE: %d::%s::%d)", 353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message, 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) method, 355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodIDToString(method), 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) -error); 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::IOError(filename, buf); 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename, const char* message, MethodID method) { 361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) char buf[512]; 362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snprintf(buf, 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizeof(buf), 364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "%s (ChromeMethodOnly: %d::%s)", 365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) message, 366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) method, 367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) MethodIDToString(method)); 368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::IOError(filename, buf); 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ErrorParsingResult ParseMethodAndError(const char* string, 3727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) MethodID* method_param, 3737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int* error) { 3747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int method; 3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) { 3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *method_param = static_cast<MethodID>(method); 3777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return METHOD_ONLY; 3787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (RE2::PartialMatch( 3807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) { 381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error = -*error; 3827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *method_param = static_cast<MethodID>(method); 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return METHOD_AND_PFE; 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (RE2::PartialMatch( 3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) string, "ChromeMethodErrno: (\\d+)::.*::(\\d+)", &method, error)) { 3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) *method_param = static_cast<MethodID>(method); 3887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return METHOD_AND_ERRNO; 389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 3907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NONE; 391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool IndicatesDiskFull(leveldb::Status status) { 39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (status.ok()) 39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return false; 39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) leveldb_env::MethodID method; 39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) int error = -1; 39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError( 39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) status.ToString().c_str(), &method, &error); 40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return (result == leveldb_env::METHOD_AND_PFE && 40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) static_cast<base::PlatformFileError>(error) == 40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::PLATFORM_FILE_ERROR_NO_SPACE) || 40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) (result == leveldb_env::METHOD_AND_ERRNO && error == ENOSPC); 40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsIOError(leveldb::Status status) { 4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb_env::MethodID method; 4084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int error = -1; 4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError( 4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) status.ToString().c_str(), &method, &error); 4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result != leveldb_env::NONE; 4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string FilePathToString(const base::FilePath& file_path) { 415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_WIN) 416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return UTF16ToUTF8(file_path.value()); 417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else 418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return file_path.value(); 419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumWritableFile::ChromiumWritableFile(const std::string& fname, 423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE* f, 424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const UMALogger* uma_logger, 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WriteTracker* tracker, 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool make_backup) 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : filename_(fname), 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_(f), 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_logger_(uma_logger), 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tracker_(tracker), 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_type_(kOther), 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) make_backup_(make_backup) { 433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath path = base::FilePath::FromUTF8Unsafe(fname); 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (FilePathToString(path.BaseName()).find("MANIFEST") == 0) 4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_type_ = kManifest; 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else if (path.MatchesExtension(table_extension)) 4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_type_ = kTable; 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (file_type_ != kManifest) 439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) tracker_->DidCreateNewFile(filename_); 440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) parent_dir_ = FilePathToString(CreateFilePath(fname).DirName()); 441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumWritableFile::~ChromiumWritableFile() { 444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (file_ != NULL) { 445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Ignoring any potential errors 446868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fclose(file_); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumWritableFile::SyncParent() { 451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status s; 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if !defined(OS_WIN) 453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TRACE_EVENT0("leveldb", "SyncParent"); 454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int parent_fd = 456868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) HANDLE_EINTR(open(parent_dir_.c_str(), O_RDONLY)); 45758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (parent_fd < 0) { 45858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int saved_errno = errno; 45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return MakeIOError( 46058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); 46158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 462868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HANDLE_EINTR(fsync(parent_fd)) != 0) { 46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int saved_errno = errno; 46458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) s = MakeIOError( 46558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) parent_dir_, strerror(saved_errno), kSyncParent, saved_errno); 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) HANDLE_EINTR(close(parent_fd)); 468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 469868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return s; 470868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 472868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumWritableFile::Append(const Slice& data) { 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (file_type_ == kManifest && tracker_->DoesDirNeedSync(filename_)) { 474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status s = SyncParent(); 475868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!s.ok()) 476868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return s; 477868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) tracker_->DidSyncDir(filename_); 478868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_); 481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (r != data.size()) { 482eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int saved_errno = errno; 483eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch uma_logger_->RecordOSError(kWritableFileAppend, saved_errno); 484eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return MakeIOError( 485eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch filename_, strerror(saved_errno), kWritableFileAppend, saved_errno); 486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 488868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumWritableFile::Close() { 491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (fclose(file_) != 0) { 493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError(filename_, strerror(errno), kWritableFileClose, errno); 494868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uma_logger_->RecordErrorAt(kWritableFileClose); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) file_ = NULL; 497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 500868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumWritableFile::Flush() { 501868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (HANDLE_EINTR(fflush_unlocked(file_))) { 503868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int saved_errno = errno; 504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError( 505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) filename_, strerror(saved_errno), kWritableFileFlush, saved_errno); 506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uma_logger_->RecordOSError(kWritableFileFlush, saved_errno); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 509868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static bool MakeBackup(const std::string& fname) { 5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath original_table_name = CreateFilePath(fname); 5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath backup_table_name = 5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) original_table_name.ReplaceExtension(backup_table_extension); 5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return base::CopyFile(original_table_name, backup_table_name); 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumWritableFile::Sync() { 519868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) TRACE_EVENT0("leveldb", "ChromiumEnv::Sync"); 520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int error = 0; 522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (HANDLE_EINTR(fflush_unlocked(file_))) 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error = errno; 525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Sync even if fflush gave an error; perhaps the data actually got out, 526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // even though something went wrong. 527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (fdatasync(fileno(file_)) && !error) 528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error = errno; 529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Report the first error we found. 530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error) { 531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError(filename_, strerror(error), kWritableFileSync, error); 532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uma_logger_->RecordErrorAt(kWritableFileSync); 5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (make_backup_ && file_type_ == kTable) { 5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool success = MakeBackup(filename_); 5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_logger_->RecordBackupResult(success); 536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumEnv::ChromiumEnv() 541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : name_("LevelDBEnv"), 5424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) make_backup_(false), 543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bgsignal_(&mu_), 544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) started_bgthread_(false), 545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kMaxRetryTimeMillis(1000) { 546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumEnv::~ChromiumEnv() { 549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to 550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // ensure that behavior isn't accidentally changed, but there's an instance in 551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // a unit test that is deleted. 552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::NewSequentialFile(const std::string& fname, 555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SequentialFile** result) { 556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "rb"); 557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (f == NULL) { 558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = NULL; 559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int saved_errno = errno; 560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOSError(kNewSequentialFile, saved_errno); 561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MakeIOError( 562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fname, strerror(saved_errno), kNewSequentialFile, saved_errno); 563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = new ChromiumSequentialFile(fname, f, this); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Status::OK(); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordOpenFilesLimit(const std::string& type) { 570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_POSIX) 571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct rlimit nofile; 572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (getrlimit(RLIMIT_NOFILE, &nofile)) 573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetMaxFDHistogram(type)->Add(nofile.rlim_cur); 575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::NewRandomAccessFile(const std::string& fname, 579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RandomAccessFile** result) { 580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN; 581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool created; 582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformFileError error_code; 583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformFile file = ::base::CreatePlatformFile( 584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CreateFilePath(fname), flags, &created, &error_code); 585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error_code == ::base::PLATFORM_FILE_OK) { 586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = new ChromiumRandomAccessFile(fname, file, this); 587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOpenFilesLimit("Success"); 588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED) 591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOpenFilesLimit("TooManyOpened"); 592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else 593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOpenFilesLimit("OtherError"); 594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = NULL; 595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOSError(kNewRandomAccessFile, error_code); 596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MakeIOError(fname, 597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PlatformFileErrorString(error_code), 598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) kNewRandomAccessFile, 599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) error_code); 600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::NewWritableFile(const std::string& fname, 603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WritableFile** result) { 604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = NULL; 605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "wb"); 606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (f == NULL) { 607eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int saved_errno = errno; 608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kNewWritableFile); 609eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return MakeIOError( 610eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fname, strerror(saved_errno), kNewWritableFile, saved_errno); 611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *result = new ChromiumWritableFile(fname, f, this, this, make_backup_); 613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromiumEnv::FileExists(const std::string& fname) { 6187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return ::base::PathExists(CreateFilePath(fname)); 619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) { 6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath table_name = 6234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base_name.AddExtension(table_extension); 6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool result = base::CopyFile(base_name.AddExtension(backup_table_extension), 6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) table_name); 6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string uma_name(name_); 6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_name.append(".TableRestore"); 6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::BooleanHistogram::FactoryGet( 6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); 6304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return table_name; 6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromiumEnv::RestoreIfNecessary(const std::string& dir, 6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::vector<std::string>* result) { 6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<base::FilePath> tables_found; 6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<base::FilePath> backups_found; 6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (std::vector<std::string>::iterator it = result->begin(); 6384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it != result->end(); 6394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ++it) { 6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath current = CreateFilePath(*it); 6414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (current.MatchesExtension(table_extension)) 6424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tables_found.insert(current.RemoveExtension()); 6434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (current.MatchesExtension(backup_table_extension)) 6444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) backups_found.insert(current.RemoveExtension()); 6454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 6464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<base::FilePath> backups_only; 6474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set_difference(backups_found.begin(), 6484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) backups_found.end(), 6494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tables_found.begin(), 6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tables_found.end(), 6514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::inserter(backups_only, backups_only.begin())); 6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (backups_only.size()) { 6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string uma_name(name_); 6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_name.append(".MissingFiles"); 6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int num_missing_files = 6564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) backups_only.size() > INT_MAX ? INT_MAX : backups_only.size(); 6574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Histogram::FactoryGet(uma_name, 6584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1 /*min*/, 6594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 100 /*max*/, 6604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8 /*num_buckets*/, 6614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Histogram::kUmaTargetedHistogramFlag) 6624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ->Add(num_missing_files); 6634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 6644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir); 6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (std::set<base::FilePath>::iterator it = backups_only.begin(); 6664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) it != backups_only.end(); 6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ++it) { 6684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath restored_table_name = 6694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RestoreFromBackup(dir_filepath.Append(*it)); 6704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result->push_back(FilePathToString(restored_table_name.BaseName())); 6714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 6724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 6734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 6748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace { 6758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_WIN) 6768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)static base::PlatformFileError GetDirectoryEntries( 6778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const base::FilePath& dir_filepath, 6788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<base::FilePath>* result) { 6798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // TODO(dgrogan): Replace with FindFirstFile / FindNextFile. Note that until 6808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // that happens this is filtering out directories whereas the Posix version 6818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // below is not. There shouldn't be any directories so this shouldn't be an 6828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // issue. 6838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FileEnumerator iter(dir_filepath, false, base::FileEnumerator::FILES); 684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath current = iter.Next(); 685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (!current.empty()) { 6868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->push_back(current.BaseName()); 687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current = iter.Next(); 688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 6898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::PLATFORM_FILE_OK; 6908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 6918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#else 6928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)static base::PlatformFileError GetDirectoryEntries( 6938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const base::FilePath& dir_filepath, 6948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<base::FilePath>* result) { 6958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string dir_string = FilePathToString(dir_filepath); 6968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->clear(); 6978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) DIR* dir = opendir(dir_string.c_str()); 6988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!dir) 6998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::ErrnoToPlatformFileError(errno); 7008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) struct dirent dent_buf; 7018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) struct dirent* dent; 7028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int readdir_result; 7038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) while ((readdir_result = readdir_r(dir, &dent_buf, &dent)) == 0 && dent) 7048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->push_back(CreateFilePath(dent->d_name)); 7058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int saved_errno = errno; 7068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) closedir(dir); 7078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (readdir_result != 0) 7088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::ErrnoToPlatformFileError(saved_errno); 7098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return base::PLATFORM_FILE_OK; 7108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 7118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif 7128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 7138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)Status ChromiumEnv::GetChildren(const std::string& dir_string, 7158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<std::string>* result) { 7168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) std::vector<base::FilePath> entries; 7178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::PlatformFileError error = 7188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GetDirectoryEntries(CreateFilePath(dir_string), &entries); 7198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (error != base::PLATFORM_FILE_OK) { 7208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) RecordOSError(kGetChildren, error); 7218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return MakeIOError( 7228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dir_string, "Could not open/read directory", kGetChildren, error); 7238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 7248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (std::vector<base::FilePath>::iterator it = entries.begin(); 7258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) it != entries.end(); 7268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ++it) { 7278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) result->push_back(FilePathToString(*it)); 7288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 7298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (make_backup_) 7318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) RestoreIfNecessary(dir_string, result); 732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::DeleteFile(const std::string& fname) { 736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 7374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::FilePath fname_filepath = CreateFilePath(fname); 738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(jorlow): Should we assert this is a file? 7394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!::base::DeleteFile(fname_filepath, false)) { 740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError(fname, "Could not delete file.", kDeleteFile); 741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kDeleteFile); 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (make_backup_ && fname_filepath.MatchesExtension(table_extension)) { 7444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::DeleteFile(fname_filepath.ReplaceExtension(backup_table_extension), 7454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) false); 7464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::CreateDir(const std::string& name) { 751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError error = base::PLATFORM_FILE_OK; 753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Retrier retrier(kCreateDir, this); 754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do { 755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (::file_util::CreateDirectoryAndGetError(CreateFilePath(name), &error)) 756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } while (retrier.ShouldKeepTrying(error)); 758eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch result = MakeIOError(name, "Could not create directory.", kCreateDir, error); 759eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RecordOSError(kCreateDir, error); 760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::DeleteDir(const std::string& name) { 764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(jorlow): Should we assert this is a directory? 7667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!::base::DeleteFile(CreateFilePath(name), false)) { 767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError(name, "Could not delete directory.", kDeleteDir); 768868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kDeleteDir); 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 770868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 771868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 773868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::GetFileSize(const std::string& fname, uint64_t* size) { 774868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status s; 775868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int64_t signed_size; 776868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) { 777868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *size = 0; 778868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) s = MakeIOError(fname, "Could not determine file size.", kGetFileSize); 779868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kGetFileSize); 780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 781868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *size = static_cast<uint64_t>(signed_size); 782868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 783868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return s; 784868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::RenameFile(const std::string& src, const std::string& dst) { 787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 788868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath src_file_path = CreateFilePath(src); 7897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!::base::PathExists(src_file_path)) 790868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 791868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath destination = CreateFilePath(dst); 792868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Retrier retrier(kRenameFile, this); 794868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError error = base::PLATFORM_FILE_OK; 795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do { 796eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (base::ReplaceFile(src_file_path, destination, &error)) 797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } while (retrier.ShouldKeepTrying(error)); 799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(error != base::PLATFORM_FILE_OK); 801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOSError(kRenameFile, error); 802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) char buf[100]; 803868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) snprintf(buf, 804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sizeof(buf), 805868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Could not rename file: %s", 806868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PlatformFileErrorString(error)); 807868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MakeIOError(src, buf, kRenameFile, error); 808868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::LockFile(const std::string& fname, FileLock** lock) { 811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *lock = NULL; 812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS | 814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PLATFORM_FILE_READ | 8154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::PLATFORM_FILE_WRITE; 816868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool created; 817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformFileError error_code; 818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformFile file; 819868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Retrier retrier(kLockFile, this); 820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do { 821868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) file = ::base::CreatePlatformFile( 822868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CreateFilePath(fname), flags, &created, &error_code); 823868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } while (error_code != ::base::PLATFORM_FILE_OK && 824868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) retrier.ShouldKeepTrying(error_code)); 825868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error_code == ::base::PLATFORM_FILE_ERROR_NOT_FOUND) { 827868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::FilePath parent = CreateFilePath(fname).DirName(); 828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::FilePath last_parent; 829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int num_missing_ancestors = 0; 830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do { 8317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::DirectoryExists(parent)) 832868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ++num_missing_ancestors; 834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) last_parent = parent; 835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) parent = parent.DirName(); 836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } while (parent != last_parent); 837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordLockFileAncestors(num_missing_ancestors); 838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error_code != ::base::PLATFORM_FILE_OK) { 841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) result = MakeIOError( 842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) fname, PlatformFileErrorString(error_code), kLockFile, error_code); 843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOSError(kLockFile, error_code); 8444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result; 8454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 8464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!locks_.Insert(fname)) { 8484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result = MakeIOError(fname, "Lock file already locked.", kLockFile); 8494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::ClosePlatformFile(file); 8504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result; 8514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 8524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Retrier lock_retrier = Retrier(kLockFile, this); 8544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) do { 8554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) error_code = ::base::LockPlatformFile(file); 8564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } while (error_code != ::base::PLATFORM_FILE_OK && 8574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) retrier.ShouldKeepTrying(error_code)); 8584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (error_code != ::base::PLATFORM_FILE_OK) { 8604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::ClosePlatformFile(file); 8614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) locks_.Remove(fname); 8624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result = MakeIOError( 8634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fname, PlatformFileErrorString(error_code), kLockFile, error_code); 8644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RecordOSError(kLockFile, error_code); 8654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result; 866868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 8674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ChromiumFileLock* my_lock = new ChromiumFileLock; 8694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) my_lock->file_ = file; 8704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) my_lock->name_ = fname; 8714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *lock = my_lock; 872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 874868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 875868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::UnlockFile(FileLock* lock) { 876868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock); 877868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Status result; 8784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 8794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::PlatformFileError error_code = 8804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::UnlockPlatformFile(my_lock->file_); 8814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (error_code != ::base::PLATFORM_FILE_OK) { 8824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result = 8834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MakeIOError(my_lock->name_, "Could not unlock lock file.", kUnlockFile); 8844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RecordOSError(kUnlockFile, error_code); 8854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ::base::ClosePlatformFile(my_lock->file_); 8864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (!::base::ClosePlatformFile(my_lock->file_)) { 8874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result = 8884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MakeIOError(my_lock->name_, "Could not close lock file.", kUnlockFile); 889868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kUnlockFile); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool removed = locks_.Remove(my_lock->name_); 8924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK(removed); 893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) delete my_lock; 894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result; 895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 897868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::GetTestDirectory(std::string* path) { 898868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mu_.Acquire(); 899868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (test_directory_.empty()) { 900868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix, 901868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &test_directory_)) { 902868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mu_.Release(); 903868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(kGetTestDirectory); 904868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MakeIOError( 905868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) "Could not create temp directory.", "", kGetTestDirectory); 906868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 907868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 908868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *path = FilePathToString(test_directory_); 909868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mu_.Release(); 910868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 911868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 91290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 913868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::NewLogger(const std::string& fname, Logger** result) { 914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FILE* f = fopen_internal(fname.c_str(), "w"); 915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (f == NULL) { 916868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = NULL; 917868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int saved_errno = errno; 918868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordOSError(kNewLogger, saved_errno); 919868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return MakeIOError(fname, strerror(saved_errno), kNewLogger, saved_errno); 920868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 921868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *result = new ChromiumLogger(f); 922868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return Status::OK(); 92390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 924868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 92590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 926868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)uint64_t ChromiumEnv::NowMicros() { 927868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ::base::TimeTicks::Now().ToInternalValue(); 928868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 930868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::SleepForMicroseconds(int micros) { 931868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Round up to the next millisecond. 932868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros)); 933868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordErrorAt(MethodID method) const { 936868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetMethodIOErrorHistogram()->Add(method); 937868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 939868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const { 940868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetLockFileAncestorHistogram()->Add(num_missing_ancestors); 941868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 942868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 943868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordOSError(MethodID method, 944868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::PlatformFileError error) const { 945868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(error < 0); 946868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(method); 947868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetOSErrorHistogram(method, -base::PLATFORM_FILE_ERROR_MAX)->Add(-error); 948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 949868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 950868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordOSError(MethodID method, int error) const { 951868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(error > 0); 952868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RecordErrorAt(method); 953868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetOSErrorHistogram(method, ERANGE + 1)->Add(error); 9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromiumEnv::RecordBackupResult(bool result) const { 9574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string uma_name(name_); 9584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_name.append(".TableBackup"); 9594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::BooleanHistogram::FactoryGet( 9604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result); 9614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 9624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 963c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method, 964868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int limit) const { 965c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string uma_name(name_); 966c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(dgrogan): This is probably not the best way to concatenate strings. 967c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uma_name.append(".IOError.").append(MethodIDToString(method)); 968c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::LinearHistogram::FactoryGet(uma_name, 1, limit, limit + 1, 969c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Histogram::kUmaTargetedHistogramFlag); 970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMethodIOErrorHistogram() const { 973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string uma_name(name_); 974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uma_name.append(".IOError"); 975c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries, 976c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag); 977c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 978c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 979c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMaxFDHistogram( 980a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const std::string& type) const { 981c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string uma_name(name_); 982c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uma_name.append(".MaxFDs.").append(type); 983c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // These numbers make each bucket twice as large as the previous bucket. 984c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int kFirstEntry = 1; 985c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int kLastEntry = 65536; 986c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const int kNumBuckets = 18; 987c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::Histogram::FactoryGet( 988c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uma_name, kFirstEntry, kLastEntry, kNumBuckets, 9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Histogram::kUmaTargetedHistogramFlag); 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 992a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetLockFileAncestorHistogram() const { 993a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::string uma_name(name_); 994a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) uma_name.append(".LockFileAncestorsNotFound"); 995a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const int kMin = 1; 996a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const int kMax = 10; 997a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const int kNumBuckets = 11; 998a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return base::LinearHistogram::FactoryGet( 999a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) uma_name, kMin, kMax, kNumBuckets, 1000a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::Histogram::kUmaTargetedHistogramFlag); 1001a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 1002a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 100390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetRetryTimeHistogram(MethodID method) const { 100490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string uma_name(name_); 100590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(dgrogan): This is probably not the best way to concatenate strings. 100690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uma_name.append(".TimeUntilSuccessFor").append(MethodIDToString(method)); 100790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 100890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int kBucketSizeMillis = 25; 100990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Add 2, 1 for each of the buckets <1 and >max. 101090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const int kNumBuckets = kMaxRetryTimeMillis / kBucketSizeMillis + 2; 101190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return base::Histogram::FactoryTimeGet( 101290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uma_name, base::TimeDelta::FromMilliseconds(1), 101390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxRetryTimeMillis + 1), 101490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kNumBuckets, 101590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Histogram::kUmaTargetedHistogramFlag); 101690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 101790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetRecoveredFromErrorHistogram( 101990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) MethodID method) const { 102090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::string uma_name(name_); 102190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uma_name.append(".RetryRecoveredFromErrorIn") 102290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) .append(MethodIDToString(method)); 102390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries, 102490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag); 102590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 102690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread : public ::base::PlatformThread::Delegate { 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread(void (*function)(void* arg), void* arg) 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : function_(function), arg_(arg) { 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::base::PlatformThreadHandle handle; 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = ::base::PlatformThread::Create(0, this, &handle); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(success); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Thread() {} 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ThreadMain() { 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*function_)(arg_); 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*function_)(void* arg); 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arg_; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::Schedule(void (*function)(void*), void* arg) { 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Acquire(); 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start background thread if necessary 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!started_bgthread_) { 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) started_bgthread_ = true; 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartThread(&ChromiumEnv::BGThreadWrapper, this); 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the queue is currently empty, the background thread may currently be 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // waiting. 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (queue_.empty()) { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bgsignal_.Signal(); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add to priority queue 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.push_back(BGItem()); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.back().function = function; 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.back().arg = arg; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::BGThread() { 1070c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::PlatformThread::SetName(name_.c_str()); 1071c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait until there is an item that is ready to run 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Acquire(); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (queue_.empty()) { 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bgsignal_.Wait(); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*function)(void*) = queue_.front().function; 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* arg = queue_.front().arg; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) queue_.pop_front(); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mu_.Release(); 1084c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TRACE_EVENT0("leveldb", "ChromiumEnv::BGThread-Task"); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*function)(arg); 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new Thread(function, arg); // Will self-delete. 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1093868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static std::string GetDirName(const std::string& filename) { 1094868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath file = base::FilePath::FromUTF8Unsafe(filename); 1095868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return FilePathToString(file.DirName()); 109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1098868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::DidCreateNewFile(const std::string& filename) { 1099868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock auto_lock(map_lock_); 1100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) needs_sync_map_[GetDirName(filename)] = true; 110190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 110290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromiumEnv::DoesDirNeedSync(const std::string& filename) { 1104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock auto_lock(map_lock_); 1105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return needs_sync_map_.find(GetDirName(filename)) != needs_sync_map_.end(); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::DidSyncDir(const std::string& filename) { 1109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::AutoLock auto_lock(map_lock_); 1110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) needs_sync_map_.erase(GetDirName(filename)); 111190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 111290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 111390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace leveldb_env 111490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 111590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace leveldb { 111690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Env* IDBEnv() { 111890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return leveldb_env::idb_env.Pointer(); 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Env* Env::Default() { 112290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return leveldb_env::default_env.Pointer(); 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace leveldb 112690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1127