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