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