Home | History | Annotate | Download | only in leveldatabase
      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:
    159     bool Insert(const std::string& fname) {
    160       leveldb::MutexLock l(&mu_);
    161       return locked_files_.insert(fname).second;
    162     }
    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();
    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.
    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