CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/FileLoaders/DiskCachingFileLoader.h
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include <vector>20#include <map>21#include <mutex>2223#include "Common/CommonTypes.h"24#include "Common/File/Path.h"25#include "Common/Swap.h"26#include "Core/Loaders.h"2728class DiskCachingFileLoaderCache;2930class DiskCachingFileLoader : public ProxiedFileLoader {31public:32DiskCachingFileLoader(FileLoader *backend);33~DiskCachingFileLoader();3435bool Exists() override;36bool ExistsFast() override;37s64 FileSize() override;3839size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {40return ReadAt(absolutePos, bytes * count, data, flags) / bytes;41}42size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;4344static std::vector<Path> GetCachedPathsInUse();4546private:47void Prepare();48void InitCache();49void ShutdownCache();5051std::once_flag preparedFlag_;52s64 filesize_ = 0;53DiskCachingFileLoaderCache *cache_ = nullptr;5455// We don't support concurrent disk cache access (we use memory cached indexes.)56// So we have to ensure there's only one of these per.57static std::map<Path, DiskCachingFileLoaderCache *> caches_;58static std::mutex cachesMutex_;59};6061class DiskCachingFileLoaderCache {62public:63DiskCachingFileLoaderCache(const Path &path, u64 filesize);64~DiskCachingFileLoaderCache();6566bool IsValid() {67return f_ != nullptr;68}6970void AddRef() {71++refCount_;72}7374bool Release() {75return --refCount_ == 0;76}7778static void SetCacheDir(const Path &path) {79cacheDir_ = path;80}8182size_t ReadFromCache(s64 pos, size_t bytes, void *data);83// Guaranteed to read at least one block into the cache.84size_t SaveIntoCache(FileLoader *backend, s64 pos, size_t bytes, void *data, FileLoader::Flags flags);8586bool HasData() const;8788private:89void InitCache(const Path &path);90void ShutdownCache();91bool MakeCacheSpaceFor(size_t blocks);92void RebalanceGenerations();93u32 AllocateBlock(u32 indexPos);9495struct BlockInfo;96bool ReadBlockData(u8 *dest, BlockInfo &info, size_t offset, size_t size);97void WriteBlockData(BlockInfo &info, const u8 *src);98void WriteIndexData(u32 indexPos, BlockInfo &info);99s64 GetBlockOffset(u32 block);100101Path MakeCacheFilePath(const Path &filename);102std::string MakeCacheFilename(const Path &path);103bool LoadCacheFile(const Path &path);104void LoadCacheIndex();105void CreateCacheFile(const Path &path);106bool LockCacheFile(bool lockStatus);107bool RemoveCacheFile(const Path &path);108void CloseFileHandle();109110u64 FreeDiskSpace();111u32 DetermineMaxBlocks();112u32 CountCachedFiles();113void GarbageCollectCacheFiles(u64 goalBytes);114115// File format:116// 64 magic117// 32 version118// 32 blockSize119// 64 filesize120// 32 maxBlocks121// 32 flags122// index[filesize / blockSize] <-- ~500 KB for 4GB123// 32 (fileoffset - headersize) / blockSize -> -1=not present124// 16 generation?125// 16 hits?126// blocks[up to maxBlocks]127// 8 * blockSize128129enum {130CACHE_VERSION = 3,131DEFAULT_BLOCK_SIZE = 65536,132MAX_BLOCKS_PER_READ = 16,133MAX_BLOCKS_LOWER_BOUND = 256, // 16 MB134MAX_BLOCKS_UPPER_BOUND = 8192, // 512 MB135INVALID_BLOCK = 0xFFFFFFFF,136INVALID_INDEX = 0xFFFFFFFF,137};138139int refCount_ = 0;140s64 filesize_;141u32 blockSize_;142u16 generation_;143u16 oldestGeneration_;144u32 maxBlocks_;145u32 flags_;146size_t cacheSize_;147size_t indexCount_;148std::mutex lock_;149Path origPath_;150151struct FileHeader {152char magic[8];153u32_le version;154u32_le blockSize;155s64_le filesize;156u32_le maxBlocks;157u32_le flags;158};159160enum FileFlags {161FLAG_LOCKED = 1 << 0,162};163164struct BlockInfo {165u32 block;166u16 generation;167u16 hits;168169BlockInfo() : block(-1), generation(0), hits(0) {170}171};172173std::vector<BlockInfo> index_;174std::vector<u32> blockIndexLookup_;175176FILE *f_ = nullptr;177int fd_ = 0;178179static Path cacheDir_;180};181182183