FileSystemIndexer v0.1.2-beta
File System Indexer - An API to index files from your system
Loading...
Searching...
No Matches
FSI_Indexer.cpp
Go to the documentation of this file.
1#include <filesystem>
2#include <algorithm>
3#include <future>
4#include <execution>
5
8
10
12
13#include "ciof/ciof.hpp"
14
15namespace fs = std::filesystem;
16
17namespace fsi
18{
19 // PROTECTED //
20 IndexerPathType Indexer::__getPathType(const std::string &path) const
21 {
22 if (fs::is_directory(path)) return IndexerPathType::Directory;
23 else if (fs::is_symlink(path)) return IndexerPathType::SymLink;
24
26 }
27
28 std::vector<std::string> Indexer::__searchMatchingStandard(const std::string &find)
29 {
30 if (find.empty())
31 return {};
32
33 std::vector<std::string> vec;
34
35 for (const auto &x : this->indexerInfo)
36 {
37 if (x.path.find(find) != std::string::npos)
38 vec.emplace_back(x.path);
39 }
40
41 return vec;
42 }
43
44 std::vector<std::string> Indexer::__searchMatchingThreaded(const std::string& find)
45 {
46 if (find.empty())
47 return {};
48
49 std::vector<std::string> result;
50 std::mutex mutex;
51
52 std::for_each(
53 std::execution::par,
54 indexerInfo.begin(),
55 indexerInfo.end(),
56 [&](const auto& x)
57 {
58 if (x.path.find(find) != std::string::npos)
59 {
60 std::lock_guard<std::mutex> lock(mutex);
61 result.emplace_back(x.path);
62 }
63 }
64 );
65
66 return result;
67 }
68
70 {
71 IndexerError error = this->addInfo(info);
72 IndexerInfo totalInfo = info;
73
74 if (__FSI_INDEXERERR_CHECK(error))
75 return error;
76
77 const std::vector<std::string> iteratedPaths = this->__iteratePath(info.path);
78
79 for (const auto &x : iteratedPaths)
80 {
81 totalInfo.pathType = this->__getPathType(totalInfo.path);
82 totalInfo.path = x;
83
84 this->indexerInfo.emplace_back(totalInfo);
85 }
86
87 return error;
88 }
89
91 {
92 IndexerError error = this->addInfo(info);
93
94 if (__FSI_INDEXERERR_CHECK(error))
95 return error;
96
97 const auto paths = this->__iteratePath(info.path);
98 const auto &chunks = this->__splitPathByCores(paths);
99
100 std::vector<std::future<std::vector<IndexerInfo>>> tasks;
101
102 for (auto &chunk : chunks)
103 {
104 if (chunk.empty())
105 continue;
106
107 tasks.emplace_back(std::async(std::launch::async,
108 [&, chunk]() -> std::vector<IndexerInfo>
109 {
110 std::vector<IndexerInfo> local;
111
112 local.reserve(chunk.size());
113
114 for (const auto &p : chunk)
115 {
116 IndexerInfo tmp = info;
117 tmp.path = p;
118 tmp.pathType = this->__getPathType(p);
119 local.emplace_back(std::move(tmp));
120 }
121
122 return local;
123 }));
124 }
125
126 // Merging phase
127 for (auto &t : tasks)
128 {
129 auto local = t.get();
130
131 this->indexerInfo.insert(
132 this->indexerInfo.end(),
133 std::make_move_iterator(local.begin()),
134 std::make_move_iterator(local.end()));
135 }
136
137 return error;
138 }
139
140 std::vector<std::string> Indexer::__iteratePath(const std::string &path)
141 {
142 std::vector<std::string> paths;
143
144 CVEC tmpPathsVec = cvec_init(-1, sizeof(char*));
145
146 fsi_walk(&tmpPathsVec, path.c_str());
147
148 for (size_t i = 0; i < tmpPathsVec.size; ++i)
149 {
150 char* p = *(char**)cvec_get(&tmpPathsVec, i);
151
152 if (p)
153 {
154 paths.emplace_back(p, strlen(p));
155
156 FSI_FREE(p);
157 }
158 }
159
160 cvec_destroy(&tmpPathsVec);
161
162 return paths;
163 }
164
165 // PUBLIC //
166 // CONSTRUCTOR
167 Indexer::Indexer(const std::string &id, const bool threadsImpl)
169 { }
170
171 // DECONSTRUCTOR
174
176 {
177 if (this->threadsImpl)
178 return this->__addExtendedInfoThreaded(info);
179
180 return this->__addExtendedInfoStandard(info);
181 }
182
183 std::string Indexer::searchExactMatching(const std::string &find)
184 {
185 if (find.empty())
186 return "";
187
188 return this->findIndex(find).path;
189 }
190
191 std::vector<std::string> Indexer::searchMatching(const std::string &find)
192 {
193 if (this->threadsImpl) return this->__searchMatchingThreaded(find);
194
195 return this->__searchMatchingStandard(find);
196 }
197
199 {
200 IndexerError error;
201 IndexerInfo totalInfo = info;
202
203 // Do checks before adding
204 if (totalInfo.path.empty())
205 {
207 error.message = "Path is empty";
208 error.fatal = false;
209 error.raise = false;
210
211 return error;
212 }
213
214 if (!fs::exists(totalInfo.path))
215 {
217 error.message = ciof::format("Unknown path `%1`; No such file or directory exists", totalInfo.path);
218 error.fatal = true;
219
220 return error;
221 }
222
223
224 // Set path type
225 totalInfo.pathType = this->__getPathType(totalInfo.path);
226
227 // Add final information
228
229 this->indexerInfo.emplace_back(totalInfo);
230
231 return error;
232 }
233
234 IndexerInfo Indexer::findIndex(const std::string &toFind)
235 {
236 for (const auto &x : this->indexerInfo)
237 {
238 if (x.path == toFind || x.id == toFind)
239 return x;
240 }
241
242 return { };
243 }
244
245 IndexerError Indexer::removeInfo(const std::string &searcher)
246 {
247 IndexerError error;
248
249 // Do checks
250
251 if (searcher.empty())
252 {
254 error.message = "Empty value to remove from the Indexer Information list";
255 error.fatal = false;
256 error.raise = false;
257
258 return error;
259 }
260
261 // Erase the found object (IndexerInfo) value by ID or Path
262 this->indexerInfo.erase(
263 std::remove_if(
264 this->indexerInfo.begin(),
265 this->indexerInfo.end(),
266 [&](const IndexerInfo &info) {
267 return (info.id == searcher || info.path == searcher);
268 }),
269 this->indexerInfo.end()
270 );
271
272 return error;
273 }
274
276 {
277 const fs::file_time_type &lastWriteTime = fs::last_write_time(path);
278
279 return utils::fsClockDataToDT(lastWriteTime);
280 }
281
282 std::vector<IndexerInfo> Indexer::getIndexerInfo() const
283 { return this->indexerInfo; }
284
285 std::vector<std::string> Indexer::getIndexPaths() const
286 {
287 std::vector<std::string> additions;
288
289 for (const auto &x : this->indexerInfo)
290 { additions.emplace_back(x.path); }
291
292 return additions;
293 }
294
295 std::string Indexer::getID() const
296 { return this->id; }
297}
298
#define __FSI_INDEXERERR_CHECK(e)
void fsi_walk(CVEC *vec, const char *path)
Walk to every directory and file and set vec to a CVEC value.
#define FSI_FREE(x)
virtual std::vector< std::string > __searchMatchingStandard(const std::string &find)
Search all matching path or ID that contains path.
virtual IndexerPathType __getPathType(const std::string &path) const
Get if path from function param is a:
IndexerInfo findIndex(const std::string &toFind)
Find the index from the vector database from the indexer.
std::vector< IndexerInfo > indexerInfo
static std::vector< std::vector< std::string > > __splitPathByCores(const std::vector< std::string > &paths)
Split the paths found to be used in the future in different CPU cores.
IndexerError addInfo(const IndexerInfo &info)
Add the exact path to have the info from.
IndexerError removeInfo(const std::string &searcher)
Remove information from its ID or full path.
utils::TimeUtils_DateTime getFileDTInfo(const std::string &path)
Get when the file, dir or symlink was last modified.
std::vector< std::string > searchMatching(const std::string &path)
Either use threaded or unthreaded search matching.
Indexer(const std::string &id, const bool threadsImpl=false)
std::vector< std::string > getIndexPaths() const
Get all the indexed paths from the vector indexes.
std::string searchExactMatching(const std::string &find)
Search for an exact matching path or ID;.
virtual IndexerError __addExtendedInfoThreaded(const IndexerInfo &info)
Threaded extended information.
std::string getID() const
Get this object's ID.
IndexerError addExtendedInfo(const IndexerInfo &info)
Add the exact path and the sub-paths to have the info from;.
std::vector< IndexerInfo > getIndexerInfo() const
Return indexer information from this object.
virtual std::vector< std::string > __iteratePath(const std::string &path)
Iterate all the files and directories (symlinks too) from path.
virtual IndexerError __addExtendedInfoStandard(const IndexerInfo &info)
Standard non-threaded extended information.
virtual std::vector< std::string > __searchMatchingThreaded(const std::string &find)
Search all matching path or ID that contains path using parallelization with multiple CPU threads.
std::string id
constexpr int ERROR_ADDITION_FAIL
constexpr int ERROR_INVALID_PATH
constexpr int ERROR_EMPTY_VALUE
TimeUtils_DateTime fsClockDataToDT(const fs::file_time_type &time)
Set std::filesystem clock data to an actual usable Date and Time format.
IndexerPathType
std::string message
std::string path
IndexerPathType pathType