1#include "DesignCache.h"
2#include "ArchiveExtractor.h"
7#include "../FileModel/Design/FileArchive.h"
9#include "../ProductModel/Design.h"
13#include <StringVector.h>
14#include <shared_mutex>
17using namespace std::filesystem;
19namespace Odb::Lib::App
21 DesignCache::DesignCache(std::string directory) :
22 m_directory(std::move(directory))
24 ensureDirectoryExists();
27 DesignCache::~DesignCache()
32 std::shared_ptr<ProductModel::Design> DesignCache::GetDesign(
const std::string& designName)
36 std::shared_lock readLock(m_cacheMutex);
37 auto findIt = m_designsByName.find(designName);
38 if (findIt != m_designsByName.end())
40 return findIt->second;
45 auto pDesign = LoadDesign(designName);
48 if (pDesign !=
nullptr)
50 std::unique_lock writeLock(m_cacheMutex);
51 auto findIt = m_designsByName.find(designName);
52 if (findIt != m_designsByName.end())
54 return findIt->second;
56 m_designsByName[designName] = pDesign;
61 std::shared_ptr<FileModel::Design::FileArchive> DesignCache::GetFileArchive(
const std::string& designName)
64 ss <<
"Retrieving design \"" << designName <<
"\" from cache... ";
69 std::shared_lock readLock(m_cacheMutex);
70 auto findIt = m_fileArchivesByName.find(designName);
71 if (findIt != m_fileArchivesByName.end())
73 logdebug(
"Found. Returning from cache.");
74 return findIt->second;
78 loginfo(
"Not found in cache, attempting to load from file...");
81 auto pFileArchive = LoadFileArchive(designName);
83 if (pFileArchive ==
nullptr)
85 logwarn(
"Failed loading from file");
89 loginfo(
"Loaded from file");
92 std::unique_lock writeLock(m_cacheMutex);
93 auto findIt = m_fileArchivesByName.find(designName);
94 if (findIt != m_fileArchivesByName.end())
96 logdebug(
"Found. Returning from cache (loaded by another thread).");
97 return findIt->second;
99 m_fileArchivesByName[designName] = pFileArchive;
104 void DesignCache::AddFileArchive(
const std::string& designName, std::shared_ptr<FileModel::Design::FileArchive> fileArchive,
bool save)
106 std::unique_lock writeLock(m_cacheMutex);
107 m_fileArchivesByName[designName] = fileArchive;
113 SaveFileArchive(designName);
117 bool DesignCache::SaveFileArchive(
const std::string& designName)
119 auto fileArchive = GetFileArchive(designName);
120 if (fileArchive !=
nullptr)
122 std::string directory;
124 std::shared_lock readLock(m_cacheMutex);
125 directory = m_directory;
127 return fileArchive->SaveFileModel(directory);
132 std::vector<std::string> DesignCache::getLoadedDesignNames(
const std::string& filter)
const
134 std::shared_lock readLock(m_cacheMutex);
135 std::vector<std::string> loadedDesigns;
136 for (
const auto& kv : m_designsByName)
138 loadedDesigns.push_back(kv.first);
140 return loadedDesigns;
143 std::vector<std::string> DesignCache::getLoadedFileArchiveNames(
const std::string& filter)
const
145 std::shared_lock readLock(m_cacheMutex);
146 std::vector<std::string> loadedFileArchives;
147 for (
const auto& kv : m_fileArchivesByName)
149 loadedFileArchives.push_back(kv.first);
151 return loadedFileArchives;
154 std::vector<std::string> DesignCache::getUnloadedDesignNames(
const std::string& filter)
const
156 std::string directory;
158 std::shared_lock readLock(m_cacheMutex);
159 directory = m_directory;
162 std::vector<std::string> unloadedNames;
167 for (
const auto& entry : directory_iterator(dir))
169 if (entry.is_regular_file())
171 unloadedNames.push_back(entry.path().stem().string());
182 return unloadedNames;
185 int DesignCache::loadAllFileArchives(
bool stopOnError)
189 std::string directory;
191 std::shared_lock readLock(m_cacheMutex);
192 directory = m_directory;
195 for (
const auto& entry : directory_iterator(directory))
197 if (entry.is_regular_file())
199 if (ArchiveExtractor::IsArchiveTypeSupported(entry.path().filename()))
203 auto pFileArchive = GetFileArchive(entry.path().stem().string());
204 if (pFileArchive !=
nullptr)
209 catch (std::exception& e)
213 if (stopOnError)
throw e;
222 int DesignCache::loadAllDesigns(
bool stopOnError)
226 std::string directory;
228 std::shared_lock readLock(m_cacheMutex);
229 directory = m_directory;
232 for (
const auto& entry : directory_iterator(directory))
234 if (entry.is_regular_file())
236 if (ArchiveExtractor::IsArchiveTypeSupported(entry.path().filename()))
240 auto pDesign = GetDesign(entry.path().stem().string());
241 if (pDesign !=
nullptr)
246 catch (std::exception& e)
261 int DesignCache::loadFileArchives(
const StringVector& names)
265 for (
const auto& name : names)
269 auto pFileArchive = GetFileArchive(name);
270 if (pFileArchive !=
nullptr)
275 catch (std::exception& e)
285 int DesignCache::loadDesigns(
const StringVector& names)
289 for (
const auto& name : names)
293 auto pDesign = GetDesign(name);
294 if (pDesign !=
nullptr)
299 catch (std::exception& e)
309 void DesignCache::setDirectory(
const std::string& directory)
311 std::unique_lock writeLock(m_cacheMutex);
312 m_directory = directory;
315 std::string DesignCache::getDirectory()
const
317 std::shared_lock readLock(m_cacheMutex);
321 void DesignCache::Clear()
323 std::unique_lock writeLock(m_cacheMutex);
324 m_fileArchivesByName.clear();
325 m_designsByName.clear();
328 std::shared_ptr<ProductModel::Design> DesignCache::LoadDesign(
const std::string& designName)
332 std::string directory;
334 std::shared_lock readLock(m_cacheMutex);
335 directory = m_directory;
338 for (
const auto& entry : directory_iterator(directory))
340 if (entry.is_regular_file())
342 if (entry.path().stem() == designName)
345 auto pFileModel = GetFileArchive(designName);
346 if (pFileModel !=
nullptr)
348 auto pDesign = std::make_shared<ProductModel::Design>();
349 if (pDesign->Build(pFileModel))
369 std::shared_ptr<FileModel::Design::FileArchive> DesignCache::LoadFileArchive(
const std::string& designName)
373 auto fileFound =
false;
375 std::string directory;
377 std::shared_lock readLock(m_cacheMutex);
378 directory = m_directory;
382 const auto options = directory_options::skip_permission_denied;
383 for (
const auto& entry : directory_iterator(directory, options))
385 if (entry.is_regular_file())
387 if (entry.path().stem() == designName)
391 loginfo(
"file found: [" + entry.path().string() +
"], attempting to parse...");
393 auto pFileArchive = std::make_shared<FileModel::Design::FileArchive>(entry.path().string());
394 if (pFileArchive->ParseFileModel())
408 logwarn(
"Failed to find file for design \"" + designName +
"\"");
410 logdebug(
"Listing all files in directory: " + directory);
411 for (
const auto& entry : directory_iterator(directory, options))
413 if (entry.is_regular_file())
415 logdebug(
"Found file: " + entry.path().filename().string() +
" (stem: " + entry.path().stem().string() +
")");
423 void DesignCache::ensureDirectoryExists()
const
425 if (!std::filesystem::exists(m_directory))
430 std::filesystem::create_directories(m_directory);
432 catch (
const std::exception& e)
434 std::string msg =
"Failed to create design cache directory: " + m_directory;
435 logexception_msg(e, msg);