Skip to content

Commit

Permalink
Added support for moving links within and between files
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidAce committed Oct 4, 2020
1 parent 98318b2 commit 4095f7d
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
28 changes: 27 additions & 1 deletion h5pp/include/h5pp/details/h5ppFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ namespace h5pp {

template<typename h5x_tgt, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_tgt>>
void
copyLinkToLocation(const std::string &localLinkPath, const h5x_tgt &targetLocationId, const std::string &targetLinkPath) const {
copyLinkToLocation(const std::string &localLinkPath, const h5x_tgt &targetLocationId, const std::string &targetLinkPath) const {
return h5pp::hdf5::copyLink(openFileHandle(), localLinkPath, targetLocationId, targetLinkPath, plists);
}

Expand All @@ -186,6 +186,31 @@ namespace h5pp {
sourceLocationId, sourceLinkPath, openFileHandle(), localLinkPath, h5pp::FilePermission::READWRITE, plists);
}

void moveLinkToFile(const std::string & localLinkPath,
const std::string & targetFilePath,
const std::string & targetLinkPath,
const FilePermission &targetFileCreatePermission = FilePermission::READWRITE) const {
return h5pp::hdf5::moveLink(getFilePath(), localLinkPath, targetFilePath, targetLinkPath, targetFileCreatePermission, plists);
}

void moveLinkFromFile(const std::string &localLinkPath, const std::string &sourceFilePath, const std::string &sourceLinkPath) {
return h5pp::hdf5::moveLink(
sourceFilePath, sourceLinkPath, getFilePath(), localLinkPath, h5pp::FilePermission::READWRITE, plists);
}

template<typename h5x_tgt, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_tgt>>
void
moveLinkToLocation(const std::string &localLinkPath, const h5x_tgt &targetLocationId, const std::string &targetLinkPath) const {
return h5pp::hdf5::moveLink(openFileHandle(), localLinkPath, targetLocationId, targetLinkPath, plists);
}


template<typename h5x_src, typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>>
void moveLinkFromLocation(const std::string &localLinkPath, const h5x_src &sourceLocationId, const std::string &sourceLinkPath) {
return h5pp::hdf5::moveLink(
sourceLocationId, sourceLinkPath, openFileHandle(), localLinkPath, h5pp::FilePermission::READWRITE, plists);
}

/*
*
* Functions for logging
Expand Down Expand Up @@ -927,6 +952,7 @@ namespace h5pp {
h5pp::format("Could not read records from table [{}]: it does not exist", util::safe_str(tablePath)));
h5pp::hdf5::readTableRecords(data, info, startIdx, numRecords);
}

template<typename DataType>
void readTableRecords(DataType &data, std::string_view tablePath, h5pp::TableSelection tableSelection) const {
Options options;
Expand Down
81 changes: 81 additions & 0 deletions h5pp/include/h5pp/details/h5ppHdf5.h
Original file line number Diff line number Diff line change
Expand Up @@ -2575,6 +2575,46 @@ namespace h5pp::hdf5 {
}
}

template<typename h5x_src,
typename h5x_tgt,
typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_src>,
typename = h5pp::type::sfinae::enable_if_is_h5_loc<h5x_tgt>>
inline void moveLink(const h5x_src & srcLocId,
const std::string & srcLinkPath,
const h5x_tgt & tgtLocId,
const std::string & tgtLinkPath,
const PropertyLists &plists = PropertyLists()) {
h5pp::logger::log->trace("Moving link [{}] --> [{}]", srcLinkPath, tgtLinkPath);
// Move the link srcLinkPath to tgtLinkPath. Note that H5Lmove only works inside a single file.
// For different files we should copyLink followed by H5Ldelete

h5pp::hid::h5f srcFileId = H5Iget_file_id(srcLocId);
h5pp::hid::h5f tgtFileId = H5Iget_file_id(tgtLocId);

if(srcFileId == tgtLocId){
// Same file
auto retval = H5Lmove(srcLocId, srcLinkPath.c_str(), tgtLocId, tgtLinkPath.c_str(), plists.linkCreate,plists.linkAccess);
if(retval < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Could not copy link [{}] --> [{}]", srcLinkPath, tgtLinkPath));
}
}else{
// Different files
auto retval = H5Ocopy(srcLocId, srcLinkPath.c_str(), tgtLocId, tgtLinkPath.c_str(), H5P_DEFAULT, plists.linkCreate);
if(retval < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Could not copy link [{}] --> [{}]", srcLinkPath, tgtLinkPath));
}
retval = H5Ldelete(srcLocId,srcLinkPath.c_str(),plists.linkAccess);
if(retval < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Could not delete link after move [{}]", srcLinkPath));
}
}

}


inline void copyLink(const std::string & srcFilePath,
const std::string & srcLinkPath,
const std::string & tgtFilePath,
Expand Down Expand Up @@ -2665,6 +2705,47 @@ namespace h5pp::hdf5 {
}
}

inline void moveLink(const std::string & srcFilePath,
const std::string & srcLinkPath,
const std::string & tgtFilePath,
const std::string & tgtLinkPath,
FilePermission targetFileCreatePermission = FilePermission::READWRITE,
const PropertyLists &plists = PropertyLists()) {
h5pp::logger::log->trace("Moving link: source link [{}] | source file [{}] --> target link [{}] | target file [{}]",
srcLinkPath,
srcFilePath,
tgtLinkPath,
tgtFilePath);

try {
auto srcPath = fs::absolute(srcFilePath);
if(not fs::exists(srcPath))
throw std::runtime_error(h5pp::format("Could not move link [{}] from file [{}]: source file does not exist [{}]",
srcLinkPath,
srcFilePath,
srcPath.string()));
auto tgtPath = h5pp::hdf5::createFile(tgtFilePath, targetFileCreatePermission, plists);

hid_t hidSrc = H5Fopen(srcPath.string().c_str(), H5F_ACC_RDWR, plists.fileAccess);
hid_t hidTgt = H5Fopen(tgtPath.string().c_str(), H5F_ACC_RDWR, plists.fileAccess);
if(hidSrc < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Failed to open source file [{}] in read-only mode", srcPath.string()));
}
if(hidTgt < 0) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Failed to open target file [{}] in read-write mode", tgtPath.string()));
}
hid::h5f srcFile = hidSrc;
hid::h5f tgtFile = hidTgt;
moveLink(srcFile, srcLinkPath, tgtFile, tgtLinkPath);
} catch(const std::exception &ex) {
H5Eprint(H5E_DEFAULT, stderr);
throw std::runtime_error(h5pp::format("Could not move link [{}] from file [{}]: {}", srcLinkPath, srcFilePath, ex.what()));
}
}


inline fs::path moveFile(const std::string & src,
const std::string & tgt,
FilePermission permission = FilePermission::COLLISION_FAIL,
Expand Down
19 changes: 19 additions & 0 deletions tests/test-moveLink.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <h5pp/h5pp.h>
#include <iostream>


// Store some dummy data to an hdf5 file

int main() {
size_t logLevel = 0;
h5pp::File fileA("output/moveLinkA.h5", h5pp::FilePermission::REPLACE, logLevel);
// Same file
fileA.writeDataset("A", "groupA/A");
fileA.moveLinkToFile("groupA/A", "output/moveLinkA.h5", "groupA_from_file_A/A");
fileA.moveLinkToFile("groupA_from_file_A/A", "output/moveLinkA.h5", "groupA/A");


// Different file
fileA.moveLinkToFile("groupA/A", "output/moveLinkB.h5", "groupA_from_file_A/A", h5pp::FilePermission::REPLACE);
fileA.moveLinkFromFile("groupA_from_file_B/A", "output/moveLinkB.h5", "groupA_from_file_A/A");
}

0 comments on commit 4095f7d

Please sign in to comment.