~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/FileLoaders/DiskCachingFileLoader.h

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2012- PPSSPP Project.
 
2
 
 
3
// This program is free software: you can redistribute it and/or modify
 
4
// it under the terms of the GNU General Public License as published by
 
5
// the Free Software Foundation, version 2.0 or later versions.
 
6
 
 
7
// This program is distributed in the hope that it will be useful,
 
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
// GNU General Public License 2.0 for more details.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official git repository and contact information can be found at
 
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
 
17
 
 
18
#pragma once
 
19
 
 
20
#include <vector>
 
21
#include <map>
 
22
#include "base/mutex.h"
 
23
#include "Common/Common.h"
 
24
#include "Core/Loaders.h"
 
25
 
 
26
class DiskCachingFileLoaderCache;
 
27
 
 
28
class DiskCachingFileLoader : public FileLoader {
 
29
public:
 
30
        DiskCachingFileLoader(FileLoader *backend);
 
31
        ~DiskCachingFileLoader() override;
 
32
 
 
33
        bool Exists() override;
 
34
        bool ExistsFast() override;
 
35
        bool IsDirectory() override;
 
36
        s64 FileSize() override;
 
37
        std::string Path() const override;
 
38
 
 
39
        void Seek(s64 absolutePos) override;
 
40
        size_t Read(size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
 
41
                return ReadAt(filepos_, bytes, count, data, flags);
 
42
        }
 
43
        size_t Read(size_t bytes, void *data, Flags flags = Flags::NONE) override {
 
44
                return ReadAt(filepos_, bytes, data, flags);
 
45
        }
 
46
        size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
 
47
                return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
 
48
        }
 
49
        size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
 
50
 
 
51
        static std::vector<std::string> GetCachedPathsInUse();
 
52
 
 
53
private:
 
54
        void Prepare();
 
55
        void InitCache();
 
56
        void ShutdownCache();
 
57
 
 
58
        bool prepared_;
 
59
        s64 filesize_;
 
60
        s64 filepos_;
 
61
        FileLoader *backend_;
 
62
        DiskCachingFileLoaderCache *cache_;
 
63
 
 
64
        // We don't support concurrent disk cache access (we use memory cached indexes.)
 
65
        // So we have to ensure there's only one of these per.
 
66
        static std::map<std::string, DiskCachingFileLoaderCache *> caches_;
 
67
        static recursive_mutex cachesMutex_;
 
68
};
 
69
 
 
70
class DiskCachingFileLoaderCache {
 
71
public:
 
72
        DiskCachingFileLoaderCache(const std::string &path, u64 filesize);
 
73
        ~DiskCachingFileLoaderCache();
 
74
 
 
75
        bool IsValid() {
 
76
                return f_ != nullptr;
 
77
        }
 
78
 
 
79
        void AddRef() {
 
80
                ++refCount_;
 
81
        }
 
82
 
 
83
        bool Release() {
 
84
                return --refCount_ == 0;
 
85
        }
 
86
 
 
87
        static void SetCacheDir(const std::string &path) {
 
88
                cacheDir_ = path;
 
89
        }
 
90
 
 
91
        size_t ReadFromCache(s64 pos, size_t bytes, void *data);
 
92
        // Guaranteed to read at least one block into the cache.
 
93
        size_t SaveIntoCache(FileLoader *backend, s64 pos, size_t bytes, void *data, FileLoader::Flags flags);
 
94
 
 
95
        bool HasData() const;
 
96
 
 
97
private:
 
98
        void InitCache(const std::string &path);
 
99
        void ShutdownCache();
 
100
        bool MakeCacheSpaceFor(size_t blocks);
 
101
        void RebalanceGenerations();
 
102
        u32 AllocateBlock(u32 indexPos);
 
103
 
 
104
        struct BlockInfo;
 
105
        bool ReadBlockData(u8 *dest, BlockInfo &info, size_t offset, size_t size);
 
106
        void WriteBlockData(BlockInfo &info, u8 *src);
 
107
        void WriteIndexData(u32 indexPos, BlockInfo &info);
 
108
        s64 GetBlockOffset(u32 block);
 
109
 
 
110
        std::string MakeCacheFilePath(const std::string &path);
 
111
        std::string MakeCacheFilename(const std::string &path);
 
112
        bool LoadCacheFile(const std::string &path);
 
113
        void LoadCacheIndex();
 
114
        void CreateCacheFile(const std::string &path);
 
115
        bool LockCacheFile(bool lockStatus);
 
116
        bool RemoveCacheFile(const std::string &path);
 
117
        void CloseFileHandle();
 
118
 
 
119
        u64 FreeDiskSpace();
 
120
        u32 DetermineMaxBlocks();
 
121
        u32 CountCachedFiles();
 
122
        void GarbageCollectCacheFiles(u64 goalBytes);
 
123
 
 
124
        // File format:
 
125
        // 64 magic
 
126
        // 32 version
 
127
        // 32 blockSize
 
128
        // 64 filesize
 
129
        // 32 maxBlocks
 
130
        // 32 flags
 
131
        // index[filesize / blockSize] <-- ~500 KB for 4GB
 
132
        //   32 (fileoffset - headersize) / blockSize -> -1=not present
 
133
        //   16 generation?
 
134
        //   16 hits?
 
135
        // blocks[up to maxBlocks]
 
136
        //   8 * blockSize
 
137
 
 
138
        enum {
 
139
                CACHE_VERSION = 3,
 
140
                DEFAULT_BLOCK_SIZE = 65536,
 
141
                MAX_BLOCKS_PER_READ = 16,
 
142
                MAX_BLOCKS_LOWER_BOUND = 256, // 16 MB
 
143
                MAX_BLOCKS_UPPER_BOUND = 8192, // 512 MB
 
144
                INVALID_BLOCK = 0xFFFFFFFF,
 
145
                INVALID_INDEX = 0xFFFFFFFF,
 
146
        };
 
147
 
 
148
        int refCount_;
 
149
        s64 filesize_;
 
150
        u32 blockSize_;
 
151
        u16 generation_;
 
152
        u16 oldestGeneration_;
 
153
        u32 maxBlocks_;
 
154
        u32 flags_;
 
155
        size_t cacheSize_;
 
156
        size_t indexCount_;
 
157
        recursive_mutex lock_;
 
158
        std::string origPath_;
 
159
 
 
160
        struct FileHeader {
 
161
                char magic[8];
 
162
                u32_le version;
 
163
                u32_le blockSize;
 
164
                s64_le filesize;
 
165
                u32_le maxBlocks;
 
166
                u32_le flags;
 
167
        };
 
168
 
 
169
        enum FileFlags {
 
170
                FLAG_LOCKED = 1 << 0,
 
171
        };
 
172
 
 
173
        struct BlockInfo {
 
174
                u32 block;
 
175
                u16 generation;
 
176
                u16 hits;
 
177
 
 
178
                BlockInfo() : block(-1), generation(0), hits(0) {
 
179
                }
 
180
        };
 
181
 
 
182
        std::vector<BlockInfo> index_;
 
183
        std::vector<u32> blockIndexLookup_;
 
184
 
 
185
        FILE *f_;
 
186
        int fd_;
 
187
 
 
188
        static std::string cacheDir_;
 
189
};