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 
     11 #include "base/metrics/histogram.h"
     12 #include "base/platform_file.h"
     13 #include "base/synchronization/condition_variable.h"
     14 #include "leveldb/env.h"
     15 #include "leveldb/slice.h"
     16 #include "leveldb/status.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   kNumEntries
     42 };
     43 
     44 const char* MethodIDToString(MethodID method);
     45 
     46 leveldb::Status MakeIOError(leveldb::Slice filename,
     47                             const char* message,
     48                             MethodID method,
     49                             int saved_errno);
     50 leveldb::Status MakeIOError(leveldb::Slice filename,
     51                             const char* message,
     52                             MethodID method,
     53                             base::PlatformFileError error);
     54 leveldb::Status MakeIOError(leveldb::Slice filename,
     55                             const char* message,
     56                             MethodID method);
     57 
     58 enum ErrorParsingResult {
     59   METHOD_ONLY,
     60   METHOD_AND_PFE,
     61   METHOD_AND_ERRNO,
     62   NONE,
     63 };
     64 
     65 ErrorParsingResult ParseMethodAndError(const char* string,
     66                                        MethodID* method,
     67                                        int* error);
     68 std::string FilePathToString(const base::FilePath& file_path);
     69 
     70 class UMALogger {
     71  public:
     72   virtual void RecordErrorAt(MethodID method) const = 0;
     73   virtual void RecordOSError(MethodID method, int saved_errno) const = 0;
     74   virtual void RecordOSError(MethodID method,
     75                              base::PlatformFileError error) const = 0;
     76 };
     77 
     78 class RetrierProvider {
     79  public:
     80   virtual int MaxRetryTimeMillis() const = 0;
     81   virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const = 0;
     82   virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
     83       MethodID method) const = 0;
     84 };
     85 
     86 class WriteTracker {
     87  public:
     88   virtual void DidCreateNewFile(const std::string& fname) = 0;
     89   virtual bool DoesDirNeedSync(const std::string& fname) = 0;
     90   virtual void DidSyncDir(const std::string& fname) = 0;
     91 };
     92 
     93 class ChromiumWritableFile : public leveldb::WritableFile {
     94  public:
     95   ChromiumWritableFile(const std::string& fname,
     96                        FILE* f,
     97                        const UMALogger* uma_logger,
     98                        WriteTracker* tracker);
     99   virtual ~ChromiumWritableFile();
    100   virtual leveldb::Status Append(const leveldb::Slice& data);
    101   virtual leveldb::Status Close();
    102   virtual leveldb::Status Flush();
    103   virtual leveldb::Status Sync();
    104 
    105  private:
    106   leveldb::Status SyncParent();
    107 
    108   std::string filename_;
    109   FILE* file_;
    110   const UMALogger* uma_logger_;
    111   WriteTracker* tracker_;
    112   bool is_manifest_;
    113   std::string parent_dir_;
    114 };
    115 
    116 class ChromiumEnv : public leveldb::Env,
    117                     public UMALogger,
    118                     public RetrierProvider,
    119                     public WriteTracker {
    120  public:
    121   ChromiumEnv();
    122   virtual ~ChromiumEnv();
    123 
    124   virtual leveldb::Status NewSequentialFile(const std::string& fname,
    125                                             leveldb::SequentialFile** result);
    126   virtual leveldb::Status NewRandomAccessFile(
    127       const std::string& fname,
    128       leveldb::RandomAccessFile** result);
    129   virtual leveldb::Status NewWritableFile(const std::string& fname,
    130                                           leveldb::WritableFile** result);
    131   virtual bool FileExists(const std::string& fname);
    132   virtual leveldb::Status GetChildren(const std::string& dir,
    133                                       std::vector<std::string>* result);
    134   virtual leveldb::Status DeleteFile(const std::string& fname);
    135   virtual leveldb::Status CreateDir(const std::string& name);
    136   virtual leveldb::Status DeleteDir(const std::string& name);
    137   virtual leveldb::Status GetFileSize(const std::string& fname, uint64_t* size);
    138   virtual leveldb::Status RenameFile(const std::string& src,
    139                                      const std::string& dst);
    140   virtual leveldb::Status LockFile(const std::string& fname,
    141                                    leveldb::FileLock** lock);
    142   virtual leveldb::Status UnlockFile(leveldb::FileLock* lock);
    143   virtual void Schedule(void (*function)(void*), void* arg);
    144   virtual void StartThread(void (*function)(void* arg), void* arg);
    145   virtual leveldb::Status GetTestDirectory(std::string* path);
    146   virtual leveldb::Status NewLogger(const std::string& fname,
    147                                     leveldb::Logger** result);
    148   virtual uint64_t NowMicros();
    149   virtual void SleepForMicroseconds(int micros);
    150 
    151  protected:
    152   virtual void DidCreateNewFile(const std::string& fname);
    153   virtual bool DoesDirNeedSync(const std::string& fname);
    154   virtual void DidSyncDir(const std::string& fname);
    155 
    156   std::string name_;
    157 
    158  private:
    159   std::map<std::string, bool> needs_sync_map_;
    160   base::Lock map_lock_;
    161 
    162   const int kMaxRetryTimeMillis;
    163   // BGThread() is the body of the background thread
    164   void BGThread();
    165   static void BGThreadWrapper(void* arg) {
    166     reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
    167   }
    168 
    169   virtual void RecordErrorAt(MethodID method) const;
    170   virtual void RecordOSError(MethodID method, int saved_errno) const;
    171   virtual void RecordOSError(MethodID method,
    172                              base::PlatformFileError error) const;
    173   void RecordOpenFilesLimit(const std::string& type);
    174   void RecordLockFileAncestors(int num_missing_ancestors) const;
    175   base::HistogramBase* GetOSErrorHistogram(MethodID method, int limit) const;
    176   base::HistogramBase* GetMethodIOErrorHistogram() const;
    177   base::HistogramBase* GetMaxFDHistogram(const std::string& type) const;
    178   base::HistogramBase* GetLockFileAncestorHistogram() const;
    179 
    180   // RetrierProvider implementation.
    181   virtual int MaxRetryTimeMillis() const { return kMaxRetryTimeMillis; }
    182   virtual base::HistogramBase* GetRetryTimeHistogram(MethodID method) const;
    183   virtual base::HistogramBase* GetRecoveredFromErrorHistogram(
    184       MethodID method) const;
    185 
    186   base::FilePath test_directory_;
    187 
    188   ::base::Lock mu_;
    189   ::base::ConditionVariable bgsignal_;
    190   bool started_bgthread_;
    191 
    192   // Entry per Schedule() call
    193   struct BGItem {
    194     void* arg;
    195     void (*function)(void*);
    196   };
    197   typedef std::deque<BGItem> BGQueue;
    198   BGQueue queue_;
    199 };
    200 
    201 }  // namespace leveldb_env
    202 
    203 #endif
    204