| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_CHROMEOS_GDATA_GDATA_CACHE_H_ |
| #define CHROME_BROWSER_CHROMEOS_GDATA_GDATA_CACHE_H_ |
| #pragma once |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| |
| class Profile; |
| |
| namespace gdata { |
| |
| // GDataCache is used to maintain cache states of GDataFileSystem. |
| // |
| // All non-static public member functions, unless mentioned otherwise (see |
| // GetCacheFilePath() for example), should be called from the sequenced |
| // worker pool with the sequence token set by CreateGDataCache(). This |
| // threading model is enforced by AssertOnSequencedWorkerPool(). |
| class GDataCache { |
| public: |
| // Enum defining GCache subdirectory location. |
| // This indexes into |GDataCache::cache_paths_| vector. |
| enum CacheSubDirectoryType { |
| CACHE_TYPE_META = 0, // Downloaded feeds. |
| CACHE_TYPE_PINNED, // Symlinks to files in persistent dir that are |
| // pinned, or to /dev/null for non-existent |
| // files. |
| CACHE_TYPE_OUTGOING, // Symlinks to files in persistent or tmp dir to |
| // be uploaded. |
| CACHE_TYPE_PERSISTENT, // Files that are pinned or modified locally, |
| // not evictable, hopefully. |
| CACHE_TYPE_TMP, // Files that don't meet criteria to be in |
| // persistent dir, and hence evictable. |
| CACHE_TYPE_TMP_DOWNLOADS, // Downloaded files. |
| CACHE_TYPE_TMP_DOCUMENTS, // Temporary JSON files for hosted documents. |
| NUM_CACHE_TYPES, // This must be at the end. |
| }; |
| |
| // This is used as a bitmask for the cache state. |
| enum CacheState { |
| CACHE_STATE_NONE = 0x0, |
| CACHE_STATE_PINNED = 0x1 << 0, |
| CACHE_STATE_PRESENT = 0x1 << 1, |
| CACHE_STATE_DIRTY = 0x1 << 2, |
| CACHE_STATE_MOUNTED = 0x1 << 3, |
| }; |
| |
| // Enum defining origin of a cached file. |
| enum CachedFileOrigin { |
| CACHED_FILE_FROM_SERVER = 0, |
| CACHED_FILE_LOCALLY_MODIFIED, |
| CACHED_FILE_MOUNTED, |
| }; |
| |
| static const char kMountedArchiveFileExtension[]; |
| |
| // Structure to store information of an existing cache file. |
| struct CacheEntry { |
| CacheEntry(const std::string& md5, |
| CacheSubDirectoryType sub_dir_type, |
| int cache_state) |
| : md5(md5), |
| sub_dir_type(sub_dir_type), |
| cache_state(cache_state) { |
| } |
| |
| bool IsPresent() const { return IsCachePresent(cache_state); } |
| bool IsPinned() const { return IsCachePinned(cache_state); } |
| bool IsDirty() const { return IsCacheDirty(cache_state); } |
| bool IsMounted() const { return IsCacheMounted(cache_state); } |
| |
| // For debugging purposes. |
| std::string ToString() const; |
| |
| std::string md5; |
| CacheSubDirectoryType sub_dir_type; |
| int cache_state; |
| }; |
| |
| static bool IsCachePresent(int cache_state) { |
| return cache_state & CACHE_STATE_PRESENT; |
| } |
| static bool IsCachePinned(int cache_state) { |
| return cache_state & CACHE_STATE_PINNED; |
| } |
| static bool IsCacheDirty(int cache_state) { |
| return cache_state & CACHE_STATE_DIRTY; |
| } |
| static bool IsCacheMounted(int cache_state) { |
| return cache_state & CACHE_STATE_MOUNTED; |
| } |
| static int SetCachePresent(int cache_state) { |
| return cache_state |= CACHE_STATE_PRESENT; |
| } |
| static int SetCachePinned(int cache_state) { |
| return cache_state |= CACHE_STATE_PINNED; |
| } |
| static int SetCacheDirty(int cache_state) { |
| return cache_state |= CACHE_STATE_DIRTY; |
| } |
| static int SetCacheMounted(int cache_state) { |
| return cache_state |= CACHE_STATE_MOUNTED; |
| } |
| static int ClearCachePresent(int cache_state) { |
| return cache_state &= ~CACHE_STATE_PRESENT; |
| } |
| static int ClearCachePinned(int cache_state) { |
| return cache_state &= ~CACHE_STATE_PINNED; |
| } |
| static int ClearCacheDirty(int cache_state) { |
| return cache_state &= ~CACHE_STATE_DIRTY; |
| } |
| static int ClearCacheMounted(int cache_state) { |
| return cache_state &= ~CACHE_STATE_MOUNTED; |
| } |
| |
| // A map table of cache file's resource id to its CacheEntry* entry. |
| typedef std::map<std::string, CacheEntry> CacheMap; |
| |
| virtual ~GDataCache(); |
| |
| // Returns the sub-directory under gdata cache directory for the given sub |
| // directory type. Example: <user_profile_dir>/GCache/v1/tmp |
| // |
| // Can be called on any thread. |
| FilePath GetCacheDirectoryPath(CacheSubDirectoryType sub_dir_type) const; |
| |
| // Returns absolute path of the file if it were cached or to be cached. |
| // |
| // Can be called on any thread. |
| FilePath GetCacheFilePath(const std::string& resource_id, |
| const std::string& md5, |
| CacheSubDirectoryType sub_dir_type, |
| CachedFileOrigin file_orign) const; |
| |
| // Returns true if the given path is under gdata cache directory, i.e. |
| // <user_profile_dir>/GCache/v1 |
| // |
| // Can be called on any thread. |
| bool IsUnderGDataCacheDirectory(const FilePath& path) const; |
| |
| // TODO(hashimoto): Remove this method when crbug.com/131756 is fixed. |
| const std::vector<FilePath>& cache_paths() const { return cache_paths_; } |
| |
| // Sets |cache_map_| data member to formal parameter |new_cache_map|. |
| virtual void SetCacheMap(const CacheMap& new_cache_map) = 0; |
| |
| // Updates cache map with entry corresponding to |resource_id|. |
| // Creates new entry if it doesn't exist, otherwise update the entry. |
| virtual void UpdateCache(const std::string& resource_id, |
| const std::string& md5, |
| CacheSubDirectoryType subdir, |
| int cache_state) = 0; |
| |
| // Removes entry corresponding to |resource_id| from cache map. |
| virtual void RemoveFromCache(const std::string& resource_id) = 0; |
| |
| // Returns the cache entry for file corresponding to |resource_id| and |md5| |
| // if entry exists in cache map. Otherwise, returns NULL. |
| // |md5| can be empty if only matching |resource_id| is desired, which may |
| // happen when looking for pinned entries where symlinks' filenames have no |
| // extension and hence no md5. |
| virtual scoped_ptr<CacheEntry> GetCacheEntry(const std::string& resource_id, |
| const std::string& md5) = 0; |
| |
| // Removes temporary files (files in CACHE_TYPE_TMP) from the cache map. |
| virtual void RemoveTemporaryFiles() = 0; |
| |
| // Factory methods for GDataCache. |
| // |pool| and |sequence_token| are used to assert that the functions are |
| // called on the right sequenced worker pool with the right sequence token. |
| // |
| // For testing, the thread assertion can be disabled by passing NULL and |
| // the default value of SequenceToken. |
| static scoped_ptr<GDataCache> CreateGDataCache( |
| const FilePath& cache_root_path, |
| base::SequencedWorkerPool* pool, |
| const base::SequencedWorkerPool::SequenceToken& sequence_token); |
| |
| // Gets the cache root path (i.e. <user_profile_dir>/GCache/v1) from the |
| // profile. |
| // TODO(satorux): Write a unit test for this. |
| static FilePath GetCacheRootPath(Profile* profile); |
| |
| protected: |
| GDataCache( |
| const FilePath& cache_root_path, |
| base::SequencedWorkerPool* pool_, |
| const base::SequencedWorkerPool::SequenceToken& sequence_token); |
| |
| // Checks whether the current thread is on the right sequenced worker pool |
| // with the right sequence ID. If not, DCHECK will fail. |
| void AssertOnSequencedWorkerPool(); |
| |
| private: |
| // The root directory of the cache (i.e. <user_profile_dir>/GCache/v1). |
| const FilePath cache_root_path_; |
| // Paths for all subdirectories of GCache, one for each |
| // GDataCache::CacheSubDirectoryType enum. |
| const std::vector<FilePath> cache_paths_; |
| base::SequencedWorkerPool* pool_; |
| const base::SequencedWorkerPool::SequenceToken sequence_token_; |
| |
| DISALLOW_COPY_AND_ASSIGN(GDataCache); |
| }; |
| |
| } // namespace gdata |
| |
| #endif // CHROME_BROWSER_CHROMEOS_GDATA_GDATA_CACHE_H_ |