30#include <boost/regex.hpp>
32#include <IceUtil/UUID.h>
42 namespace fs = std::filesystem;
45 databasePrx(databasePrx)
48 if (!armarxCachePath.empty())
50 init(armarxCachePath);
54 static std::string cachePath =
55 (std::filesystem::temp_directory_path() / std::to_string(std::random_device{}()))
62 const std::string& cachePath) :
63 databasePrx(databasePrx)
79 if (!fs::exists(cachePath))
81 fs::create_directory(cachePath);
84 fileCachePath = fs::path(cachePath) / fs::path(
"files");
86 if (!fs::exists(fileCachePath))
88 fs::create_directory(fileCachePath);
92 if (!fileCachePath.is_absolute())
95 std::filesystem::path fullPath(std::filesystem::current_path());
96 fileCachePath = fullPath / fileCachePath;
103 return fileCachePath.string();
108 std::string& cacheFileName,
109 bool preserveOriginalName)
121 fs::path filenameFromProxy(filePrx->getFilename());
123 fs::path localFile = fileCachePath / filenameFromProxy.stem();
125 if (!preserveOriginalName)
127 localFile += fs::path(filePrx->getId() +
"_" + filePrx->getMD5());
129 std::string localFileStr = localFile.string();
130 std::string extensionStr = filenameFromProxy.extension().string();
131 localFile = fs::path(localFileStr + extensionStr);
134 bool cached = fs::exists(localFile);
138 cached = cached && ((std::uintmax_t)filePrx->getFileSize() == fs::file_size(localFile));
141 fs::file_time_type lwt = fs::last_write_time(localFile);
142 auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
143 lwt - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
144 time_t time = std::chrono::system_clock::to_time_t(sctp);
146 cached = cached && (!preserveOriginalName || (time >= filePrx->getUploadDate() / 1000));
156 std::filesystem::path filePath;
157 filePath = localFile;
158 filePath = filePath.parent_path();
159 create_directories(filePath);
162 const std::string tmpLocalFile = localFile.string() + IceUtil::generateUUID() +
".part";
164 fsOut.open(tmpLocalFile.c_str(), std::ios_base::out | std::ios_base::binary);
166 memoryx::Blob buffer;
169 while (filePrx->getNextChunk(buffer))
171 fsOut.write((
char*)&buffer[0], buffer.size());
175 fs::rename(tmpLocalFile, localFile);
178 cacheFileName = localFile.string();
184 std::string& cacheFileName,
185 bool preserveOriginalName)
189 GridFileInterfacePrx filePrx = getFileProxyFromAttr(fileAttr);
198 databasePrx->releaseFileProxy(filePrx);
204 std::vector<std::string>& cacheFileNames,
205 bool preserveOriginalNames )
210 GridFileList filePrxList = getFileProxiesFromAttr(fileAttr);
212 if (filePrxList.empty())
217 std::string cacheFileName;
219 for (GridFileList::iterator it = filePrxList.begin(); it != filePrxList.end(); ++it)
223 cacheFileNames.push_back(cacheFileName);
224 databasePrx->releaseFileProxy(*it);
232 bool preserveOriginalNames )
235 std::vector<std::string> cacheFileNames;
243 std::string cacheFileName;
248 fs.open(cacheFileName.c_str(), std::ios_base::in);
259 GridFileInterfacePrx filePrx = getFileProxyFromAttr(fileAttr);
261 databasePrx->releaseFileProxy(filePrx);
267 const std::string& localFileName,
268 EntityAttributeBasePtr& fileAttr,
269 const std::string& gridFSName )
272 return addFileToAttr(filesDBName, localFileName, fileAttr, gridFSName);
277 const std::string& localFileName,
278 EntityAttributeBasePtr& fileAttr,
279 const std::string& gridFSName )
282 std::filesystem::path fname(localFileName);
283 fname = std::filesystem::absolute(fname);
288 fileId = databasePrx->storeFile(
291 (gridFSName.empty() ? fname.filename().string() : gridFSName));
293 catch (
const FileNotFoundException& e)
297 std::ifstream fin(fname.string().c_str(), std::ios::binary);
300 throw FileNotFoundException(
"File not found: " + fname.string(), fname.string());
302 std::stringstream contentStream;
303 contentStream << fin.rdbuf();
304 fileId = databasePrx->storeTextFile(
307 (gridFSName.empty() ? fname.filename().string() : gridFSName));
313 fileAttr->addValue(fileVar);
320 const std::string& localDirectoryName,
321 EntityAttributeBasePtr& fileAttr,
322 std::string excludeFilter)
325 boost::regex exclude(excludeFilter.c_str());
330 std::filesystem::path relativePathBase = localDirectoryName;
331 relativePathBase = relativePathBase.parent_path();
334 for (std::filesystem::recursive_directory_iterator end, dir(localDirectoryName.c_str());
339 if (dir->status().type() != std::filesystem::file_type::directory)
341 if (boost::regex_match(dir->path().filename().c_str(), exclude))
343 dir.disable_recursion_pending();
347 std::string fileName = makeRelativePath(dir->path(), relativePathBase);
350 const std::string fileId =
351 addFileToAttr(filesDBName, dir->path().c_str(), fileAttr, fileName);
352 success &= !fileId.empty();
362 const std::string& localBaseDirectoryName,
363 const std::vector<std::string>& localFiles,
364 EntityAttributeBasePtr& fileAttr)
370 std::filesystem::path relativePathBase = localBaseDirectoryName;
371 relativePathBase = relativePathBase.parent_path();
373 for (
size_t i = 0; i < localFiles.size(); i++)
375 std::filesystem::path f = localFiles[i];
376 std::string fileName = makeRelativePath(f, relativePathBase);
378 const std::string fileId =
addFileToAttr(filesDBName, f.c_str(), fileAttr, fileName);
379 success &= !fileId.empty();
389 const MongoDBRefPtr fileRef = extractMongoDBRef(fileAttr->getValueAt(fileIndex));
396 return databasePrx->removeFileById(fileRef->dbName, fileRef->docId);
410 for (
size_t i = 0; i < (size_t)fileAttr->size(); ++i)
419 GridFileManager::getFileProxyFromAttr(
const AttributeBasePtr& attr)
const
426 return databasePrx->getFileProxyById(fileRef->dbName, fileRef->docId);
430 ARMARX_WARNING <<
"Could not get fileref for attribute " << attr->getName();
431 return GridFileInterfacePrx();
436 GridFileManager::getFileProxiesFromAttr(
const AttributeBasePtr& attr)
const
447 for (
size_t i = 0; i < (size_t)entityAttr->size(); ++i)
449 const MongoDBRefPtr fileRef = extractMongoDBRef(entityAttr->getValueAt(i));
453 const GridFileInterfacePrx prx =
454 databasePrx->getFileProxyById(fileRef->dbName, fileRef->docId);
455 result.push_back(prx);
463 GridFileManager::extractMongoDBRef(
const AttributeBasePtr& attr)
const
473 return extractMongoDBRef(entityAttr->getValue());
505 GridFileManager::makeRelativePath(
const std::filesystem::path& directory,
506 const std::filesystem::path& basePath)
509 std::filesystem::path diffpath;
510 std::filesystem::path tmppath = directory;
512 while (tmppath != basePath)
514 diffpath = tmppath.filename() / diffpath;
515 tmppath = tmppath.parent_path();
520 diffpath = directory;
525 return diffpath.string();
static bool ReplaceEnvVars(std::string &string)
ReplaceEnvVars replaces environment variables in a string with their values, if the env.
static std::string GetCachePath()
The base Cache directory of ArmarX.
The Variant class is described here: Variants.
bool storeFilesToAttr(const std::string &filesDBName, const std::string &localBaseDirectoryName, const std::vector< std::string > &localFiles, EntityAttributeBasePtr &fileAttr)
Stores a set of files with in GridFS and puts a reference to it into entity attribute.
void init(std::string cachePath)
bool getFileStream(GridFileInterfacePrx &filePrx, std::ifstream &fs)
Caches the file locally and opens a filestream for it.
bool ensureFileInCache(GridFileInterfacePrx &filePrx, std::string &cacheFileName, bool preserveOriginalName=false)
Caches the file locally and returns the filename.
bool removeAttrFiles(const EntityAttributeBasePtr &fileAttr)
Removes all GridFS files referenced by entity attribute.
GridFileManager(const CommonStorageInterfacePrx &databasePrx)
Constructs new GridFileManager.
bool removeAttrFile(const EntityAttributeBasePtr &fileAttr, unsigned int fileIndex)
std::string getFileCachePath() const
Retrieves a local path where files will be cached.
std::string addFileToAttr(const std::string &filesDBName, const std::string &localFileName, EntityAttributeBasePtr &fileAttr, const std::string &gridFSName="")
Stores a file in GridFS and puts a reference to it into entity attribute.
bool ensureFilesInCache(const EntityAttributeBasePtr &fileAttr, std::vector< std::string > &cacheFileNames, bool preserveOriginalNames=false)
Caches multiple files locally.
~GridFileManager() override
bool storeDirectoryToAttr(const std::string &filesDBName, const std::string &localDirectoryName, EntityAttributeBasePtr &fileAttr, std::string excludeFilter=".svn")
Stores a complete directory tree in GridFS and puts a reference to it into entity attribute Overwrite...
std::string storeFileToAttr(const std::string &filesDBName, const std::string &localFileName, EntityAttributeBasePtr &fileAttr, const std::string &gridFSName="")
Stores a file in GridFS and puts a reference to it into entity attribute.
Represents a cross-database reference to a document in MongoDB.
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
const VariantTypeId MongoDBRef
IceInternal::Handle< Variant > VariantPtr
::IceInternal::Handle<::armarx::VariantBase > VariantBasePtr
IceInternal::Handle< EntityAttribute > EntityAttributePtr
Typedef of EntityAttributePtr as IceInternal::Handle<EntityAttribute> for convenience.
IceInternal::Handle< MongoDBRef > MongoDBRefPtr