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)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/leveldatabase/env_chromium.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <io.h>
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/debug/trace_event.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/leveldatabase/env_chromium_stdio.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/re2/re2/re2.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/command_line.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "third_party/leveldatabase/env_chromium_win.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using leveldb::FileLock;
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using leveldb::Slice;
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using leveldb::Status;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace leveldb_env {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::FilePath::CharType backup_table_extension[] =
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FILE_PATH_LITERAL(".bak");
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const base::FilePath::CharType table_extension[] = FILE_PATH_LITERAL(".ldb");
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLevelDBTestDirectoryPrefix[]
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    = FILE_PATH_LITERAL("leveldb-test-");
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ChromiumFileLock : public FileLock {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::base::File file_;
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string name_;
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class Retrier {
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Retrier(MethodID method, RetrierProvider* provider)
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : start_(base::TimeTicks::Now()),
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        limit_(start_ + base::TimeDelta::FromMilliseconds(
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            provider->MaxRetryTimeMillis())),
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        last_(start_),
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        time_to_sleep_(base::TimeDelta::FromMilliseconds(10)),
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        success_(true),
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        method_(method),
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        last_error_(base::File::FILE_OK),
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        provider_(provider) {}
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ~Retrier() {
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (success_) {
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      provider_->GetRetryTimeHistogram(method_)->AddTime(last_ - start_);
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (last_error_ != base::File::FILE_OK) {
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        DCHECK_LT(last_error_, 0);
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        provider_->GetRecoveredFromErrorHistogram(method_)->Add(-last_error_);
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool ShouldKeepTrying(base::File::Error last_error) {
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DCHECK_NE(last_error, base::File::FILE_OK);
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    last_error_ = last_error;
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (last_ < limit_) {
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::PlatformThread::Sleep(time_to_sleep_);
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      last_ = base::TimeTicks::Now();
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return true;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    success_ = false;
76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::TimeTicks start_;
81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::TimeTicks limit_;
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::TimeTicks last_;
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::TimeDelta time_to_sleep_;
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success_;
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MethodID method_;
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File::Error last_error_;
87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RetrierProvider* provider_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class IDBEnvStdio : public ChromiumEnvStdio {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IDBEnvStdio() : ChromiumEnvStdio() {
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    name_ = "LevelDBEnv.IDB";
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    make_backup_ = true;
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class IDBEnvWin : public ChromiumEnvWin {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public:
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  IDBEnvWin() : ChromiumEnvWin() {
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    name_ = "LevelDBEnv.IDB";
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    make_backup_ = true;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)::base::LazyInstance<IDBEnvWin>::Leaky idb_env =
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)::base::LazyInstance<IDBEnvStdio>::Leaky idb_env =
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)::base::LazyInstance<ChromiumEnvStdio>::Leaky default_env =
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // unnamed namespace
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char* MethodIDToString(MethodID method) {
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (method) {
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kSequentialFileRead:
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "SequentialFileRead";
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kSequentialFileSkip:
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "SequentialFileSkip";
1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kRandomAccessFileRead:
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "RandomAccessFileRead";
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kWritableFileAppend:
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "WritableFileAppend";
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kWritableFileClose:
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "WritableFileClose";
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kWritableFileFlush:
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "WritableFileFlush";
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kWritableFileSync:
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "WritableFileSync";
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kNewSequentialFile:
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "NewSequentialFile";
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kNewRandomAccessFile:
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "NewRandomAccessFile";
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kNewWritableFile:
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "NewWritableFile";
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kDeleteFile:
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "DeleteFile";
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kCreateDir:
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "CreateDir";
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kDeleteDir:
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "DeleteDir";
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kGetFileSize:
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "GetFileSize";
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kRenameFile:
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "RenameFile";
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kLockFile:
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "LockFile";
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kUnlockFile:
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "UnlockFile";
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kGetTestDirectory:
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "GetTestDirectory";
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kNewLogger:
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "NewLogger";
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kSyncParent:
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "SyncParent";
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case kGetChildren:
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return "GetChildren";
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case kNumEntries:
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      NOTREACHED();
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return "kNumEntries";
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  NOTREACHED();
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return "Unknown";
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename,
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   const char* message,
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   MethodID method,
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   int saved_errno) {
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  char buf[512];
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  snprintf(buf,
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           sizeof(buf),
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           "%s (ChromeMethodErrno: %d::%s::%d)",
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           message,
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           method,
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           MethodIDToString(method),
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           saved_errno);
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status::IOError(filename, buf);
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename,
189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   const char* message,
190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                   MethodID method,
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   base::File::Error error) {
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_LT(error, 0);
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  char buf[512];
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  snprintf(buf,
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           sizeof(buf),
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           "%s (ChromeMethodPFE: %d::%s::%d)",
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           message,
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           method,
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           MethodIDToString(method),
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           -error);
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status::IOError(filename, buf);
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status MakeIOError(Slice filename, const char* message, MethodID method) {
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  char buf[512];
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  snprintf(buf,
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           sizeof(buf),
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           "%s (ChromeMethodOnly: %d::%s)",
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           message,
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           method,
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           MethodIDToString(method));
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status::IOError(filename, buf);
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ErrorParsingResult ParseMethodAndError(const char* string,
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       MethodID* method_param,
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       int* error) {
2187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  int method;
2197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (RE2::PartialMatch(string, "ChromeMethodOnly: (\\d+)", &method)) {
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    *method_param = static_cast<MethodID>(method);
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return METHOD_ONLY;
2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (RE2::PartialMatch(
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          string, "ChromeMethodPFE: (\\d+)::.*::(\\d+)", &method, error)) {
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *error = -*error;
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    *method_param = static_cast<MethodID>(method);
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return METHOD_AND_PFE;
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (RE2::PartialMatch(
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          string, "ChromeMethodErrno: (\\d+)::.*::(\\d+)", &method, error)) {
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    *method_param = static_cast<MethodID>(method);
2327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return METHOD_AND_ERRNO;
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return NONE;
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Keep in sync with LevelDBCorruptionTypes in histograms.xml. Also, don't
2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// change the order because indices into this array have been recorded in uma
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// histograms.
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const char* patterns[] = {
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "missing files",
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "log record too small",
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "corrupted internal key",
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "partial record",
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "missing start of fragmented record",
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "error in middle of record",
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "unknown record type",
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "truncated record at end",
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad record length",
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "VersionEdit",
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "FileReader invoked with unexpected value",
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "corrupted key",
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "CURRENT file does not end with newline",
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "no meta-nextfile entry",
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "no meta-lognumber entry",
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "no last-sequence-number entry",
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "malformed WriteBatch",
2581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad WriteBatch Put",
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad WriteBatch Delete",
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "unknown WriteBatch tag",
2611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "WriteBatch has wrong count",
2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad entry in block",
2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad block contents",
2641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad block handle",
2651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "truncated block read",
2661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "block checksum mismatch",
2671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "checksum mismatch",
2681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "corrupted compressed block contents",
2691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad block type",
2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "bad magic number",
2711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  "file is too short",
2721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)};
2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Returns 1-based index into the above array or 0 if nothing matches.
2750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)int GetCorruptionCode(const leveldb::Status& status) {
2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!status.IsIOError());
2771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(!status.ok());
2781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int kOtherError = 0;
2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int error = kOtherError;
2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const std::string& str_error = status.ToString();
2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const size_t kNumPatterns = arraysize(patterns);
2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (size_t i = 0; i < kNumPatterns; ++i) {
2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (str_error.find(patterns[i]) != std::string::npos) {
2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      error = i + 1;
2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      break;
2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return error;
2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)int GetNumCorruptionCodes() {
2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // + 1 for the "other" error that is returned when a corruption message
2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // doesn't match any of the patterns.
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return arraysize(patterns) + 1;
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
2961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)std::string GetCorruptionMessage(const leveldb::Status& status) {
2980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  int code = GetCorruptionCode(status);
2990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (code == 0)
3000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    return "Unknown corruption";
3010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return patterns[code - 1];
3020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool IndicatesDiskFull(const leveldb::Status& status) {
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (status.ok())
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  leveldb_env::MethodID method;
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int error = -1;
30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError(
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      status.ToString().c_str(), &method, &error);
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return (result == leveldb_env::METHOD_AND_PFE &&
312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          static_cast<base::File::Error>(error) ==
313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              base::File::FILE_ERROR_NO_SPACE) ||
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)         (result == leveldb_env::METHOD_AND_ERRNO && error == ENOSPC);
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool IsIOError(const leveldb::Status& status) {
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  leveldb_env::MethodID method;
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int error = -1;
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  leveldb_env::ErrorParsingResult result = leveldb_env::ParseMethodAndError(
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      status.ToString().c_str(), &method, &error);
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return result != leveldb_env::NONE;
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool IsCorruption(const leveldb::Status& status) {
3260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // LevelDB returns InvalidArgument when an sst file is truncated but there is
3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // no IsInvalidArgument() accessor defined.
3280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  return status.IsCorruption() || (!status.ok() && !IsIOError(status));
3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
3300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::string FilePathToString(const base::FilePath& file_path) {
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if defined(OS_WIN)
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF16ToUTF8(file_path.value());
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#else
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return file_path.value();
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::FilePath ChromiumEnv::CreateFilePath(const std::string& file_path) {
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_WIN)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::FilePath(base::UTF8ToUTF16(file_path));
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::FilePath(file_path);
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ChromiumEnv::MakeBackup(const std::string& fname) {
3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath original_table_name = CreateFilePath(fname);
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath backup_table_name =
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      original_table_name.ReplaceExtension(backup_table_extension);
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return base::CopyFile(original_table_name, backup_table_name);
3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool ChromiumEnv::HasTableExtension(const base::FilePath& path) {
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return path.MatchesExtension(table_extension);
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumEnv::ChromiumEnv()
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : name_("LevelDBEnv"),
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      make_backup_(false),
361868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bgsignal_(&mu_),
362868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      started_bgthread_(false),
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      kMaxRetryTimeMillis(1000) {
364868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ChromiumEnv::~ChromiumEnv() {
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // In chromium, ChromiumEnv is leaked. It'd be nice to add NOTREACHED here to
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // ensure that behavior isn't accidentally changed, but there's an instance in
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // a unit test that is deleted.
370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ChromiumEnv::FileExists(const std::string& fname) {
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return ::base::PathExists(CreateFilePath(fname));
374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char* ChromiumEnv::FileErrorString(::base::File::Error error) {
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (error) {
378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_FAILED:
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "No further details.";
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_IN_USE:
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "File currently in use.";
382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_EXISTS:
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "File already exists.";
384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NOT_FOUND:
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "File not found.";
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_ACCESS_DENIED:
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Access denied.";
388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_TOO_MANY_OPENED:
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Too many files open.";
390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NO_MEMORY:
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Out of memory.";
392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NO_SPACE:
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "No space left on drive.";
394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NOT_A_DIRECTORY:
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Not a directory.";
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_INVALID_OPERATION:
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Invalid operation.";
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_SECURITY:
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Security error.";
400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_ABORT:
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "File operation aborted.";
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NOT_A_FILE:
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "The supplied path was not a file.";
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_NOT_EMPTY:
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "The file was not empty.";
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_INVALID_URL:
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "Invalid URL.";
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_IO:
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "OS or hardware error.";
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_OK:
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return "OK.";
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case ::base::File::FILE_ERROR_MAX:
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTIMPLEMENTED();
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return "Unknown error.";
417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)base::FilePath ChromiumEnv::RestoreFromBackup(const base::FilePath& base_name) {
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath table_name =
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base_name.AddExtension(table_extension);
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool result = base::CopyFile(base_name.AddExtension(backup_table_extension),
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                               table_name);
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string uma_name(name_);
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uma_name.append(".TableRestore");
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::BooleanHistogram::FactoryGet(
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result);
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return table_name;
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromiumEnv::RestoreIfNecessary(const std::string& dir,
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     std::vector<std::string>* result) {
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::set<base::FilePath> tables_found;
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::set<base::FilePath> backups_found;
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (std::vector<std::string>::iterator it = result->begin();
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != result->end();
4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++it) {
4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::FilePath current = CreateFilePath(*it);
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (current.MatchesExtension(table_extension))
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      tables_found.insert(current.RemoveExtension());
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (current.MatchesExtension(backup_table_extension))
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      backups_found.insert(current.RemoveExtension());
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::set<base::FilePath> backups_only =
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::STLSetDifference<std::set<base::FilePath> >(backups_found,
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                                        tables_found);
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (backups_only.size()) {
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    std::string uma_name(name_);
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    uma_name.append(".MissingFiles");
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int num_missing_files =
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        backups_only.size() > INT_MAX ? INT_MAX : backups_only.size();
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::Histogram::FactoryGet(uma_name,
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                1 /*min*/,
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                100 /*max*/,
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                8 /*num_buckets*/,
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                base::Histogram::kUmaTargetedHistogramFlag)
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        ->Add(num_missing_files);
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath dir_filepath = base::FilePath::FromUTF8Unsafe(dir);
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (std::set<base::FilePath>::iterator it = backups_only.begin();
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       it != backups_only.end();
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       ++it) {
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::FilePath restored_table_name =
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        RestoreFromBackup(dir_filepath.Append(*it));
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    result->push_back(FilePathToString(restored_table_name.BaseName()));
4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)Status ChromiumEnv::GetChildren(const std::string& dir_string,
4718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                std::vector<std::string>* result) {
4728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  std::vector<base::FilePath> entries;
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File::Error error =
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      GetDirectoryEntries(CreateFilePath(dir_string), &entries);
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error != base::File::FILE_OK) {
4768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    RecordOSError(kGetChildren, error);
4778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return MakeIOError(
4788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        dir_string, "Could not open/read directory", kGetChildren, error);
4798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  result->clear();
4818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (std::vector<base::FilePath>::iterator it = entries.begin();
4828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       it != entries.end();
4838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       ++it) {
4848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    result->push_back(FilePathToString(*it));
4858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
4868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (make_backup_)
4888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    RestoreIfNecessary(dir_string, result);
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status::OK();
490868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
491a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::DeleteFile(const std::string& fname) {
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::FilePath fname_filepath = CreateFilePath(fname);
495868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jorlow): Should we assert this is a file?
4964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!::base::DeleteFile(fname_filepath, false)) {
497868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result = MakeIOError(fname, "Could not delete file.", kDeleteFile);
498868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordErrorAt(kDeleteFile);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (make_backup_ && fname_filepath.MatchesExtension(table_extension)) {
5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::DeleteFile(fname_filepath.ReplaceExtension(backup_table_extension),
5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     false);
5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
506868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
507868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::CreateDir(const std::string& name) {
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File::Error error = base::File::FILE_OK;
510868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Retrier retrier(kCreateDir, this);
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (base::CreateDirectoryAndGetError(CreateFilePath(name), &error))
513868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return result;
514868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (retrier.ShouldKeepTrying(error));
515eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  result = MakeIOError(name, "Could not create directory.", kCreateDir, error);
516eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  RecordOSError(kCreateDir, error);
517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::DeleteDir(const std::string& name) {
521868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jorlow): Should we assert this is a directory?
5237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!::base::DeleteFile(CreateFilePath(name), false)) {
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    result = MakeIOError(name, "Could not delete directory.", kDeleteDir);
525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordErrorAt(kDeleteDir);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::GetFileSize(const std::string& fname, uint64_t* size) {
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status s;
532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64_t signed_size;
533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!::base::GetFileSize(CreateFilePath(fname), &signed_size)) {
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *size = 0;
535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    s = MakeIOError(fname, "Could not determine file size.", kGetFileSize);
536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordErrorAt(kGetFileSize);
537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *size = static_cast<uint64_t>(signed_size);
539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return s;
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::RenameFile(const std::string& src, const std::string& dst) {
544868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FilePath src_file_path = CreateFilePath(src);
5467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!::base::PathExists(src_file_path))
547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return result;
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FilePath destination = CreateFilePath(dst);
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Retrier retrier(kRenameFile, this);
551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::File::Error error = base::File::FILE_OK;
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (base::ReplaceFile(src_file_path, destination, &error))
554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return result;
555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } while (retrier.ShouldKeepTrying(error));
556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(error != base::File::FILE_OK);
558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RecordOSError(kRenameFile, error);
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  char buf[100];
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  snprintf(buf,
561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           sizeof(buf),
562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           "Could not rename file: %s",
563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           FileErrorString(error));
564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return MakeIOError(src, buf, kRenameFile, error);
565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::LockFile(const std::string& fname, FileLock** lock) {
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *lock = NULL;
569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int flags = ::base::File::FLAG_OPEN_ALWAYS |
571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              ::base::File::FLAG_READ |
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              ::base::File::FLAG_WRITE;
573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::base::File::Error error_code;
574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::base::File file;
575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Retrier retrier(kLockFile, this);
576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  do {
577a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    file.Initialize(CreateFilePath(fname), flags);
578a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (!file.IsValid())
579a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      error_code = file.error_details();
580a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } while (!file.IsValid() && retrier.ShouldKeepTrying(error_code));
581a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
582a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!file.IsValid()) {
583a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (error_code == ::base::File::FILE_ERROR_NOT_FOUND) {
584a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ::base::FilePath parent = CreateFilePath(fname).DirName();
585a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ::base::FilePath last_parent;
586a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      int num_missing_ancestors = 0;
587a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      do {
588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (base::DirectoryExists(parent))
589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          break;
590a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ++num_missing_ancestors;
591a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        last_parent = parent;
592a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        parent = parent.DirName();
593a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      } while (parent != last_parent);
594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      RecordLockFileAncestors(num_missing_ancestors);
595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
597a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    result = MakeIOError(fname, FileErrorString(error_code), kLockFile,
598a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         error_code);
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RecordOSError(kLockFile, error_code);
6004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return result;
6014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!locks_.Insert(fname)) {
6044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    result = MakeIOError(fname, "Lock file already locked.", kLockFile);
6054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return result;
6064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
6074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Retrier lock_retrier = Retrier(kLockFile, this);
6094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  do {
610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    error_code = file.Lock();
611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } while (error_code != ::base::File::FILE_OK &&
6124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           retrier.ShouldKeepTrying(error_code));
6134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
614a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error_code != ::base::File::FILE_OK) {
6154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    locks_.Remove(fname);
616a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    result = MakeIOError(fname, FileErrorString(error_code), kLockFile,
617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         error_code);
6184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RecordOSError(kLockFile, error_code);
6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return result;
620868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
6214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
6224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ChromiumFileLock* my_lock = new ChromiumFileLock;
623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  my_lock->file_ = file.Pass();
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  my_lock->name_ = fname;
6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  *lock = my_lock;
626868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::UnlockFile(FileLock* lock) {
630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock);
631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Status result;
6324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ::base::File::Error error_code = my_lock->file_.Unlock();
634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (error_code != ::base::File::FILE_OK) {
6354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    result =
6364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        MakeIOError(my_lock->name_, "Could not unlock lock file.", kUnlockFile);
6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    RecordOSError(kUnlockFile, error_code);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool removed = locks_.Remove(my_lock->name_);
6404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(removed);
641868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  delete my_lock;
642868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return result;
643868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)Status ChromiumEnv::GetTestDirectory(std::string* path) {
646868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  mu_.Acquire();
647868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (test_directory_.empty()) {
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!base::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix,
649a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      &test_directory_)) {
650868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      mu_.Release();
651868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      RecordErrorAt(kGetTestDirectory);
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return MakeIOError(
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          "Could not create temp directory.", "", kGetTestDirectory);
654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
655868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
656868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  *path = FilePathToString(test_directory_);
657868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  mu_.Release();
658868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return Status::OK();
659868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
66090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
661868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)uint64_t ChromiumEnv::NowMicros() {
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return ::base::TimeTicks::Now().ToInternalValue();
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::SleepForMicroseconds(int micros) {
666868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Round up to the next millisecond.
667868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ::base::PlatformThread::Sleep(::base::TimeDelta::FromMicroseconds(micros));
668868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
670868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordErrorAt(MethodID method) const {
671868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GetMethodIOErrorHistogram()->Add(method);
672868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
674868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordLockFileAncestors(int num_missing_ancestors) const {
675868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GetLockFileAncestorHistogram()->Add(num_missing_ancestors);
676868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
677868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
678868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordOSError(MethodID method,
679a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                base::File::Error error) const {
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_LT(error, 0);
681868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RecordErrorAt(method);
682a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GetOSErrorHistogram(method, -base::File::FILE_ERROR_MAX)->Add(-error);
683868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
684868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
685868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::RecordOSError(MethodID method, int error) const {
6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_GT(error, 0);
687868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RecordErrorAt(method);
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GetOSErrorHistogram(method, ERANGE + 1)->Add(error);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ChromiumEnv::RecordBackupResult(bool result) const {
6924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string uma_name(name_);
6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uma_name.append(".TableBackup");
6944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::BooleanHistogram::FactoryGet(
6954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      uma_name, base::Histogram::kUmaTargetedHistogramFlag)->AddBoolean(result);
6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
6974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetOSErrorHistogram(MethodID method,
699868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                                      int limit) const {
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dgrogan): This is probably not the best way to concatenate strings.
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".IOError.").append(MethodIDToString(method));
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(uma_name, 1, limit, limit + 1,
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMethodIOErrorHistogram() const {
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".IOError");
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries,
711c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag);
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetMaxFDHistogram(
715a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const std::string& type) const {
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string uma_name(name_);
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uma_name.append(".MaxFDs.").append(type);
718c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // These numbers make each bucket twice as large as the previous bucket.
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kFirstEntry = 1;
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kLastEntry = 65536;
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int kNumBuckets = 18;
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::Histogram::FactoryGet(
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      uma_name, kFirstEntry, kLastEntry, kNumBuckets,
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
727a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetLockFileAncestorHistogram() const {
728a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  std::string uma_name(name_);
729a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  uma_name.append(".LockFileAncestorsNotFound");
730a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kMin = 1;
731a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kMax = 10;
732a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const int kNumBuckets = 11;
733a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(
734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      uma_name, kMin, kMax, kNumBuckets,
735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
736a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
737a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
73890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetRetryTimeHistogram(MethodID method) const {
73990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string uma_name(name_);
74090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(dgrogan): This is probably not the best way to concatenate strings.
74190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uma_name.append(".TimeUntilSuccessFor").append(MethodIDToString(method));
74290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
74390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kBucketSizeMillis = 25;
74490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Add 2, 1 for each of the buckets <1 and >max.
74590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const int kNumBuckets = kMaxRetryTimeMillis / kBucketSizeMillis + 2;
74690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return base::Histogram::FactoryTimeGet(
74790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      uma_name, base::TimeDelta::FromMilliseconds(1),
74890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kMaxRetryTimeMillis + 1),
74990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      kNumBuckets,
75090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Histogram::kUmaTargetedHistogramFlag);
75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)base::HistogramBase* ChromiumEnv::GetRecoveredFromErrorHistogram(
75490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    MethodID method) const {
75590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string uma_name(name_);
75690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  uma_name.append(".RetryRecoveredFromErrorIn")
75790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      .append(MethodIDToString(method));
75890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return base::LinearHistogram::FactoryGet(uma_name, 1, kNumEntries,
75990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      kNumEntries + 1, base::Histogram::kUmaTargetedHistogramFlag);
76090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
76190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Thread : public ::base::PlatformThread::Delegate {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread(void (*function)(void* arg), void* arg)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : function_(function), arg_(arg) {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::base::PlatformThreadHandle handle;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = ::base::PlatformThread::Create(0, this, &handle);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Thread() {}
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void ThreadMain() {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*function_)(arg_);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void (*function_)(void* arg);
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* arg_;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ChromiumEnv::Schedule(ScheduleFunc* function, void* arg) {
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mu_.Acquire();
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start background thread if necessary
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!started_bgthread_) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    started_bgthread_ = true;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartThread(&ChromiumEnv::BGThreadWrapper, this);
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the queue is currently empty, the background thread may currently be
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // waiting.
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (queue_.empty()) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bgsignal_.Signal();
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add to priority queue
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.push_back(BGItem());
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.back().function = function;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  queue_.back().arg = arg;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mu_.Release();
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::BGThread() {
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThread::SetName(name_.c_str());
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Wait until there is an item that is ready to run
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Acquire();
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (queue_.empty()) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bgsignal_.Wait();
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void (*function)(void*) = queue_.front().function;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arg = queue_.front().arg;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    queue_.pop_front();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mu_.Release();
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TRACE_EVENT0("leveldb", "ChromiumEnv::BGThread-Task");
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*function)(arg);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) {
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  new Thread(function, arg);  // Will self-delete.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
828868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static std::string GetDirName(const std::string& filename) {
829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::FilePath file = base::FilePath::FromUTF8Unsafe(filename);
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return FilePathToString(file.DirName());
83190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
83290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::DidCreateNewFile(const std::string& filename) {
834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::AutoLock auto_lock(map_lock_);
835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  needs_sync_map_[GetDirName(filename)] = true;
83690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
83790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ChromiumEnv::DoesDirNeedSync(const std::string& filename) {
839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::AutoLock auto_lock(map_lock_);
840868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return needs_sync_map_.find(GetDirName(filename)) != needs_sync_map_.end();
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
843868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ChromiumEnv::DidSyncDir(const std::string& filename) {
844868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::AutoLock auto_lock(map_lock_);
845868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  needs_sync_map_.erase(GetDirName(filename));
84690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
84790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
84890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace leveldb_env
84990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
85090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace leveldb {
85190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Env* IDBEnv() {
85390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return leveldb_env::idb_env.Pointer();
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Env* Env::Default() {
85790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return leveldb_env::default_env.Pointer();
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace leveldb
861