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 
     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:
    154     bool Insert(const std::string& fname) {
    155       leveldb::MutexLock l(&mu_);
    156       return locked_files_.insert(fname).second;
    157     }
    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();
    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.
    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