• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <set>
11 #include <string>
12 #include <vector>
13 
14 #include "base/files/file.h"
15 #include "base/files/file_path.h"
16 #include "base/metrics/histogram.h"
17 #include "leveldb/env.h"
18 #include "port/port_chromium.h"
19 #include "util/mutexlock.h"
20 
21 namespace leveldb_env {
22 
23 enum MethodID {
24   kSequentialFileRead,
25   kSequentialFileSkip,
26   kRandomAccessFileRead,
27   kWritableFileAppend,
28   kWritableFileClose,
29   kWritableFileFlush,
30   kWritableFileSync,
31   kNewSequentialFile,
32   kNewRandomAccessFile,
33   kNewWritableFile,
34   kDeleteFile,
35   kCreateDir,
36   kDeleteDir,
37   kGetFileSize,
38   kRenameFile,
39   kLockFile,
40   kUnlockFile,
41   kGetTestDirectory,
42   kNewLogger,
43   kSyncParent,
44   kGetChildren,
45   kNumEntries
46 };
47 
48 const char* MethodIDToString(MethodID method);
49 
50 leveldb::Status MakeIOError(leveldb::Slice filename,
51                             const char* message,
52                             MethodID method,
53                             int saved_errno);
54 leveldb::Status MakeIOError(leveldb::Slice filename,
55                             const char* message,
56                             MethodID method,
57                             base::File::Error error);
58 leveldb::Status MakeIOError(leveldb::Slice filename,
59                             const char* message,
60                             MethodID method);
61 
62 enum ErrorParsingResult {
63   METHOD_ONLY,
64   METHOD_AND_PFE,
65   METHOD_AND_ERRNO,
66   NONE,
67 };
68 
69 ErrorParsingResult ParseMethodAndError(const char* string,
70                                        MethodID* method,
71                                        int* error);
72 int GetCorruptionCode(const leveldb::Status& status);
73 int GetNumCorruptionCodes();
74 std::string GetCorruptionMessage(const leveldb::Status& status);
75 bool IndicatesDiskFull(const leveldb::Status& status);
76 bool IsIOError(const leveldb::Status& status);
77 bool IsCorruption(const leveldb::Status& status);
78 std::string FilePathToString(const base::FilePath& file_path);
79 
80 class UMALogger {
81  public:
82   virtual void RecordErrorAt(MethodID method) const = 0;
83   virtual void RecordOSError(MethodID method, int saved_errno) const = 0;
84   virtual void RecordOSError(MethodID method,
85                              base::File::Error error) const = 0;
86   virtual void RecordBackupResult(bool success) const = 0;
87 };
88 
89 class RetrierProvider {
90  public:
91   virtual int MaxRetryTimeMillis() const = 0;
92   virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const = 0;
93   virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
94       MethodID method) const = 0;
95 };
96 
97 class WriteTracker {
98  public:
99   virtual void DidCreateNewFile(const std::string& fname) = 0;
100   virtual bool DoesDirNeedSync(const std::string& fname) = 0;
101   virtual void DidSyncDir(const std::string& fname) = 0;
102 };
103 
104 class ChromiumEnv : public leveldb::Env,
105                     public UMALogger,
106                     public RetrierProvider,
107                     public WriteTracker {
108  public:
109   typedef void(ScheduleFunc)(void*);
110 
111   static bool MakeBackup(const std::string& fname);
112   static base::FilePath CreateFilePath(const std::string& file_path);
113   static const char* FileErrorString(::base::File::Error error);
114   static bool HasTableExtension(const base::FilePath& path);
115   virtual ~ChromiumEnv();
116 
117   virtual bool FileExists(const std::string& fname);
118   virtual leveldb::Status GetChildren(const std::string& dir,
119                                       std::vector<std::string>* result);
120   virtual leveldb::Status DeleteFile(const std::string& fname);
121   virtual leveldb::Status CreateDir(const std::string& name);
122   virtual leveldb::Status DeleteDir(const std::string& name);
123   virtual leveldb::Status GetFileSize(const std::string& fname, uint64_t* size);
124   virtual leveldb::Status RenameFile(const std::string& src,
125                                      const std::string& dst);
126   virtual leveldb::Status LockFile(const std::string& fname,
127                                    leveldb::FileLock** lock);
128   virtual leveldb::Status UnlockFile(leveldb::FileLock* lock);
129   virtual void Schedule(ScheduleFunc*, void* arg);
130   virtual void StartThread(void (*function)(void* arg), void* arg);
131   virtual leveldb::Status GetTestDirectory(std::string* path);
132   virtual uint64_t NowMicros();
133   virtual void SleepForMicroseconds(int micros);
134 
135  protected:
136   ChromiumEnv();
137 
138   virtual void DidCreateNewFile(const std::string& fname);
139   virtual bool DoesDirNeedSync(const std::string& fname);
140   virtual void DidSyncDir(const std::string& fname);
141   virtual base::File::Error GetDirectoryEntries(
142       const base::FilePath& dir_param,
143       std::vector<base::FilePath>* result) const = 0;
144   virtual void RecordErrorAt(MethodID method) const;
145   virtual void RecordOSError(MethodID method, int saved_errno) const;
146   virtual void RecordOSError(MethodID method,
147                              base::File::Error error) const;
148   base::HistogramBase* GetMaxFDHistogram(const std::string& type) const;
149   base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const;
150 
151   std::string name_;
152   bool make_backup_;
153 
154  private:
155   // File locks may not be exclusive within a process (e.g. on POSIX). Track
156   // locks held by the ChromiumEnv to prevent access within the process.
157   class LockTable {
158    public:
Insert(const std::string & fname)159     bool Insert(const std::string& fname) {
160       leveldb::MutexLock l(&mu_);
161       return locked_files_.insert(fname).second;
162     }
Remove(const std::string & fname)163     bool Remove(const std::string& fname) {
164       leveldb::MutexLock l(&mu_);
165       return locked_files_.erase(fname) == 1;
166     }
167    private:
168     leveldb::port::Mutex mu_;
169     std::set<std::string> locked_files_;
170   };
171 
172   std::map<std::string, bool> needs_sync_map_;
173   base::Lock map_lock_;
174 
175   const int kMaxRetryTimeMillis;
176   // BGThread() is the body of the background thread
177   void BGThread();
BGThreadWrapper(void * arg)178   static void BGThreadWrapper(void* arg) {
179     reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
180   }
181 
182   virtual void RecordBackupResult(bool result) const;
183   void RestoreIfNecessary(const std::string& dir,
184                           std::vector<std::string>* children);
185   base::FilePath RestoreFromBackup(const base::FilePath& base_name);
186   void RecordLockFileAncestors(int num_missing_ancestors) const;
187   base::HistogramBase* GetMethodIOErrorHistogram() const;
188   base::HistogramBase* GetLockFileAncestorHistogram() const;
189 
190   // RetrierProvider implementation.
MaxRetryTimeMillis()191   virtual int MaxRetryTimeMillis() const { return kMaxRetryTimeMillis; }
192   virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const;
193   virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
194       MethodID method) const;
195 
196   base::FilePath test_directory_;
197 
198   ::base::Lock mu_;
199   ::base::ConditionVariable bgsignal_;
200   bool started_bgthread_;
201 
202   // Entry per Schedule() call
203   struct BGItem {
204     void* arg;
205     void (*function)(void*);
206   };
207   typedef std::deque<BGItem> BGQueue;
208   BGQueue queue_;
209   LockTable locks_;
210 };
211 
212 }  // namespace leveldb_env
213 
214 #endif  // THIRD_PARTY_LEVELDATABASE_ENV_CHROMIUM_H_
215