env_chromium.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromium_logger.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/env.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "leveldb/slice.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "port/port.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "util/logging.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h>
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <fcntl.h>
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/resource.h>
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/time.h>
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) || \
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    defined(OS_OPENBSD)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following are glibc-specific
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)size_t fread_wrapper(void *ptr, size_t size, size_t n, FILE *file) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fread(ptr, size, n, file);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)size_t fwrite_wrapper(const void *ptr, size_t size, size_t n, FILE *file) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fwrite(ptr, size, n, file);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int fflush_wrapper(FILE *file) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fflush(file);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int fdatasync(int fildes) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _commit(fildes);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return HANDLE_EINTR(fsync(fildes));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#else
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class TryToLockFILE {
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // This class should be deleted if it doesn't turn up anything useful after
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // going to stable (chrome 29).
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) public:
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TryToLockFILE(FILE* file) : file_to_unlock_(NULL) {
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (ftrylockfile(file) == 0)
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      file_to_unlock_ = file;
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    else
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      UMA_HISTOGRAM_BOOLEAN("LevelDBEnv.All.SafeThreadAccess", false);
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ~TryToLockFILE() {
84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (file_to_unlock_)
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      funlockfile(file_to_unlock_);
86b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) private:
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  FILE* file_to_unlock_;
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)};
91b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)size_t fread_wrapper(void *ptr, size_t size, size_t n, FILE *file) {
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TryToLockFILE lock(file);
94b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return fread_unlocked(ptr, size, n, file);
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
97b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)size_t fwrite_wrapper(const void *ptr, size_t size, size_t n, FILE *file) {
98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TryToLockFILE lock(file);
99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return fwrite_unlocked(ptr, size, n, file);
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
102b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int fflush_wrapper(FILE *file) {
103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TryToLockFILE lock(file);
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return fflush_unlocked(file);
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wide-char safe fopen wrapper.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FILE* fopen_internal(const char* fname, const char* mode) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return _wfopen(UTF8ToUTF16(fname).c_str(), ASCIIToUTF16(mode).c_str());
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fopen(fname, mode);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath CreateFilePath(const std::string& file_path) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath(UTF8ToUTF16(file_path));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath(file_path);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string FilePathToString(const base::FilePath& file_path) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UTF16ToUTF8(file_path.value());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file_path.value();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool sync_parent(const std::string& fname) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_WIN)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TRACE_EVENT0("leveldb", "sync_parent");
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath parent_dir = CreateFilePath(fname).DirName();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int parent_fd =
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      HANDLE_EINTR(open(FilePathToString(parent_dir).c_str(), O_RDONLY));
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (parent_fd < 0)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HANDLE_EINTR(fsync(parent_fd));
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HANDLE_EINTR(close(parent_fd));
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)enum MethodID {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kSequentialFileRead,
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kSequentialFileSkip,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kRandomAccessFileRead,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kWritableFileAppend,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kWritableFileClose,
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kWritableFileFlush,
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kWritableFileSync,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kNewSequentialFile,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kNewRandomAccessFile,
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kNewWritableFile,
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kDeleteFile,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kCreateDir,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kDeleteDir,
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kGetFileSize,
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  kRenameFile,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kLockFile,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kUnlockFile,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kGetTestDirectory,
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kNewLogger,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kNumEntries
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* MethodIDToString(MethodID method) {
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  switch (method) {
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kSequentialFileRead:
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "SequentialFileRead";
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kSequentialFileSkip:
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "SequentialFileSkip";
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kRandomAccessFileRead:
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "RandomAccessFileRead";
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kWritableFileAppend:
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "WritableFileAppend";
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kWritableFileClose:
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "WritableFileClose";
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kWritableFileFlush:
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "WritableFileFlush";
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kWritableFileSync:
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "WritableFileSync";
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kNewSequentialFile:
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "NewSequentialFile";
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kNewRandomAccessFile:
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "NewRandomAccessFile";
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kNewWritableFile:
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "NewWritableFile";
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kDeleteFile:
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "DeleteFile";
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kCreateDir:
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "CreateDir";
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kDeleteDir:
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "DeleteDir";
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kGetFileSize:
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "GetFileSize";
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kRenameFile:
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "RenameFile";
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kLockFile:
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "LockFile";
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kUnlockFile:
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "UnlockFile";
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kGetTestDirectory:
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "GetTestDirectory";
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kNewLogger:
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "NewLogger";
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case kNumEntries:
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NOTREACHED();
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "kNumEntries";
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NOTREACHED();
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return "Unknown";
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UMALogger {
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void RecordErrorAt(MethodID method) const = 0;
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void RecordOSError(MethodID method, int saved_errno) const = 0;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void RecordOSError(MethodID method, base::PlatformFileError error)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const = 0;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace leveldb {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Thread;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[]
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    = FILE_PATH_LITERAL("leveldb-test-");
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* PlatformFileErrorString(const ::base::PlatformFileError& error) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_FAILED:
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return "No further details.";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_IN_USE:
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "File currently in use.";
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_EXISTS:
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "File already exists.";
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NOT_FOUND:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "File not found.";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Access denied.";
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Too many files open.";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NO_MEMORY:
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Out of memory.";
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NO_SPACE:
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "No space left on drive.";
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Not a directory.";
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION:
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Invalid operation.";
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_SECURITY:
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Security error.";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_ABORT:
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "File operation aborted.";
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "The supplied path was not a file.";
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY:
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "The file was not empty.";
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_INVALID_URL:
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "Invalid URL.";
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_IO:
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return "OS or hardware error.";
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ::base::PLATFORM_FILE_OK:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "OK.";
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case ::base::PLATFORM_FILE_ERROR_MAX:
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NOTREACHED();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "Unknown error.";
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumSequentialFile: public SequentialFile {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE* file_;
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UMALogger* uma_logger_;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChromiumSequentialFile(const std::string& fname, FILE* f,
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const UMALogger* uma_logger)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : filename_(fname), file_(f), uma_logger_(uma_logger) { }
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ChromiumSequentialFile() { fclose(file_); }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Read(size_t n, Slice* result, char* scratch) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status s;
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    size_t r = fread_wrapper(scratch, 1, n, file_);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = Slice(scratch, r);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r < n) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (feof(file_)) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We leave status as ok if we hit the end of the file
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // A partial read with an error: return a non-ok status
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = Status::IOError(filename_, strerror(errno));
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        uma_logger_->RecordErrorAt(kSequentialFileRead);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Skip(uint64_t n) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fseek(file_, n, SEEK_CUR)) {
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_logger_->RecordErrorAt(kSequentialFileSkip);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Status::IOError(filename_, strerror(errno));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Status::OK();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumRandomAccessFile: public RandomAccessFile {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename_;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::base::PlatformFile file_;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UMALogger* uma_logger_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const UMALogger* uma_logger)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : filename_(fname), file_(file), uma_logger_(uma_logger) { }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Read(uint64_t offset, size_t n, Slice* result,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      char* scratch) const {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status s;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int r = ::base::ReadPlatformFile(file_, offset, scratch, n);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = Slice(scratch, (r < 0) ? 0 : r);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r < 0) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // An error: return a non-ok status
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s = Status::IOError(filename_, "Could not perform read");
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_logger_->RecordErrorAt(kRandomAccessFileRead);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumWritableFile : public WritableFile {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string filename_;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILE* file_;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const UMALogger* uma_logger_;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChromiumWritableFile(const std::string& fname, FILE* f,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const UMALogger* uma_logger)
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : filename_(fname), file_(f), uma_logger_(uma_logger) { }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ChromiumWritableFile() {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (file_ != NULL) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ignoring any potential errors
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fclose(file_);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Append(const Slice& data) {
363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    size_t r = fwrite_wrapper(data.data(), 1, data.size(), file_);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (r != data.size()) {
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      uma_logger_->RecordOSError(kWritableFileAppend, errno);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(filename_, strerror(errno));
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Close() {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fclose(file_) != 0) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(filename_, strerror(errno));
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_logger_->RecordErrorAt(kWritableFileClose);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_ = NULL;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Flush() {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
384b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (HANDLE_EINTR(fflush_wrapper(file_))) {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int saved_errno = errno;
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result = Status::IOError(filename_, strerror(saved_errno));
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      uma_logger_->RecordOSError(kWritableFileFlush, saved_errno);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status Sync() {
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TRACE_EVENT0("leveldb", "ChromiumEnv::Sync");
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int error = 0;
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
397b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (HANDLE_EINTR(fflush_wrapper(file_)))
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error = errno;
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Sync even if fflush gave an error; perhaps the data actually got out,
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // even though something went wrong.
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (fdatasync(fileno(file_)) && !error)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error = errno;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Report the first error we found.
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (error) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = Status::IOError(filename_, strerror(error));
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      uma_logger_->RecordErrorAt(kWritableFileSync);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChromiumFileLock : public FileLock {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::base::PlatformFile file_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ChromiumEnv : public Env, public UMALogger {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromiumEnv();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ChromiumEnv() {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status NewSequentialFile(const std::string& fname,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   SequentialFile** result) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE* f = fopen_internal(fname.c_str(), "rb");
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (f == NULL) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = NULL;
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int saved_errno = errno;
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOSError(kNewSequentialFile, saved_errno);
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status::IOError(fname, strerror(saved_errno));
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *result = new ChromiumSequentialFile(fname, f, this);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Status::OK();
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RecordOpenFilesLimit(const std::string& type) {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    struct rlimit nofile;
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (getrlimit(RLIMIT_NOFILE, &nofile))
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetMaxFDHistogram(type)->Add(nofile.rlim_cur);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status NewRandomAccessFile(const std::string& fname,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     RandomAccessFile** result) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool created;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformFileError error_code;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformFile file = ::base::CreatePlatformFile(
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateFilePath(fname), flags, &created, &error_code);
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (error_code == ::base::PLATFORM_FILE_OK) {
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      *result = new ChromiumRandomAccessFile(fname, file, this);
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOpenFilesLimit("Success");
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status::OK();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (error_code == ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED)
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOpenFilesLimit("TooManyOpened");
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOpenFilesLimit("OtherError");
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *result = NULL;
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordOSError(kNewRandomAccessFile, error_code);
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return Status::IOError(fname, PlatformFileErrorString(error_code));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status NewWritableFile(const std::string& fname,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 WritableFile** result) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = NULL;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE* f = fopen_internal(fname.c_str(), "wb");
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (f == NULL) {
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kNewWritableFile);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Status::IOError(fname, strerror(errno));
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!sync_parent(fname)) {
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fclose(f);
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        RecordErrorAt(kNewWritableFile);
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return Status::IOError(fname, strerror(errno));
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *result = new ChromiumWritableFile(fname, f, this);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Status::OK();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool FileExists(const std::string& fname) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::file_util::PathExists(CreateFilePath(fname));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status GetChildren(const std::string& dir,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::vector<std::string>* result) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->clear();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::file_util::FileEnumerator iter(
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES);
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath current = iter.Next();
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!current.empty()) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->push_back(FilePathToString(current.BaseName()));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current = iter.Next();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //               we'll always return OK. Maybe manually check for error
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //               conditions like the file not existing?
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Status::OK();
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status DeleteFile(const std::string& fname) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jorlow): Should we assert this is a file?
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::file_util::Delete(CreateFilePath(fname), false)) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(fname, "Could not delete file.");
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kDeleteFile);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status CreateDir(const std::string& name) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::file_util::CreateDirectory(CreateFilePath(name))) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(name, "Could not create directory.");
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kCreateDir);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status DeleteDir(const std::string& name) {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(jorlow): Should we assert this is a directory?
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::file_util::Delete(CreateFilePath(name), false)) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(name, "Could not delete directory.");
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kDeleteDir);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status s;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64_t signed_size;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *size = 0;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s = Status::IOError(fname, "Could not determine file size.");
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kGetFileSize);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *size = static_cast<uint64_t>(signed_size);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class Retrier {
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   public:
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Retrier(base::HistogramBase* histogram, const int kMaxRetryMillis) :
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        start_(base::TimeTicks::Now()),
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        limit_(start_ + base::TimeDelta::FromMilliseconds(kMaxRetryMillis)),
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        last_(start_),
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        time_to_sleep_(base::TimeDelta::FromMilliseconds(10)),
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        success_(true),
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        histogram_(histogram) {
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ~Retrier() {
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (success_)
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        histogram_->AddTime(last_ - start_);
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool ShouldKeepTrying() {
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (last_ < limit_) {
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::PlatformThread::Sleep(time_to_sleep_);
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        last_ = base::TimeTicks::Now();
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return true;
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      success_ = false;
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   private:
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks start_;
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks limit_;
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks last_;
575c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeDelta time_to_sleep_;
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool success_;
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::HistogramBase* histogram_;
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status RenameFile(const std::string& src, const std::string& dst) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath src_file_path = CreateFilePath(src);
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!::file_util::PathExists(src_file_path))
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return result;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath destination = CreateFilePath(dst);
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Retrier retrier(GetRetryTimeHistogram(kRenameFile), kMaxRenameTimeMillis);
588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::PlatformFileError error = base::PLATFORM_FILE_OK;
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    do {
590b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (::file_util::ReplaceFileAndGetError(
591b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)              src_file_path, destination, &error)) {
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sync_parent(dst);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (src != dst)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          sync_parent(src);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return result;
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } while (retrier.ShouldKeepTrying());
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK(error != base::PLATFORM_FILE_OK);
600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    RecordOSError(kRenameFile, error);
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    char buf[100];
602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    snprintf(buf, sizeof(buf), "Could not rename file: %s",
603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)             PlatformFileErrorString(error));
604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return Status::IOError(src, buf);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status LockFile(const std::string& fname, FileLock** lock) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *lock = NULL;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS |
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ::base::PLATFORM_FILE_READ |
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ::base::PLATFORM_FILE_WRITE |
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ::base::PLATFORM_FILE_EXCLUSIVE_READ |
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ::base::PLATFORM_FILE_EXCLUSIVE_WRITE;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool created;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformFileError error_code;
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ::base::PlatformFile file;
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Retrier retrier(GetRetryTimeHistogram(kLockFile), kMaxRenameTimeMillis);
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    do {
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      file = ::base::CreatePlatformFile(
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          CreateFilePath(fname), flags, &created, &error_code);
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } while (error_code != ::base::PLATFORM_FILE_OK &&
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             retrier.ShouldKeepTrying());
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
625a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (error_code == ::base::PLATFORM_FILE_ERROR_NOT_FOUND) {
626a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      ::base::FilePath parent = CreateFilePath(fname).DirName();
627a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      ::base::FilePath last_parent;
628a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      int num_missing_ancestors = 0;
629a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      do {
630a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        if (file_util::DirectoryExists(parent))
631a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          break;
632a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        ++num_missing_ancestors;
633a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        last_parent = parent;
634a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        parent = parent.DirName();
635a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      } while (parent != last_parent);
636a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      RecordLockFileAncestors(num_missing_ancestors);
637a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
638a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code != ::base::PLATFORM_FILE_OK) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError(fname, PlatformFileErrorString(error_code));
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOSError(kLockFile, error_code);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ChromiumFileLock* my_lock = new ChromiumFileLock;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      my_lock->file_ = file;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *lock = my_lock;
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status UnlockFile(FileLock* lock) {
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Status result;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!::base::ClosePlatformFile(my_lock->file_)) {
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = Status::IOError("Could not close lock file.");
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RecordErrorAt(kUnlockFile);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete my_lock;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Schedule(void (*function)(void*), void* arg);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StartThread(void (*function)(void* arg), void* arg);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status GetTestDirectory(std::string* path) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Acquire();
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (test_directory_.empty()) {
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix,
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &test_directory_)) {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mu_.Release();
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        RecordErrorAt(kGetTestDirectory);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return Status::IOError("Could not create temp directory.");
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *path = FilePathToString(test_directory_);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Release();
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Status::OK();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Status NewLogger(const std::string& fname, Logger** result) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE* f = fopen_internal(fname.c_str(), "w");
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (f == NULL) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = NULL;
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int saved_errno = errno;
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      RecordOSError(kNewLogger, saved_errno);
686c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return Status::IOError(fname, strerror(saved_errno));
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!sync_parent(fname)) {
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fclose(f);
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return Status::IOError(fname, strerror(errno));
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = new ChromiumLogger(f);
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Status::OK();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual uint64_t NowMicros() {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ::base::TimeTicks::Now().ToInternalValue();
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SleepForMicroseconds(int micros) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Round up to the next millisecond.
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros));
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
706c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RecordErrorAt(MethodID method) const {
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetMethodIOErrorHistogram()->Add(method);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
710a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  void RecordLockFileAncestors(int num_missing_ancestors) const {
711a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    GetLockFileAncestorHistogram()->Add(num_missing_ancestors);
712a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
713a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RecordOSError(MethodID method, base::PlatformFileError error) const {
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(error < 0);
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordErrorAt(method);
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetOSErrorHistogram(method, -base::PLATFORM_FILE_ERROR_MAX)->
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        Add(-error);
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RecordOSError(MethodID method, int error) const {
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(error > 0);
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RecordErrorAt(method);
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetOSErrorHistogram(method, ERANGE + 1)->Add(error);
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string name_;
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kMaxRenameTimeMillis;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BGThread() is the body of the background thread
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void BGThread();
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void BGThreadWrapper(void* arg) {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const;
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::HistogramBase* GetRetryTimeHistogram(MethodID method) const;
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::HistogramBase* GetMethodIOErrorHistogram() const;
741a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::HistogramBase* GetMaxFDHistogram(const std::string& type) const;
742a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::HistogramBase* GetLockFileAncestorHistogram() const;
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_directory_;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::base::Lock mu_;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ::base::ConditionVariable bgsignal_;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool started_bgthread_;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Entry per Schedule() call
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct BGItem { void* arg; void (*function)(void*); };
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::deque<BGItem> BGQueue;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BGQueue queue_;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromiumEnv::ChromiumEnv()
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : name_("LevelDBEnv"),
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bgsignal_(&mu_),
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      started_bgthread_(false),
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kMaxRenameTimeMillis(1000) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method,
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                            int limit) const {
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dgrogan): This is probably not the best way to concatenate strings.
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".IOError.").append(MethodIDToString(method));
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(uma_name, 1, limit, limit + 1,
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetRetryTimeHistogram(MethodID method) const {
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dgrogan): This is probably not the best way to concatenate strings.
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".TimeUntilSuccessFor").append(MethodIDToString(method));
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kBucketSizeMillis = 25;
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add 2, 1 for each of the buckets <1 and >max.
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kNumBuckets = kMaxRenameTimeMillis / kBucketSizeMillis + 2;
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::Histogram::FactoryTimeGet(
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      uma_name, base::TimeDelta::FromMilliseconds(1),
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxRenameTimeMillis + 1),
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kNumBuckets,
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMethodIOErrorHistogram() const {
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".IOError");
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries,
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag);
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMaxFDHistogram(
794a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const std::string& type) const {
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".MaxFDs.").append(type);
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // These numbers make each bucket twice as large as the previous bucket.
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kFirstEntry = 1;
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kLastEntry = 65536;
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kNumBuckets = 18;
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::Histogram::FactoryGet(
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      uma_name, kFirstEntry, kLastEntry, kNumBuckets,
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
806a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetLockFileAncestorHistogram() const {
807a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::string uma_name(name_);
808a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  uma_name.append(".LockFileAncestorsNotFound");
809a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kMin = 1;
810a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kMax = 10;
811a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kNumBuckets = 11;
812a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(
813a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      uma_name, kMin, kMax, kNumBuckets,
814a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
815a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
816a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread : public ::base::PlatformThread::Delegate {
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread(void (*function)(void* arg), void* arg)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : function_(function), arg_(arg) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformThreadHandle handle;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = ::base::PlatformThread::Create(0, this, &handle);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Thread() {}
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ThreadMain() {
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*function_)(arg_);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*function_)(void* arg);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* arg_;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::Schedule(void (*function)(void*), void* arg) {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mu_.Acquire();
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start background thread if necessary
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!started_bgthread_) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    started_bgthread_ = true;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartThread(&ChromiumEnv::BGThreadWrapper, this);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the queue is currently empty, the background thread may currently be
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // waiting.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (queue_.empty()) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bgsignal_.Signal();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add to priority queue
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.push_back(BGItem());
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.back().function = function;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.back().arg = arg;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mu_.Release();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::BGThread() {
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThread::SetName(name_.c_str());
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait until there is an item that is ready to run
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Acquire();
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (queue_.empty()) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bgsignal_.Wait();
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void (*function)(void*) = queue_.front().function;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg = queue_.front().arg;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queue_.pop_front();
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Release();
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TRACE_EVENT0("leveldb", "ChromiumEnv::BGThread-Task");
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*function)(arg);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new Thread(function, arg); // Will self-delete.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class IDBEnv : public ChromiumEnv {
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IDBEnv() : ChromiumEnv() {
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    name_ = "LevelDBEnv.IDB";
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)::base::LazyInstance<IDBEnv>::Leaky
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    idb_env = LAZY_INSTANCE_INITIALIZER;
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)::base::LazyInstance<ChromiumEnv>::Leaky
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_env = LAZY_INSTANCE_INITIALIZER;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Env* IDBEnv() {
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return idb_env.Pointer();
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Env* Env::Default() {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return default_env.Pointer();
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
907