• 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 
12 #include "base/metrics/histogram.h"
13 #include "base/platform_file.h"
14 #include "base/synchronization/condition_variable.h"
15 #include "leveldb/env.h"
16 #include "leveldb/slice.h"
17 #include "leveldb/status.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::PlatformFileError 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::PlatformFileError 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 ChromiumWritableFile : public leveldb::WritableFile {
105  public:
106   ChromiumWritableFile(const std::string& fname,
107                        FILE* f,
108                        const UMALogger* uma_logger,
109                        WriteTracker* tracker,
110                        bool make_backup);
111   virtual ~ChromiumWritableFile();
112   virtual leveldb::Status Append(const leveldb::Slice& data);
113   virtual leveldb::Status Close();
114   virtual leveldb::Status Flush();
115   virtual leveldb::Status Sync();
116 
117  private:
118   enum Type {
119     kManifest,
120     kTable,
121     kOther
122   };
123   leveldb::Status SyncParent();
124 
125   std::string filename_;
126   FILE* file_;
127   const UMALogger* uma_logger_;
128   WriteTracker* tracker_;
129   Type file_type_;
130   std::string parent_dir_;
131   bool make_backup_;
132 };
133 
134 class ChromiumEnv : public leveldb::Env,
135                     public UMALogger,
136                     public RetrierProvider,
137                     public WriteTracker {
138  public:
139   ChromiumEnv();
140   virtual ~ChromiumEnv();
141 
142   virtual leveldb::Status NewSequentialFile(const std::string& fname,
143                                             leveldb::SequentialFile** result);
144   virtual leveldb::Status NewRandomAccessFile(
145       const std::string& fname,
146       leveldb::RandomAccessFile** result);
147   virtual leveldb::Status NewWritableFile(const std::string& fname,
148                                           leveldb::WritableFile** result);
149   virtual bool FileExists(const std::string& fname);
150   virtual leveldb::Status GetChildren(const std::string& dir,
151                                       std::vector<std::string>* result);
152   virtual leveldb::Status DeleteFile(const std::string& fname);
153   virtual leveldb::Status CreateDir(const std::string& name);
154   virtual leveldb::Status DeleteDir(const std::string& name);
155   virtual leveldb::Status GetFileSize(const std::string& fname, uint64_t* size);
156   virtual leveldb::Status RenameFile(const std::string& src,
157                                      const std::string& dst);
158   virtual leveldb::Status LockFile(const std::string& fname,
159                                    leveldb::FileLock** lock);
160   virtual leveldb::Status UnlockFile(leveldb::FileLock* lock);
161   virtual void Schedule(void (*function)(void*), void* arg);
162   virtual void StartThread(void (*function)(void* arg), void* arg);
163   virtual leveldb::Status GetTestDirectory(std::string* path);
164   virtual leveldb::Status NewLogger(const std::string& fname,
165                                     leveldb::Logger** result);
166   virtual uint64_t NowMicros();
167   virtual void SleepForMicroseconds(int micros);
168 
169  protected:
170   virtual void DidCreateNewFile(const std::string& fname);
171   virtual bool DoesDirNeedSync(const std::string& fname);
172   virtual void DidSyncDir(const std::string& fname);
173 
174   std::string name_;
175   bool make_backup_;
176 
177  private:
178   // File locks may not be exclusive within a process (e.g. on POSIX). Track
179   // locks held by the ChromiumEnv to prevent access within the process.
180   class LockTable {
181    public:
Insert(const std::string & fname)182     bool Insert(const std::string& fname) {
183       leveldb::MutexLock l(&mu_);
184       return locked_files_.insert(fname).second;
185     }
Remove(const std::string & fname)186     bool Remove(const std::string& fname) {
187       leveldb::MutexLock l(&mu_);
188       return locked_files_.erase(fname) == 1;
189     }
190    private:
191     leveldb::port::Mutex mu_;
192     std::set<std::string> locked_files_;
193   };
194 
195   std::map<std::string, bool> needs_sync_map_;
196   base::Lock map_lock_;
197 
198   const int kMaxRetryTimeMillis;
199   // BGThread() is the body of the background thread
200   void BGThread();
BGThreadWrapper(void * arg)201   static void BGThreadWrapper(void* arg) {
202     reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
203   }
204 
205   virtual void RecordErrorAt(MethodID method) const;
206   virtual void RecordOSError(MethodID method, int saved_errno) const;
207   virtual void RecordOSError(MethodID method,
208                              base::PlatformFileError error) const;
209   virtual void RecordBackupResult(bool result) const;
210   void RestoreIfNecessary(const std::string& dir,
211                           std::vector<std::string>* children);
212   base::FilePath RestoreFromBackup(const base::FilePath& base_name);
213   void RecordOpenFilesLimit(const std::string& type);
214   void RecordLockFileAncestors(int num_missing_ancestors) const;
215   base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const;
216   base::HistogramBase* GetMethodIOErrorHistogram() const;
217   base::HistogramBase* GetMaxFDHistogram(const std::string& type) const;
218   base::HistogramBase* GetLockFileAncestorHistogram() const;
219 
220   // RetrierProvider implementation.
MaxRetryTimeMillis()221   virtual int MaxRetryTimeMillis() const { return kMaxRetryTimeMillis; }
222   virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const;
223   virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
224       MethodID method) const;
225 
226   base::FilePath test_directory_;
227 
228   ::base::Lock mu_;
229   ::base::ConditionVariable bgsignal_;
230   bool started_bgthread_;
231 
232   // Entry per Schedule() call
233   struct BGItem {
234     void* arg;
235     void (*function)(void*);
236   };
237   typedef std::deque<BGItem> BGQueue;
238   BGQueue queue_;
239   LockTable locks_;
240 };
241 
242 }  // namespace leveldb_env
243 
244 #endif
245