1 // Copyright (c) 2013 The LevelDB Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. See the AUTHORS file for names of contributors. 4 5 #ifndef THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_H_ 6 #define THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_H_ 7 8 #include <deque> 9 #include <map> 10 11 #include "base/metrics/histogram.h" 12 #include "base/platform_file.h" 13 #include "base/synchronization/condition_variable.h" 14 #include "leveldb/env.h" 15 #include "leveldb/slice.h" 16 #include "leveldb/status.h" 17 18 namespace leveldb_env { 19 20 enum MethodID { 21 kSequentialFileRead, 22 kSequentialFileSkip, 23 kRandomAccessFileRead, 24 kWritableFileAppend, 25 kWritableFileClose, 26 kWritableFileFlush, 27 kWritableFileSync, 28 kNewSequentialFile, 29 kNewRandomAccessFile, 30 kNewWritableFile, 31 kDeleteFile, 32 kCreateDir, 33 kDeleteDir, 34 kGetFileSize, 35 kRenameFile, 36 kLockFile, 37 kUnlockFile, 38 kGetTestDirectory, 39 kNewLogger, 40 kSyncParent, 41 kNumEntries 42 }; 43 44 const char* MethodIDToString(MethodID method); 45 46 leveldb::Status MakeIOError(leveldb::Slice filename, 47 const char* message, 48 MethodID method, 49 int saved_errno); 50 leveldb::Status MakeIOError(leveldb::Slice filename, 51 const char* message, 52 MethodID method, 53 base::PlatformFileError error); 54 leveldb::Status MakeIOError(leveldb::Slice filename, 55 const char* message, 56 MethodID method); 57 58 enum ErrorParsingResult { 59 METHOD_ONLY, 60 METHOD_AND_PFE, 61 METHOD_AND_ERRNO, 62 NONE, 63 }; 64 65 ErrorParsingResult ParseMethodAndError(const char* string, 66 MethodID* method, 67 int* error); 68 std::string FilePathToString(const base::FilePath& file_path); 69 70 class UMALogger { 71 public: 72 virtual void RecordErrorAt(MethodID method) const = 0; 73 virtual void RecordOSError(MethodID method, int saved_errno) const = 0; 74 virtual void RecordOSError(MethodID method, 75 base::PlatformFileError error) const = 0; 76 }; 77 78 class RetrierProvider { 79 public: 80 virtual int MaxRetryTimeMillis() const = 0; 81 virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const = 0; 82 virtual base::HistogramBase* GetRecoveredFromErrorHistogram( 83 MethodID method) const = 0; 84 }; 85 86 class WriteTracker { 87 public: 88 virtual void DidCreateNewFile(const std::string& fname) = 0; 89 virtual bool DoesDirNeedSync(const std::string& fname) = 0; 90 virtual void DidSyncDir(const std::string& fname) = 0; 91 }; 92 93 class ChromiumWritableFile : public leveldb::WritableFile { 94 public: 95 ChromiumWritableFile(const std::string& fname, 96 FILE* f, 97 const UMALogger* uma_logger, 98 WriteTracker* tracker); 99 virtual ~ChromiumWritableFile(); 100 virtual leveldb::Status Append(const leveldb::Slice& data); 101 virtual leveldb::Status Close(); 102 virtual leveldb::Status Flush(); 103 virtual leveldb::Status Sync(); 104 105 private: 106 leveldb::Status SyncParent(); 107 108 std::string filename_; 109 FILE* file_; 110 const UMALogger* uma_logger_; 111 WriteTracker* tracker_; 112 bool is_manifest_; 113 std::string parent_dir_; 114 }; 115 116 class ChromiumEnv : public leveldb::Env, 117 public UMALogger, 118 public RetrierProvider, 119 public WriteTracker { 120 public: 121 ChromiumEnv(); 122 virtual ~ChromiumEnv(); 123 124 virtual leveldb::Status NewSequentialFile(const std::string& fname, 125 leveldb::SequentialFile** result); 126 virtual leveldb::Status NewRandomAccessFile( 127 const std::string& fname, 128 leveldb::RandomAccessFile** result); 129 virtual leveldb::Status NewWritableFile(const std::string& fname, 130 leveldb::WritableFile** result); 131 virtual bool FileExists(const std::string& fname); 132 virtual leveldb::Status GetChildren(const std::string& dir, 133 std::vector<std::string>* result); 134 virtual leveldb::Status DeleteFile(const std::string& fname); 135 virtual leveldb::Status CreateDir(const std::string& name); 136 virtual leveldb::Status DeleteDir(const std::string& name); 137 virtual leveldb::Status GetFileSize(const std::string& fname, uint64_t* size); 138 virtual leveldb::Status RenameFile(const std::string& src, 139 const std::string& dst); 140 virtual leveldb::Status LockFile(const std::string& fname, 141 leveldb::FileLock** lock); 142 virtual leveldb::Status UnlockFile(leveldb::FileLock* lock); 143 virtual void Schedule(void (*function)(void*), void* arg); 144 virtual void StartThread(void (*function)(void* arg), void* arg); 145 virtual leveldb::Status GetTestDirectory(std::string* path); 146 virtual leveldb::Status NewLogger(const std::string& fname, 147 leveldb::Logger** result); 148 virtual uint64_t NowMicros(); 149 virtual void SleepForMicroseconds(int micros); 150 151 protected: 152 virtual void DidCreateNewFile(const std::string& fname); 153 virtual bool DoesDirNeedSync(const std::string& fname); 154 virtual void DidSyncDir(const std::string& fname); 155 156 std::string name_; 157 158 private: 159 std::map<std::string, bool> needs_sync_map_; 160 base::Lock map_lock_; 161 162 const int kMaxRetryTimeMillis; 163 // BGThread() is the body of the background thread 164 void BGThread(); 165 static void BGThreadWrapper(void* arg) { 166 reinterpret_cast<ChromiumEnv*>(arg)->BGThread(); 167 } 168 169 virtual void RecordErrorAt(MethodID method) const; 170 virtual void RecordOSError(MethodID method, int saved_errno) const; 171 virtual void RecordOSError(MethodID method, 172 base::PlatformFileError error) const; 173 void RecordOpenFilesLimit(const std::string& type); 174 void RecordLockFileAncestors(int num_missing_ancestors) const; 175 base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const; 176 base::HistogramBase* GetMethodIOErrorHistogram() const; 177 base::HistogramBase* GetMaxFDHistogram(const std::string& type) const; 178 base::HistogramBase* GetLockFileAncestorHistogram() const; 179 180 // RetrierProvider implementation. 181 virtual int MaxRetryTimeMillis() const { return kMaxRetryTimeMillis; } 182 virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const; 183 virtual base::HistogramBase* GetRecoveredFromErrorHistogram( 184 MethodID method) const; 185 186 base::FilePath test_directory_; 187 188 ::base::Lock mu_; 189 ::base::ConditionVariable bgsignal_; 190 bool started_bgthread_; 191 192 // Entry per Schedule() call 193 struct BGItem { 194 void* arg; 195 void (*function)(void*); 196 }; 197 typedef std::deque<BGItem> BGQueue; 198 BGQueue queue_; 199 }; 200 201 } // namespace leveldb_env 202 203 #endif 204