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