Home | History | Annotate | Download | only in drive
      1 // Copyright (c) 2012 The Chromium 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.
      4 
      5 #ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
      6 #define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
      7 
      8 #include <set>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/callback_forward.h"
     13 #include "base/files/file_path.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "base/memory/weak_ptr.h"
     16 #include "chrome/browser/chromeos/drive/file_errors.h"
     17 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
     18 
     19 namespace base {
     20 class SequencedTaskRunner;
     21 }  // namespace base
     22 
     23 namespace drive {
     24 
     25 class FileCacheEntry;
     26 
     27 // Callback for GetCacheEntry.
     28 // |success| indicates if the operation was successful.
     29 // |cache_entry| is the obtained cache entry. On failure, |cache_state| is
     30 // set to TEST_CACHE_STATE_NONE.
     31 typedef base::Callback<void(bool success, const FileCacheEntry& cache_entry)>
     32     GetCacheEntryCallback;
     33 
     34 // Callback for Iterate().
     35 typedef base::Callback<void(const std::string& resource_id,
     36                             const FileCacheEntry& cache_entry)>
     37     CacheIterateCallback;
     38 
     39 namespace internal {
     40 
     41 // Callback for GetFileFromCache.
     42 typedef base::Callback<void(FileError error,
     43                             const base::FilePath& cache_file_path)>
     44     GetFileFromCacheCallback;
     45 
     46 // Callback for ClearAllOnUIThread.
     47 // |success| indicates if the operation was successful.
     48 // TODO(satorux): Change this to FileError when it becomes necessary.
     49 typedef base::Callback<void(bool success)> ClearAllCallback;
     50 
     51 // Interface class used for getting the free disk space. Tests can inject an
     52 // implementation that reports fake free disk space.
     53 class FreeDiskSpaceGetterInterface {
     54  public:
     55   virtual ~FreeDiskSpaceGetterInterface() {}
     56   virtual int64 AmountOfFreeDiskSpace() = 0;
     57 };
     58 
     59 // FileCache is used to maintain cache states of FileSystem.
     60 //
     61 // All non-static public member functions, unless mentioned otherwise (see
     62 // GetCacheFilePath() for example), should be run with |blocking_task_runner|.
     63 class FileCache {
     64  public:
     65   // Enum defining type of file operation e.g. copy or move, etc.
     66   enum FileOperationType {
     67     FILE_OPERATION_MOVE = 0,
     68     FILE_OPERATION_COPY,
     69   };
     70 
     71   typedef ResourceMetadataStorage::CacheEntryIterator Iterator;
     72 
     73   // Name of the cache metadata DB previously used.
     74   // TODO(hashimoto): Remove this at some point.
     75   static const base::FilePath::CharType kOldCacheMetadataDBName[];
     76 
     77   // |cache_file_directory| stores cached files.
     78   //
     79   // |blocking_task_runner| is used to post a task to the blocking worker
     80   // pool for file operations. Must not be null.
     81   //
     82   // |free_disk_space_getter| is used to inject a custom free disk space
     83   // getter for testing. NULL must be passed for production code.
     84   //
     85   // Must be called on the UI thread.
     86   FileCache(ResourceMetadataStorage* storage,
     87             const base::FilePath& cache_file_directory,
     88             base::SequencedTaskRunner* blocking_task_runner,
     89             FreeDiskSpaceGetterInterface* free_disk_space_getter);
     90 
     91   // Returns true if the given path is under drive cache directory, i.e.
     92   // <user_profile_dir>/GCache/v1
     93   //
     94   // Can be called on any thread.
     95   bool IsUnderFileCacheDirectory(const base::FilePath& path) const;
     96 
     97   // Gets the cache entry for file corresponding to |resource_id| and runs
     98   // |callback| with true and the entry found if entry exists in cache map.
     99   // Otherwise, runs |callback| with false.
    100   // |callback| must not be null.
    101   // Must be called on the UI thread.
    102   void GetCacheEntryOnUIThread(const std::string& resource_id,
    103                                const GetCacheEntryCallback& callback);
    104 
    105   // Gets the cache entry by the given resource ID.
    106   // See also GetCacheEntryOnUIThread().
    107   bool GetCacheEntry(const std::string& resource_id,
    108                      FileCacheEntry* entry);
    109 
    110   // Runs Iterate() with |iteration_callback| on |blocking_task_runner_| and
    111   // runs |completion_callback| upon completion.
    112   // Must be called on UI thread.
    113   void IterateOnUIThread(const CacheIterateCallback& iteration_callback,
    114                          const base::Closure& completion_callback);
    115 
    116   // Returns an object to iterate over entries.
    117   scoped_ptr<Iterator> GetIterator();
    118 
    119   // Frees up disk space to store a file with |num_bytes| size content, while
    120   // keeping kMinFreeSpace bytes on the disk, if needed.
    121   // Returns true if we successfully manage to have enough space, otherwise
    122   // false.
    123   bool FreeDiskSpaceIfNeededFor(int64 num_bytes);
    124 
    125   // Runs GetFile() on |blocking_task_runner_|, and calls |callback| with
    126   // the result asynchronously.
    127   // |callback| must not be null.
    128   // Must be called on the UI thread.
    129   void GetFileOnUIThread(const std::string& resource_id,
    130                          const GetFileFromCacheCallback& callback);
    131 
    132   // Checks if file corresponding to |resource_id| exists in cache, and returns
    133   // FILE_ERROR_OK with |cache_file_path| storing the path to the file.
    134   // |cache_file_path| must not be null.
    135   FileError GetFile(const std::string& resource_id,
    136                     base::FilePath* cache_file_path);
    137 
    138   // Runs Store() on |blocking_task_runner_|, and calls |callback| with
    139   // the result asynchronously.
    140   // |callback| must not be null.
    141   // Must be called on the UI thread.
    142   void StoreOnUIThread(const std::string& resource_id,
    143                        const std::string& md5,
    144                        const base::FilePath& source_path,
    145                        FileOperationType file_operation_type,
    146                        const FileOperationCallback& callback);
    147 
    148   // Stores |source_path| as a cache of the remote content of the file
    149   // with |resource_id| and |md5|.
    150   FileError Store(const std::string& resource_Id,
    151                   const std::string& md5,
    152                   const base::FilePath& source_path,
    153                   FileOperationType file_operation_type);
    154 
    155   // Runs Pin() on |blocking_task_runner_|, and calls |callback| with the result
    156   // asynchronously.
    157   // |callback| must not be null.
    158   // Must be called on the UI thread.
    159   void PinOnUIThread(const std::string& resource_id,
    160                      const FileOperationCallback& callback);
    161 
    162   // Pins the specified entry.
    163   FileError Pin(const std::string& resource_id);
    164 
    165   // Runs Unpin() on |blocking_task_runner_|, and calls |callback| with the
    166   // result asynchronously.
    167   // |callback| must not be null.
    168   // Must be called on the UI thread.
    169   void UnpinOnUIThread(const std::string& resource_id,
    170                        const FileOperationCallback& callback);
    171 
    172   // Unpins the specified entry.
    173   FileError Unpin(const std::string& resource_id);
    174 
    175   // Sets the state of the cache entry corresponding to |resource_id| as
    176   // mounted.
    177   // |callback| must not be null.
    178   // Must be called on the UI thread.
    179   void MarkAsMountedOnUIThread(const std::string& resource_id,
    180                                const GetFileFromCacheCallback& callback);
    181 
    182   // Set the state of the cache entry corresponding to file_path as unmounted.
    183   // |callback| must not be null.
    184   // Must be called on the UI thread.
    185   void MarkAsUnmountedOnUIThread(const base::FilePath& file_path,
    186                                  const FileOperationCallback& callback);
    187 
    188   // Runs MarkDirty() on |blocking_task_runner_|, and calls |callback| with the
    189   // result asynchronously.
    190   // |callback| must not be null.
    191   // Must be called on the UI thread.
    192   void MarkDirtyOnUIThread(const std::string& resource_id,
    193                            const FileOperationCallback& callback);
    194 
    195   // Marks the specified entry dirty.
    196   FileError MarkDirty(const std::string& resource_id);
    197 
    198   // Clears dirty state of the specified entry and updates its MD5.
    199   FileError ClearDirty(const std::string& resource_id,
    200                        const std::string& md5);
    201 
    202   // Runs Remove() on |blocking_task_runner_| and runs |callback| with the
    203   // result.
    204   // Must be called on the UI thread.
    205   void RemoveOnUIThread(const std::string& resource_id,
    206                         const FileOperationCallback& callback);
    207 
    208   // Removes the specified cache entry and delete cache files if available.
    209   // Synchronous version of RemoveOnUIThread().
    210   FileError Remove(const std::string& resource_id);
    211 
    212   // Does the following:
    213   // - remove all the files in the cache directory.
    214   // - re-create the |metadata_| instance.
    215   // |callback| must not be null.
    216   // Must be called on the UI thread.
    217   void ClearAllOnUIThread(const ClearAllCallback& callback);
    218 
    219   // Initializes the cache. Returns true on success.
    220   bool Initialize();
    221 
    222   // Destroys this cache. This function posts a task to the blocking task
    223   // runner to safely delete the object.
    224   // Must be called on the UI thread.
    225   void Destroy();
    226 
    227  private:
    228   friend class FileCacheTest;
    229   friend class FileCacheTestOnUIThread;
    230 
    231   ~FileCache();
    232 
    233   // Returns absolute path of the file if it were cached or to be cached.
    234   //
    235   // Can be called on any thread.
    236   base::FilePath GetCacheFilePath(const std::string& resource_id) const;
    237 
    238   // Checks whether the current thread is on the right sequenced worker pool
    239   // with the right sequence ID. If not, DCHECK will fail.
    240   void AssertOnSequencedWorkerPool();
    241 
    242   // Destroys the cache on the blocking pool.
    243   void DestroyOnBlockingPool();
    244 
    245   // Used to implement Store and StoreLocallyModifiedOnUIThread.
    246   // TODO(hidehiko): Merge this method with Store(), after
    247   // StoreLocallyModifiedOnUIThread is removed.
    248   FileError StoreInternal(const std::string& resource_id,
    249                           const std::string& md5,
    250                           const base::FilePath& source_path,
    251                           FileOperationType file_operation_type);
    252 
    253   // Used to implement MarkAsMountedOnUIThread.
    254   FileError MarkAsMounted(const std::string& resource_id,
    255                           base::FilePath* cache_file_path);
    256 
    257   // Used to implement MarkAsUnmountedOnUIThread.
    258   FileError MarkAsUnmounted(const base::FilePath& file_path);
    259 
    260   // Used to implement ClearAllOnUIThread.
    261   bool ClearAll();
    262 
    263   // Returns true if we have sufficient space to store the given number of
    264   // bytes, while keeping kMinFreeSpace bytes on the disk.
    265   bool HasEnoughSpaceFor(int64 num_bytes, const base::FilePath& path);
    266 
    267   // Imports old format DB from |old_db_path| and deletes it.
    268   // TODO(hashimoto): Remove this method and FileCacheMetadata at some point.
    269   bool ImportOldDB(const base::FilePath& old_db_path);
    270 
    271   // Renames cache files from old "resource_id.md5" format to the new format.
    272   // TODO(hashimoto): Remove this method at some point.
    273   void RenameCacheFilesToNewFormat();
    274 
    275   const base::FilePath cache_file_directory_;
    276 
    277   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
    278 
    279   ResourceMetadataStorage* storage_;
    280 
    281   FreeDiskSpaceGetterInterface* free_disk_space_getter_;  // Not owned.
    282 
    283   // Resource IDs of files marked mounted.
    284   std::set<std::string> mounted_files_;
    285 
    286   // Note: This should remain the last member so it'll be destroyed and
    287   // invalidate its weak pointers before any other members are destroyed.
    288   base::WeakPtrFactory<FileCache> weak_ptr_factory_;
    289   DISALLOW_COPY_AND_ASSIGN(FileCache);
    290 };
    291 
    292 // The minimum free space to keep. Operations that add cache files return
    293 // FILE_ERROR_NO_LOCAL_SPACE if the available space is smaller than
    294 // this value.
    295 //
    296 // Copied from cryptohome/homedirs.h.
    297 // TODO(satorux): Share the constant.
    298 const int64 kMinFreeSpace = 512 * 1LL << 20;
    299 
    300 }  // namespace internal
    301 }  // namespace drive
    302 
    303 #endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
    304