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 std::string_view path;
43 };
44 using Directories = std::vector<Dir>;
45
46public:
47 FilePoolCore(std::string fileCache,
48 std::function<Directories()> getDirectories,
49 std::function<void(std::string_view, float)> reportProgress);
51
56 [[nodiscard]] File getFile(FileType fileType, const Sha1Sum& sha1sum);
57
62 [[nodiscard]] Sha1Sum getSha1Sum(File& file);
63
68 void abort() { stop = true; }
69
70private:
71 struct ScanProgress {
72 uint64_t lastTime;
73 unsigned amountScanned = 0;
74 bool printed = false;
75 };
76
77 struct Entry {
78 Entry(const Sha1Sum& s, time_t t, std::string_view f)
79 : filename(f), time(t), sum(s)
80 {
81 assert(time != Date::INVALID_TIME_T);
82 }
83 Entry(const Sha1Sum& s, const char* t, std::string_view f)
84 : filename(f), timeStr(t), sum(s)
85 {
86 assert(timeStr != nullptr);
87 }
88
89 [[nodiscard]] time_t getTime();
90 void setTime(time_t t);
91
92 // - At least one of 'timeStr' or 'time' is valid.
93 // - 'filename' and 'timeStr' are non-owning pointers.
94 std::string_view filename;
95 const char* timeStr = nullptr; // might be nullptr
96 time_t time = Date::INVALID_TIME_T;
97 Sha1Sum sum;
98 };
99
100 using Pool = ObjectPool<Entry>;
101 using Index = Pool::Index;
102 using Sha1Index = std::vector<Index>; // sorted on sha1sum
103
104 class FilenameIndexHelper {
105 public:
106 FilenameIndexHelper(const Pool& p) : pool(p) {}
107 [[nodiscard]] std::string_view get(std::string_view s) const { return s; }
108 [[nodiscard]] std::string_view get(Index idx) const { return pool[idx].filename; }
109 private:
110 const Pool& pool;
111 };
112 struct FilenameIndexHash : FilenameIndexHelper {
113 FilenameIndexHash(const Pool& p) : FilenameIndexHelper(p) {}
114 template<typename T> [[nodiscard]] auto operator()(T t) const {
115 XXHasher hasher;
116 return hasher(get(t));
117 }
118 };
119 struct FilenameIndexEqual : FilenameIndexHelper {
120 FilenameIndexEqual(const Pool& p) : FilenameIndexHelper(p) {}
121 template<typename T1, typename T2>
122 [[nodiscard]] bool operator()(T1 x, T2 y) const {
123 return get(x) == get(y);
124 }
125 };
126 // Hash indexed by filename, points to a full object in 'pool'
127 using FilenameIndex = SimpleHashSet<Index, Index(-1), FilenameIndexHash, FilenameIndexEqual>;
128
129private:
130 void insert(const Sha1Sum& sum, time_t time, const std::string& filename);
131 [[nodiscard]] Sha1Index::iterator getSha1Iterator(Index idx, Entry& entry);
132 void remove(Sha1Index::iterator it);
133 void remove(Index idx);
134 void remove(Index idx, Entry& entry);
135 bool adjustSha1(Sha1Index::iterator it, Entry& entry, const Sha1Sum& newSum);
136 bool adjustSha1(Index idx, Entry& entry, const Sha1Sum& newSum);
137
138 void readSha1sums();
139 void writeSha1sums();
140
141 [[nodiscard]] File getFromPool(const Sha1Sum& sha1sum);
142 [[nodiscard]] File scanDirectory(
143 const Sha1Sum& sha1sum,
144 const std::string& directory,
145 std::string_view poolPath,
146 ScanProgress& progress);
147 [[nodiscard]] File scanFile(
148 const Sha1Sum& sha1sum,
149 const std::string& filename,
150 const FileOperations::Stat& st,
151 std::string_view poolPath,
152 ScanProgress& progress);
153 [[nodiscard]] Sha1Sum calcSha1sum(File& file);
154 [[nodiscard]] std::pair<Index, Entry*> findInDatabase(std::string_view filename);
155
156private:
157 std::string fileCache; // path of the '.filecache' file.
158 std::function<Directories()> getDirectories;
159 std::function<void(std::string_view, float)> reportProgress;
160
161 MemBuffer<char> fileMem; // content of initial .filecache
162 std::vector<std::string> stringBuffer; // owns strings that are not in 'fileMem'
163
164 Pool pool; // the actual entries
165 Sha1Index sha1Index; // entries accessible via sha1, sorted on 'CompareSha1'
166 FilenameIndex filenameIndex{FilenameIndexHash(pool), FilenameIndexEqual(pool)}; // accessible via filename
167
168 bool stop = false; // abort long search (set via reportProgress callback)
169 bool needWrite = false; // dirty '.filecache'? write on exit
170
171 friend struct GetSha1;
172};
173
174} // namespace openmsx
175
176#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).
Definition: FilePoolCore.hh:68
std::vector< Dir > Directories
Definition: FilePoolCore.hh:44
FilePoolCore(std::string fileCache, std::function< Directories()> getDirectories, std::function< void(std::string_view, float)> reportProgress)
Definition: FilePoolCore.cc:24
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:23
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:9
FileType operator&(FileType x, FileType y)
Definition: FilePoolCore.hh:29
FileType & operator|=(FileType &x, FileType y)
Definition: FilePoolCore.hh:32
FileType operator|(FileType x, FileType y)
Definition: FilePoolCore.hh:26
auto sum(InputRange &&range, Proj proj={})
Definition: stl.hh:245