1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_CONTENT_CACHE_CONTENT_CACHE_IMPL_H_
#define CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_CONTENT_CACHE_CONTENT_CACHE_IMPL_H_
#include "base/callback_list.h"
#include "base/files/file_error_or.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/sequence_bound.h"
#include "chrome/browser/ash/file_system_provider/content_cache/content_cache.h"
#include "chrome/browser/ash/file_system_provider/content_cache/content_lru_cache.h"
#include "chrome/browser/ash/file_system_provider/content_cache/context_database.h"
#include "chrome/browser/ash/file_system_provider/content_cache/local_fd.h"
#include "chrome/browser/ash/file_system_provider/opened_cloud_file.h"
#include "chrome/browser/ash/file_system_provider/provided_file_system_interface.h"
namespace ash::file_system_provider {
// The content cache for every mounted FSP. This will serve as the single point
// of orchestration between the LRU cache and the disk persistence layer.
class ContentCacheImpl : public ContentCache {
public:
ContentCacheImpl(const base::FilePath& root_dir,
BoundContextDatabase context_db,
size_t max_cache_size);
ContentCacheImpl(const ContentCacheImpl&) = delete;
ContentCacheImpl& operator=(const ContentCacheImpl&) = delete;
~ContentCacheImpl() override;
// Creates a `ContentCache` with the concrete implementation.
static std::unique_ptr<ContentCache> Create(const base::FilePath& root_dir,
BoundContextDatabase context_db,
size_t max_cache_items = 500);
void SetMaxCacheItems(size_t max_cache_items) override;
void ReadBytes(
const OpenedCloudFile& file,
scoped_refptr<net::IOBuffer> buffer,
int64_t offset,
int length,
ProvidedFileSystemInterface::ReadChunkReceivedCallback callback) override;
void WriteBytes(const OpenedCloudFile& file,
scoped_refptr<net::IOBuffer> buffer,
int64_t offset,
int length,
FileErrorCallback callback) override;
void CloseFile(const OpenedCloudFile& file) override;
void LoadFromDisk(base::OnceClosure callback) override;
std::vector<base::FilePath> GetCachedFilePaths() override;
void Notify(ProvidedFileSystemObserver::Changes& changes) override;
void ObservedVersionTag(const base::FilePath& entry_path,
const std::string& version_tag) override;
void Evict(const base::FilePath& file_path) override;
void AddObserver(ContentCache::Observer* observer) override;
void RemoveObserver(ContentCache::Observer* observer) override;
private:
void OnBytesRead(
const base::FilePath& file_path,
ProvidedFileSystemInterface::ReadChunkReceivedCallback callback,
FileErrorOrBytesRead error_or_bytes_read);
// Called when the database returns an ID that will be used as the file name
// to write the bytes to disk.
void OnFileIdGenerated(const OpenedCloudFile& file,
scoped_refptr<net::IOBuffer> buffer,
int64_t offset,
int length,
FileErrorCallback callback,
std::unique_ptr<int64_t> inserted_id,
bool item_add_success);
void WriteBytesToDisk(const OpenedCloudFile& file,
scoped_refptr<net::IOBuffer> buffer,
int64_t offset,
int length,
FileErrorCallback callback);
void OnBytesWritten(const base::FilePath& file_path,
int64_t offset,
int length,
FileErrorCallback callback,
base::File::Error result);
// Invoked in the flow of `LoadFromDisk` once all the files have been
// discovered in the FSP content cache mount directory. The results are keyed
// by the id (i.e. the file name on disk) with a corresponding
// `CacheFileContext` containing the total bytes on disk populated.
void GotFilesFromDisk(base::OnceClosure callback,
std::map<int, int64_t> files_on_disk);
// Invoked in the flow of `LoadFromDisk` once all the items from the database
// have been retrieved.
void GotItemsFromContextDatabase(base::OnceClosure callback,
std::map<int, int64_t> files_on_disk,
ContextDatabase::IdToItemMap items);
// Invoked in the flow of `LoadFromDisk` once all the orphaned files (from
// disk OR in the DB) have been removed. The `success` vector contains 2 bools
// indicating the success of the db removal and disk removal (respectively).
void OnStaleItemsPruned(base::OnceClosure callback,
std::vector<bool> prune_success);
// Removes items individually from the disk and the lru_cache. Removes items
// in bulk from the database.
void RemoveItems(const std::vector<base::FilePath>& fsp_paths);
// Removes items in bulk from the database.
void RemoveItemsFromDatabase(std::vector<int64_t>& item_ids);
void OnItemsRemovedFromDatabase(size_t number_of_items, bool success);
// Removes an item with `path_on_disk` from the disk. Upon success, removes
// item with `fsp_path` from the lru cache.
void RemoveItemFromDisk(const base::FilePath& path_on_disk,
const base::FilePath& fsp_path);
void OnItemRemovedFromDisk(const base::FilePath& fsp_path, bool success);
// Evict the items with `file_paths`. The items are still accessible to
// current FSP requests but inaccessible to new FSP requests. All items that
// aren't being accessed by current FSP requests will be removed from the disk
// and the database. Each remaining item will be removed once the last FSP
// request for the item completes with `CloseFile()`.
void EvictItems(const std::vector<base::FilePath>& file_paths);
// The cache has maximum bounds on the number of items available. In the event
// this boundary is exceeded, excess items should be evicted. There may
// already be evicted items still in the cache (yet to be removed). The
// remaining items to evict will be the least-recently used items.
// TODO(b/330602540): Update the logic to also evict items when the maximum
// size threshold has been reached.
void EvictExcessItems();
// Generates the absolute path on disk from the supplied `item_id`.
const base::FilePath GetPathOnDiskFromId(int64_t item_id);
SEQUENCE_CHECKER(sequence_checker_);
const base::FilePath root_dir_;
ContentLRUCache lru_cache_ GUARDED_BY_CONTEXT(sequence_checker_);
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
BoundContextDatabase context_db_;
size_t max_cache_items_;
// Number of evicted items that will be removed on the next removal cycle.
size_t evicted_cache_items_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
base::ObserverList<ContentCache::Observer> observers_;
base::WeakPtrFactory<ContentCacheImpl> weak_ptr_factory_{this};
};
} // namespace ash::file_system_provider
#endif // CHROME_BROWSER_ASH_FILE_SYSTEM_PROVIDER_CONTENT_CACHE_CONTENT_CACHE_IMPL_H_
|