IODA
Factory.cpp
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020-2021 UCAR
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #include "ioda/Engines/Factory.h"
9 
10 #include <string>
11 
12 #include "ioda/Engines/HH.h"
13 #include "ioda/Engines/ObsStore.h"
14 #include "ioda/Exception.h"
15 #include "ioda/Group.h"
16 #include "ioda/defs.h"
17 
18 namespace ioda {
19 namespace Engines {
20 Group constructFromCmdLine(int argc, char** argv, const std::string& defaultFilename) {
21  /* Options:
22  Start with --ioda-engine-options. All options after this are
23  positional options.
24 
25  --ioda-engine-options name parameters...
26 
27  Currently supported engine names:
28  1. HDF5 with file backend [HDF5-file]
29  2. HDF5 in-memory backend [HDF5-mem]
30 3. ObsStore in-memory backend [obs-store]
31 
32  Engine parameters:
33  1. Needs a file name, file opening properties [create, open],
34  access mode [read, read_write, create, truncate].
35  2. Needs a file name, file size increment length (in MB), flush_on_close (bool).
36  3. None
37  */
39  BackendNames backendName;
40 
41  using std::string;
42  std::vector<string> opts(argc);
43  for (size_t i = 0; i < (size_t)argc; ++i) opts[i] = string(argv[i]);
44 
45  // Find the "--ioda-engine-options" option.
46  // If none is specified, use a default.
47  auto it = std::find(opts.cbegin(), opts.cend(), "--ioda-engine-options");
48  if (it == opts.cend()) {
49  // No options --> create a file using the defaultFileName
50  backendName = BackendNames::Hdf5File;
51  params.fileName = defaultFilename;
54  } else {
55  ++it;
56  if (it == opts.cend()) {
57  throw Exception("Bad option --ioda-engine-options. Got the "
58  "--ioda-engine-options token but nothing else.", ioda_Here());
59  }
60 
61  // convert array of c-string options into vector of strings
62  auto readOpts = [&opts, &it](size_t n) -> std::vector<string> {
63  std::vector<string> res(n);
64  for (size_t i = 0; i < n; ++i) {
65  ++it;
66  if (it == opts.cend())
67  throw Exception("Bad option --ioda-engine-options. "
68  "Wrong number of elements.", ioda_Here()).add("Expected", n);
69  res[i] = std::string(*it);
70  }
71  return res;
72  };
73 
74  string sEngine = *it;
75  if (sEngine == "HDF5-file") {
76  auto engineOpts = readOpts(3);
77  backendName = BackendNames::Hdf5File;
78  params.fileName = engineOpts[0];
79 
80  enum class open_or_create {
81  open,
82  create
83  } action
84  = (engineOpts[1] == "create") ? open_or_create::create : open_or_create::open;
85  if (action == open_or_create::open) {
86  // open action
88  params.openMode = (engineOpts[2] == "read_write") ? BackendOpenModes::Read_Write
90  } else {
91  // create action
93  params.createMode = (engineOpts[2] == "truncate") ? BackendCreateModes::Truncate_If_Exists
95  }
96  } else if (sEngine == "HDF5-mem") {
97  auto engineOpts = readOpts(3);
98  // TODO(ryan): Allow open / create
99  // enum class open_or_create { open, create } action
100  // = (engineOpts[1] == "create") ? open_or_create::create :
101  // open_or_create::open;
102 
103  backendName = BackendNames::Hdf5Mem;
104  params.fileName = engineOpts[0];
107 
108  string sAllocLen_MB = engineOpts[1];
109  string sFlush = engineOpts[2];
110 
111  params.allocBytes = gsl::narrow<size_t>(((size_t)std::stoul(sAllocLen_MB)) * 1024 * 1024);
112  params.flush = (sFlush == "true");
113  } else if (sEngine == "obs-store") {
114  backendName = BackendNames::ObsStore;
115  } else {
116  throw Exception("Bad option --ioda-engine-options. "
117  "Unknown engine.", ioda_Here()).add("Engine", sEngine);
118  }
119  }
120  return constructBackend(backendName, params);
121 }
122 
124  Group backend;
125  if (name == BackendNames::Hdf5File) {
126  if (params.action == BackendFileActions::Open)
127  return HH::openFile(params.fileName, params.openMode);
128  if (params.action == BackendFileActions::Create)
130  throw Exception("Unknown BackendFileActions value", ioda_Here());
131  }
132  if (name == BackendNames::Hdf5Mem) {
133  if (params.action == BackendFileActions::Open)
134  return HH::openMemoryFile(params.fileName, params.openMode, params.flush, params.allocBytes);
135  if (params.action == BackendFileActions::Create)
136  return HH::createMemoryFile(params.fileName, params.createMode, params.flush,
137  params.allocBytes);
138  throw Exception("Unknown BackendFileActions value", ioda_Here());
139  }
141 
142  // If we get to here, then we have a backend name that is
143  // not implemented yet.
144  throw Exception("Backend not implemented yet", ioda_Here());
145 }
146 } // namespace Engines
147 } // namespace ioda
IODA's error system.
Definitions for setting up backends with file and memory I/O.
Interfaces for ioda::Group and related classes.
HDF5 engine.
ObsStore engine.
The ioda exception class.
Definition: Exception.h:54
Exception & add(const std::string &key, const T value)
Add a key-value pair to the error message.
Definition: Exception.h:75
Groups are a new implementation of ObsSpaces.
Definition: Group.h:159
Common preprocessor definitions used throughout IODA.
IODA_DL Group createFile(const std::string &filename, BackendCreateModes mode, HDF5_Version_Range compat=defaultVersionRange())
Create a ioda::Group backed by an HDF5 file.
Definition: HH.cpp:113
IODA_DL Group openFile(const std::string &filename, BackendOpenModes mode, HDF5_Version_Range compat=defaultVersionRange())
Open a ioda::Group backed by an HDF5 file.
Definition: HH.cpp:135
IODA_DL Group openMemoryFile(const std::string &filename, BackendOpenModes mode=BackendOpenModes::Read_Only, bool flush_on_close=false, size_t increment_len_bytes=1000000, HDF5_Version_Range compat=defaultVersionRange())
Map an HDF5 file in memory and open a ioda::Group.
Definition: HH.cpp:154
IODA_DL Group createMemoryFile(const std::string &filename, BackendCreateModes mode, bool flush_on_close=false, size_t increment_len_bytes=1000000, HDF5_Version_Range compat=defaultVersionRange())
Create a ioda::Group backed by the HDF5 in-memory-store.
Definition: HH.cpp:86
std::pair< HDF5_Version, HDF5_Version > HDF5_Version_Range
Definition: HH.h:40
@ V18
Use the latest HDF5 v1.8 format for storing objects.
@ V110
Use the latest HDF5 v1.10 format for storing objects.
IODA_DL Group createRootGroup()
Create a ioda::Group backed by an OsbStore Group object.
Definition: ObsStore.cpp:24
IODA_DL Group constructFromCmdLine(int argc, char **argv, const std::string &defaultFilename)
This is a wrapper function around the constructBackend function for creating a backend based on comma...
Definition: Factory.cpp:20
BackendNames
Backend names.
Definition: Factory.h:27
IODA_DL Group constructBackend(BackendNames name, BackendCreationParameters &params)
This is a simple factory style function that will instantiate a different backend based on a given na...
Definition: Factory.cpp:123
@ Open
Open an existing file.
@ Hdf5Mem
HDF5 in-memory "file".
@ Hdf5File
HDF5 file access.
@ ObsStore
ObsStore in-memory.
@ Fail_If_Exists
If the file already exists, fail with an error.
@ Truncate_If_Exists
If the file already exists, overwrite it.
@ Read_Write
Open the file in read-write mode.
@ Read_Only
Open the file in read-only mode.
#define ioda_Here()
Used to specify backend creation-time properties.
Definition: Factory.h:56