openMSX
FilePoolCore.hh
Go to the documentation of this file.
1#ifndef FILEPOOLCORE_HH
2#define FILEPOOLCORE_HH
3
4#include "FileOperations.hh"
5#include "ObjectPool.hh"
6#include "MemBuffer.hh"
7#include "SimpleHashSet.hh"
8#include "sha1.hh"
9#include "xxhash.hh"
10#include <cassert>
11#include <cstdint>
12#include <ctime>
13#include <functional>
14#include <string>
15#include <string_view>
16#include <vector>
17
18namespace openmsx {
19
20class File;
21
22enum class FileType {
23 NONE = 0,
24 SYSTEM_ROM = 1, ROM = 2, DISK = 4, TAPE = 8
25};
27 return static_cast<FileType>(int(x) | int(y));
28}
30 return static_cast<FileType>(int(x) & int(y));
31}
33 x = x | y;
34 return x;
35}
36
38{
39public:
40 struct Dir {
41 Dir() = default;
42 Dir(std::string_view p, FileType t)
43 : path(p), types(t) {} // clang-15 workaround
44
45 std::string_view path;
47 };
48 using Directories = std::vector<Dir>;
49
50public:
51 FilePoolCore(std::string fileCache,
52 std::function<Directories()> getDirectories,
53 std::function<void(std::string_view, float)> reportProgress);
55
60 [[nodiscard]] File getFile(FileType fileType, const Sha1Sum& sha1sum);
61
66 [[nodiscard]] Sha1Sum getSha1Sum(File& file);
67
72 void abort() { stop = true; }
73
74private:
75 struct ScanProgress {
76 uint64_t lastTime;
77 unsigned amountScanned = 0;
78 bool printed = false;
79 };
80
81 struct Entry {
82 Entry(const Sha1Sum& s, time_t t, std::string_view f)
83 : filename(f), time(t), sum(s)
84 {
85 assert(time != Date::INVALID_TIME_T);
86 }
87 Entry(const Sha1Sum& s, const char* t, std::string_view f)
88 : filename(f), timeStr(t), sum(s)
89 {
90 assert(timeStr != nullptr);
91 }
92
93 [[nodiscard]] time_t getTime();
94 void setTime(time_t t);
95
96 // - At least one of 'timeStr' or 'time' is valid.
97 // - 'filename' and 'timeStr' are non-owning pointers.
98 std::string_view filename;
99 const char* timeStr = nullptr; // might be nullptr
100 time_t time = Date::INVALID_TIME_T;
101 Sha1Sum sum;
102 };
103
104 using Pool = ObjectPool<Entry>;
105 using Index = Pool::Index;
106 using Sha1Index = std::vector<Index>; // sorted on sha1sum
107
108 class FilenameIndexHelper {
109 public:
110 explicit FilenameIndexHelper(const Pool& p) : pool(p) {}
111 [[nodiscard]] std::string_view get(std::string_view s) const { return s; }
112 [[nodiscard]] std::string_view get(Index idx) const { return pool[idx].filename; }
113 private:
114 const Pool& pool;
115 };
116 struct FilenameIndexHash : FilenameIndexHelper {
117 using FilenameIndexHelper::FilenameIndexHelper;
118 template<typename T> [[nodiscard]] auto operator()(T t) const {
119 XXHasher hasher;
120 return hasher(get(t));
121 }
122 };
123 struct FilenameIndexEqual : FilenameIndexHelper {
124 using FilenameIndexHelper::FilenameIndexHelper;
125 template<typename T1, typename T2>
126 [[nodiscard]] bool operator()(T1 x, T2 y) const {
127 return get(x) == get(y);
128 }
129 };
130 // Hash indexed by filename, points to a full object in 'pool'
131 using FilenameIndex = SimpleHashSet<Index(-1), FilenameIndexHash, FilenameIndexEqual>;
132
133private:
134 void insert(const Sha1Sum& sum, time_t time, const std::string& filename);
135 [[nodiscard]] Sha1Index::iterator getSha1Iterator(Index idx, const Entry& entry);
136 void remove(Sha1Index::iterator it);
137 void remove(Index idx);
138 void remove(Index idx, const Entry& entry);
139 bool adjustSha1(Sha1Index::iterator it, Entry& entry, const Sha1Sum& newSum);
140 bool adjustSha1(Index idx, Entry& entry, const Sha1Sum& newSum);
141
142 void readSha1sums();
143 void writeSha1sums();
144
145 [[nodiscard]] File getFromPool(const Sha1Sum& sha1sum);
146 [[nodiscard]] File scanDirectory(
147 const Sha1Sum& sha1sum,
148 const std::string& directory,
149 std::string_view poolPath,
150 ScanProgress& progress);
151 [[nodiscard]] File scanFile(
152 const Sha1Sum& sha1sum,
153 const std::string& filename,
154 const FileOperations::Stat& st,
155 std::string_view poolPath,
156 ScanProgress& progress);
157 [[nodiscard]] Sha1Sum calcSha1sum(File& file) const;
158 [[nodiscard]] std::pair<Index, Entry*> findInDatabase(std::string_view filename);
159
160private:
161 std::string fileCache; // path of the '.filecache' file.
162 std::function<Directories()> getDirectories;
163 std::function<void(std::string_view, float)> reportProgress;
164
165 MemBuffer<char> fileMem; // content of initial .filecache
166 std::vector<std::string> stringBuffer; // owns strings that are not in 'fileMem'
167
168 Pool pool; // the actual entries
169 Sha1Index sha1Index; // entries accessible via sha1, sorted on 'CompareSha1'
170 FilenameIndex filenameIndex{FilenameIndexHash(pool), FilenameIndexEqual(pool)}; // accessible via filename
171
172 bool stop = false; // abort long search (set via reportProgress callback)
173 bool needWrite = false; // dirty '.filecache'? write on exit
174
175 friend struct GetSha1;
176};
177
178} // namespace openmsx
179
180#endif
TclObject t
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
void abort()
This is only meaningful to call from within the 'reportProgress' callback (constructor parameter).
std::vector< Dir > Directories
This class represents the result of a sha1 calculation (a 160-bit value).
Definition sha1.hh:24
constexpr time_t INVALID_TIME_T
Definition Date.hh:11
uint64_t getTime()
Get current (real) time in us.
Definition Timer.cc:7
This file implemented 3 utility functions:
Definition Autofire.cc:11
FileType operator&(FileType x, FileType y)
FileType & operator|=(FileType &x, FileType y)
FileType operator|(FileType x, FileType y)
constexpr auto sum(InputRange &&range, Proj proj={})
Definition stl.hh:248
Dir(std::string_view p, FileType t)