icedb  version 0.5.1
Snow particle scattering database API
databases.cpp
Go to the documentation of this file.
1 #include <set>
2 #include <map>
3 #include <memory>
4 #include <stdexcept>
5 #include "../icedb/fs.hpp"
6 #include "../icedb/compat/gsl/gsl_assert"
7 #include "../icedb/fs_backend.hpp"
8 #include "../private/hdf5_supplemental.hpp"
9 #include "../icedb/Database.hpp"
10 #include "../private/Database_impl.hpp"
11 #include "../private/hdf5_load.h"
12 
13 
14 namespace icedb {
15  namespace Databases {
16  std::shared_ptr<H5::H5File> file_image::getHFile() const { return hFile; }
17  file_image::file_image(const std::string &filename,
18  size_t desiredSizeInBytes)
19  : buffer(desiredSizeInBytes), filename(filename),
20  propertyList(-1), hFile(nullptr)
21  {
22  propertyList = H5Pcreate(H5P_FILE_ACCESS);
23  const auto h5Result = H5Pset_fapl_core(propertyList, buffer.size(), false);
24  Expects(h5Result >= 0 && "H5Pset_fapl_core failed");
25  // This new memory-only dataset needs to always be writable. The flags parameter
26  // has little meaning in this context.
27  hFile = std::make_shared<H5::H5File>(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, propertyList);
28  //m_file = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, propertyList);
29  }
31  if (propertyList != -1) H5Pclose(propertyList);
32  }
33 
34  std::shared_ptr<H5::H5File> Database_impl::makeDatabaseFileStandard(const std::string &p) {
35  auto res = std::make_shared<H5::H5File>(p,
37  H5P_DEFAULT);
38  constexpr uint64_t dbverno = 1;
39  auto basegrp = res->openGroup("."); //->getHDF5Group();
40  icedb::fs::hdf5::addAttr<uint64_t, H5::Group>(&basegrp, "Version", dbverno);
41  icedb::fs::hdf5::addAttr<std::string, H5::Group>(&basegrp, "Software", "libicedb");
42 
43  //icedb::fs::hdf5::addAttr<uint64_t, H5::H5File>(res.get(), "Version", dbverno);
44  //icedb::fs::hdf5::addAttr<std::string, H5::H5File>(res.get(), "Software", "libicedb");
45  return res;
46  }
47 
49  return Groups::Group::createGroup(path, hFile.get());
50  }
51 
53  return Groups::Group::openGroup(path, hFile.get());
54  }
55 
56  Database_impl::Database_impl() : hFileImage(fs::impl::getUniqueVROOTname(), 10 * 1024 * 1024)
57  { }
58 
59  Database_impl::Database_impl(size_t virtualMemSizeInBytes) : hFileImage(fs::impl::getUniqueVROOTname(), virtualMemSizeInBytes)
60  { }
61 
63 
65 
67 
69  const std::string &location)
70  {
71  const auto flag_truncate = fs::hdf5::getHDF5IOflags(fs::IOopenFlags::TRUNCATE);
72 
73  sfs::path pBase(location);
74  sfs::create_directories(pBase);
75  Expects(sfs::exists(pBase));
76 
77  sfs::create_directory(pBase / "3d_Structures");
78  sfs::create_directory(pBase / "Physical_Particle_Properties");
79  sfs::create_directory(pBase / "Extended_Scattering_Variables");
80  sfs::create_directory(pBase / "Essential_Scattering_Variables");
81  sfs::create_directory(pBase / "Testing");
82 
83  Database_impl::makeDatabaseFileStandard((pBase / "3d_Structures" / "3dS-1.hdf5").string());
84  Database_impl::makeDatabaseFileStandard((pBase / "3d_Structures" / "3dS-2.hdf5").string());
85  Database_impl::makeDatabaseFileStandard((pBase / "3d_Structures" / "3dS-3.hdf5").string());
86  Database_impl::makeDatabaseFileStandard((pBase / "Physical_Particle_Properties" / "ppp.hdf5").string());
87  Database_impl::makeDatabaseFileStandard((pBase / "Essential_Scattering_Variables" / "esv1.hdf5").string());
88  Database_impl::makeDatabaseFileStandard((pBase / "Essential_Scattering_Variables" / "esv2.hdf5").string());
89  Database_impl::makeDatabaseFileStandard((pBase / "Testing" / "scratch.hdf5").string());
90  Database_impl::makeDatabaseFileStandard((pBase / "metadata.hdf5").string());
91 
93  }
94 
96  const std::string &location) {
97  const auto flag_truncate = fs::hdf5::getHDF5IOflags(fs::IOopenFlags::TRUNCATE);
98 
99  //sfs::path pBase(location);
100  //sfs::create_directories(pBase);
101  //Expects(sfs::exists(pBase));
103 
105  }
106 
108  {
109  auto res = std::make_unique<Database_impl>();
110  //std::unique_ptr<Database_impl, mem::icedb_delete<Database_impl> > res(new Database_impl);
111  //= std::make_unique(<Database_impl, mem::icedb_delete<Database_impl> >();
112  res->hFile = res->hFileImage.getHFile();
113 
114  return std::move(res);
115  }
116 
117 
119  const std::string &location, fs::IOopenFlags flags)
120  {
121  sfs::path pBaseS = fs::impl::resolveSymLinks(location);
122  if (!sfs::exists(pBaseS)) {
123  if (flags == fs::IOopenFlags::TRUNCATE || flags == fs::IOopenFlags::CREATE) {
124  return createSingleFileDatabase(location);
125  } else throw(std::invalid_argument("Attempting to open a database root that does not exist. Did you mean to first create this database?"));
126  }
128  unsigned int Hflags = fs::hdf5::getHDF5IOflags(flags);
129  auto res = std::make_unique<Database_impl>();
130  //std::unique_ptr<Database_impl, mem::icedb_delete<Database_impl> > res(new Database_impl);
131  //= std::make_unique(<Database_impl, mem::icedb_delete<Database_impl> >();
132 
133  Expects(mountFiles.size() > 0);
134  if (mountFiles.size() == 1) {
135  res->hFile = std::make_shared<H5::H5File>(
136  mountFiles.begin()->first.string().c_str(), Hflags, H5P_DEFAULT);
137  }
138  else {
139  res->hFile = res->hFileImage.getHFile();
140 
141  // Check for the existence of the appropriate groups in the relative path tree
142  // Create any missing groups in the relative path tree
143  for (const auto &toMount : mountFiles) {
144  std::string mountStr = toMount.second;
145  if (mountStr == "index.hdf5") continue;
146  H5::Group grp = icedb::fs::hdf5::createGroupStructure(mountStr, *(res->hFile.get()));
147  // Open files and mount in the relative path tree
148  std::shared_ptr<H5::H5File> newHfile = std::make_shared<H5::H5File>(toMount.first.string(), Hflags);
149  //res._impl->mappedFiles[toMount.second] = newHfile;
150 
153  H5::PropList pl(H5P_DEFAULT);
154  res->hFile->mount(toMount.second, *(newHfile.get()), pl);
155  }
156  }
157 
158  return std::move(res);
159  }
160 
161  void Database::indexDatabase(const std::string &location)
162  {
163  sfs::path pBaseS = fs::impl::resolveSymlinkPathandForceExists(location);
165  Expects(mountFiles.size() > 0);
166  if (mountFiles.size() == 1) return;
167 
168  std::unique_ptr<Database_impl> res = std::make_unique<Database_impl>();
169  res->hFile = Database_impl::makeDatabaseFileStandard(location + "/index.hdf5");
170 
171  // Check for the existence of the appropriate groups in the relative path tree
172  // Create any missing groups in the relative path tree, and then make the link.
173  for (const auto &toMount : mountFiles) {
174  std::string mountStr = toMount.second;
175  if (mountStr == "index.hdf5") continue;
176  auto explodedPath = fs::hdf5::explodeHDF5groupPath(mountStr);
177  std::string linkName = *(explodedPath.rbegin());
178  explodedPath.pop_back();
179 
183  if (explodedPath.size()) {
184  auto grp = fs::hdf5::createGroupStructure(explodedPath, *(res->hFile.get()));
185  H5Lcreate_external(toMount.second.c_str(), "/", grp.getLocId(), linkName.c_str(), H5P_DEFAULT, H5P_DEFAULT);
186  } else {
187  H5Lcreate_external(toMount.second.c_str(), "/", res->hFile->getLocId(), linkName.c_str(), H5P_DEFAULT, H5P_DEFAULT);
188  }
189  }
190 
191  }
192 
194  {
195  H5::Group grp = icedb::fs::hdf5::createGroupStructure(groupName, *(hFile.get()));
196  std::shared_ptr<H5::Group> ngrp = std::make_shared<H5::Group>(grp);
197  return Groups::Group::openGroup(ngrp);
198  }
199  Groups::Group::Group_ptr Database_impl::createGroupStructure(const std::vector<std::string> &groupNames)
200  {
201  H5::Group grp = icedb::fs::hdf5::createGroupStructure(groupNames, *(hFile.get()));
202  std::shared_ptr<H5::Group> ngrp = std::make_shared<H5::Group>(grp);
203  return Groups::Group::openGroup(ngrp);
204  }
205 
206 
207  }
208 }
static void indexDatabase(const std::string &location)
Definition: databases.cpp:161
H5::Group createGroupStructure(const std::string &groupName, ICEDB_H5_GROUP_OWNER &base)
IOopenFlags
Definition: fs.hpp:16
Groups::Group::Group_ptr openGroup(const std::string &path) override
Definition: databases.cpp:52
file_image hFileImage
Used if a virtual base is needed (the typical case)
file_image(const std::string &filename, size_t desiredSizeInBytes)
Definition: databases.cpp:17
sfs::path resolveSymLinks(const sfs::path &base)
Finds out where a symbolic link points to.
Definition: fs_backend.cpp:16
virtual Group_ptr createGroup(const std::string &groupName)=0
Create a group.
std::shared_ptr< H5::H5File > getHFile() const
Definition: databases.cpp:16
static Database_ptr createSampleDatabase(const std::string &location)
Definition: databases.cpp:68
sfs::path resolveSymlinkPathandForceExists(const std::string &location)
Like resolveSymLinks, but throw if the resulting path does not exist.
Definition: fs_backend.cpp:73
std::unique_ptr< Database > Database_ptr
Definition: Database.hpp:20
icedb::Groups::Group::Group_ptr basegrp
Shapes get written to this location in the output database.
Definition: shapes-main.cpp:79
static Database_ptr createSingleFileDatabase(const std::string &location)
Definition: databases.cpp:95
virtual Group_ptr openGroup(const std::string &groupName) const =0
Opens a group.
std::vector< std::string > explodeHDF5groupPath(const std::string &s)
std::shared_ptr< H5::H5File > hFile
std::unique_ptr< Groups::Group > Group_ptr
Definition: Group.hpp:30
std::shared_ptr< H5::H5File > hFile
std::vector< std::pair< sfs::path, std::string > > CollectedFilesRet_Type
File path, relative mount point.
Definition: fs_backend.hpp:45
static Database_ptr openVirtualDatabase(size_t memSizeInBytes)
Definition: databases.cpp:107
unsigned int getHDF5IOflags(fs::IOopenFlags flags)
static Database_ptr openDatabase(const std::string &location, fs::IOopenFlags flags=fs::IOopenFlags::READ_ONLY)
Definition: databases.cpp:118
static std::shared_ptr< H5::H5File > makeDatabaseFileStandard(const std::string &p)
Definition: databases.cpp:34
Groups::Group::Group_ptr createGroupStructure(const std::string &groupName) override
Definition: databases.cpp:193
std::vector< char > buffer
CollectedFilesRet_Type collectActualHDF5files(const sfs::path &pBaseS)
Like collectDatasetFiles for HDF5 files, but then check that these files are, indeed, HDF5 files.
Definition: fs_backend.cpp:82
Groups::Group::Group_ptr createGroup(const std::string &path) override
Definition: databases.cpp:48
std::string getUniqueVROOTname()
Generate a unique string, used in memort-only HDF5 file trees.
Definition: fs_backend.cpp:100