15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_errors.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ScopedClosureRunner;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SequencedTaskRunner;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace internal {
25b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Interface class used for getting the free disk space. Tests can inject an
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// implementation that reports fake free disk space.
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class FreeDiskSpaceGetterInterface {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~FreeDiskSpaceGetterInterface() {}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int64 AmountOfFreeDiskSpace() = 0;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// FileCache is used to maintain cache states of FileSystem.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All non-static public member functions, unless mentioned otherwise (see
37b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// GetCacheFilePath() for example), should be run with |blocking_task_runner|.
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class FileCache {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Enum defining type of file operation e.g. copy or move, etc.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum FileOperationType {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_OPERATION_MOVE = 0,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FILE_OPERATION_COPY,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // |cache_file_directory| stores cached files.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // |blocking_task_runner| indicates the blocking worker pool for cache
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // operations. All operations on this FileCache must be run on this runner.
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Must not be null.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |free_disk_space_getter| is used to inject a custom free disk space
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // getter for testing. NULL must be passed for production code.
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  //
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Must be called on the UI thread.
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  FileCache(ResourceMetadataStorage* storage,
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            const base::FilePath& cache_file_directory,
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            base::SequencedTaskRunner* blocking_task_runner,
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            FreeDiskSpaceGetterInterface* free_disk_space_getter);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the given path is under drive cache directory, i.e.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // <user_profile_dir>/GCache/v1
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Can be called on any thread.
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool IsUnderFileCacheDirectory(const base::FilePath& path) const;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Frees up disk space to store a file with |num_bytes| size content, while
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // keeping cryptohome::kMinFreeSpaceInBytes bytes on the disk, if needed.
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Returns true if we successfully manage to have enough space, otherwise
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // false.
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool FreeDiskSpaceIfNeededFor(int64 num_bytes);
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Checks if file corresponding to |id| exists in cache, and returns
7458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // FILE_ERROR_OK with |cache_file_path| storing the path to the file.
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // |cache_file_path| must not be null.
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError GetFile(const std::string& id, base::FilePath* cache_file_path);
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Stores |source_path| as a cache of the remote content of the file
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // with |id| and |md5|.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Pass an empty string as MD5 to mark the entry as dirty.
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError Store(const std::string& id,
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  const std::string& md5,
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  const base::FilePath& source_path,
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  FileOperationType file_operation_type);
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Pins the specified entry.
87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError Pin(const std::string& id);
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Unpins the specified entry.
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError Unpin(const std::string& id);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Sets the state of the cache entry corresponding to |id| as mounted.
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError MarkAsMounted(const std::string& id,
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          base::FilePath* cache_file_path);
95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Sets the state of the cache entry corresponding to file_path as unmounted.
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  FileError MarkAsUnmounted(const base::FilePath& file_path);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Opens the cache file corresponding to |id| for write. |file_closer| should
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // be kept alive until writing finishes.
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This method must be called before writing to cache files.
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError OpenForWrite(const std::string& id,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         scoped_ptr<base::ScopedClosureRunner>* file_closer);
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Returns true if the cache file corresponding to |id| is write-opened.
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool IsOpenedForWrite(const std::string& id);
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Calculates MD5 of the cache file and updates the stored value.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError UpdateMd5(const std::string& id);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Clears dirty state of the specified entry.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  FileError ClearDirty(const std::string& id);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Removes the specified cache entry and delete cache files if available.
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FileError Remove(const std::string& id);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Removes all the files in the cache directory.
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  bool ClearAll();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Initializes the cache. Returns true on success.
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool Initialize();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Destroys this cache. This function posts a task to the blocking task
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // runner to safely delete the object.
125b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Must be called on the UI thread.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Destroy();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Moves files in the cache directory which are not managed by FileCache to
1290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // |dest_directory|.
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // |recovered_cache_info| should contain cache info recovered from the trashed
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // metadata DB. It is used to ignore non-dirty files.
1320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  bool RecoverFilesFromCacheDirectory(
1330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      const base::FilePath& dest_directory,
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const ResourceMetadataStorage::RecoveredCacheInfoMap&
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          recovered_cache_info);
1360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  friend class FileCacheTest;
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  ~FileCache();
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns absolute path of the file if it were cached or to be cached.
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Can be called on any thread.
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  base::FilePath GetCacheFilePath(const std::string& id) const;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks whether the current thread is on the right sequenced worker pool
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the right sequence ID. If not, DCHECK will fail.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AssertOnSequencedWorkerPool();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Destroys the cache on the blocking pool.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DestroyOnBlockingPool();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returns true if we have sufficient space to store the given number of
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // bytes, while keeping cryptohome::kMinFreeSpaceInBytes bytes on the disk.
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool HasEnoughSpaceFor(int64 num_bytes, const base::FilePath& path);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Renames cache files from old "prefix:id.md5" format to the new format.
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // TODO(hashimoto): Remove this method at some point.
1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  bool RenameCacheFilesToNewFormat();
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This method must be called after writing to a cache file.
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Used to implement OpenForWrite().
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CloseForWrite(const std::string& id);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::FilePath cache_file_directory_;
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ResourceMetadataStorage* storage_;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FreeDiskSpaceGetterInterface* free_disk_space_getter_;  // Not owned.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // IDs of files being write-opened.
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::map<std::string, int> write_opened_files_;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // IDs of files marked mounted.
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::set<std::string> mounted_files_;
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This object should be accessed only on |blocking_task_runner_|.
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::WeakPtrFactory<FileCache> weak_ptr_factory_;
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FileCache);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace internal
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace drive
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_FILE_CACHE_H_
191