Midas C++ API - midas::odb (odbxx)
This page explains how the midas::odb C++ interface to the ODB behaves, and contains its full API reference (odbxx.h).
For the concepts and day-to-day use, see ODB: overview.
For task-based examples (and the equivalent code for the other C++ APIs and other languages), see ODB: programming.
midas::odb is a modern C++ interface to the ODB. A midas::odb object behaves like a "magic dictionary" that is kept in sync with the ODB: reading a value from the object re-reads it from the ODB, and assigning a value writes it to the ODB straight away. There are no handles, sizes or TID_xxx types to manage, and values convert to and from the usual C++ types, including std::string, std::vector and std::array.
#include "midas.h"
#include "odbxx.h"
cm_connect_experiment("", "", "my_program", nullptr);
midas::odb exp("/Experiment");
int timeout = exp["Transition timeout"]; // Read from the ODB
exp["Transition timeout"] = timeout + 100; // Written to the ODB immediately
midas::odb needs C++11 or later. When accessing the live ODB, you must call cm_connect_experiment() before creating any object that refers to an ODB path. Objects that read a saved ODB dump (see Offline use) work without a midas connection.
The program examples/odbxx/odbxx_test.cxx in the midas repository exercises almost every feature described on this page.
Using midas::odb
Paths and values
A string that starts with / is an ODB path. Any other string is a plain string value:
midas::odb settings("/Equipment/Trigger/Settings"); // Connected to the ODB
midas::odb label("detector"); // A local string value
Connecting to a path that doesn't exist creates it as an empty directory. If a misspelled path should be an error instead, check it first with midas::odb::exists(). Subkeys are accessed with [], and you can index with a relative path such as o["Logger/Write data"]. As in the rest of the ODB, key names are case-insensitive.
You can read a single value without keeping the object around:
int run_number = midas::odb("/Runinfo/Run number");
Keep an object for the directory when you access several values from it, so that the directory is only looked up once.
Reading and writing values
A value is read by converting it to a C++ type, and written by assigning to it. Increment, decrement and compound assignment (+=, -=, *=, /=) read the current value, update it and write it back. Binary arithmetic (o["Gain"] + 1.0) and comparisons (o["Gain"] > 1.0) return ordinary C++ values and don't change the ODB.
midas::odb o("/Equipment/Trigger/Settings");
int threshold = o["Threshold"];
std::string name = o["Name"];
o["Threshold"] = 30;
o["Counter"]++;
o["Gain"] *= 1.1;
Assigning to a subkey that doesn't exist creates it, with a type matching the C++ value. To read a value that might not exist yet, call the object with a default value. A missing key is created with that value, and an existing key keeps its current value:
double gain = o["New gain"](1.0);
Arrays and strings
ODB arrays convert to and from std::vector, and can also be assigned from a std::array. Use [] with an integer to access a single element, and size() and resize() to query and change the number of elements:
std::vector<float> hv = o["Voltages"];
o["Voltages"][1] = 1500.0f;
o["Voltages"] = std::vector<float>(16, 1200.0f);
o["Voltages"].resize(32);
for (float v : o["Voltages"])
std::cout << v << "\n";
Some behaviours to be aware of:
- Writing to an element beyond the end of an array enlarges the array. Call
set_auto_enlarge_array(false)to throwmidas::odb_out_of_rangeinstead - Arithmetic operators applied to a whole array apply to every element, so
o["Gains"] *= 2.0doubles all the gains - Strings are returned as
std::string, and string arrays asstd::vector<std::string>. Assigning a shorter string may shrink the ODB string length; callset_preserve_string_size(true)to keep the existing length
Iterating over subkeys
Iterating over a directory gives one midas::odb object per subkey. Use named_items() with structured bindings if you also want the name, and contains() to check whether a subkey exists without creating it:
midas::odb exp("/Experiment");
for (midas::odb& subkey : exp)
std::cout << subkey.get_name() << " = " << subkey << "\n";
for (auto& [name, subkey] : exp.named_items())
std::cout << name << " = " << subkey << "\n";
for (auto it = exp.begin(); it != exp.end(); ++it) {
midas::odb& subkey = *it;
std::cout << subkey.get_full_path() << "\n";
}
if (exp.contains("Transition timeout"))
std::cout << "Found it\n";
named_items() throws midas::odb_type_error if the object isn't a directory. items() returns the object itself, so for (midas::odb& subkey : exp.items()) is the same as the first loop. contains() accepts a direct subkey name or a relative path.
Key information and management
Objects can tell you about the ODB key they represent:
midas::odb o("/Equipment/Trigger/Settings");
std::string path = o.get_full_path(); // "/Equipment/Trigger/Settings"
std::string parent = o.get_parent_path(); // "/Equipment/Trigger"
std::string name = o.get_name(); // "Settings"
int n = o.size(); // Number of values (1 for a single value)
bool dir = o.is_directory(); // A directory
bool array = o.is_array(); // A value with more than one element
bool scalar = o.is_scalar(); // A single value
std::string type = o.type_name(); // e.g. "INT32", "STRING" or "KEY"
HNDLE hKey = o.get_hkey(); // For use with the low-level db_xxx functions
For an array, type_name() gives the type of its elements. An empty object (not yet assigned or connected) has the type name "NULL", and isn't a directory, array or single value.
Some static functions work on ODB paths without creating an object. Paths are always relative to the top of the ODB:
bool found = midas::odb::exists("/Equipment/Trigger/Settings");
midas::odb::create("/Equipment/Trigger/Settings/Gain", TID_FLOAT); // Create one key
midas::odb::delete_key("/Equipment/Trigger/Settings/Gain");
To delete the key an object represents, call o.delete_key(). Unlike accessing a missing subkey with [], exists() never creates anything.
Defining a directory structure
A program usually expects its settings in a particular layout. You can describe that layout, with default values, using an initializer list, then connect() it to the ODB:
midas::odb settings = {
{"Threshold (mV)", -30}, // TID_INT32
{"Scale factor", 1.5f}, // TID_FLOAT (note the f)
{"Enabled", true}, // TID_BOOL
{"Label", "detector"}, // TID_STRING
{"Gains", {1.0, 1.1, 1.2}}, // TID_DOUBLE array
{"Masks", std::array<int, 32>{}}, // TID_INT32 array with 32 elements
{"Comment", std::string(255, '\0')}, // TID_STRING of length 255
{"Calibration", {{"Offset", 0.0}, {"Gain", 1.0}}} // Subdirectory
};
settings.connect("/Equipment/Trigger/Settings");
The ODB type is taken from the C++ type, so write 1.5f for a TID_FLOAT (1.5 would create a TID_DOUBLE). Use std::array to create an array of a fixed size, and a string of '\0' characters to reserve the length of a string.
There are three ways to connect the structure, which differ in how they treat keys that already exist:
| Situation | connect(path) |
connect(path, true) |
connect_and_fix_structure(path) |
|---|---|---|---|
| Key in the ODB and in your code | Keep the ODB value | Overwrite with your default | Keep the ODB value |
| Key only in your code | Create with your default | Create with your default | Create with your default |
| Key only in the ODB | Leave alone | Leave alone | Delete |
| Order of keys | Unchanged | Unchanged | Changed to match your code |
In all cases, an existing key whose type differs from your default is deleted and re-created with your default type and value. connect_and_fix_structure() behaves like the old db_check_record() function. You can't connect a structure to the root of the ODB (/).
Comparing trees
Use compare() to check two midas::odb objects without writing either tree to the ODB or a file:
std::string compare(const odb& other,
const std::vector<std::string>& ignore_values = {}) const;
The result is an empty string if the trees match, or a diagnostic string containing the differences. Diagnostics contain relative key paths, zero-based array indices, and neutral reasons: missing, type differs, array size differs, or differs. They do not identify either object or include raw values, so null characters in string values cannot truncate a message passed to cm_msg().
midas::odb expected = {
{"Threshold", 60.f},
{"Enabled", true},
{"Calibration", {{"Gain", 1.0}}}
};
midas::odb existing("/Equipment/Trigger/Settings");
std::string differences = expected.compare(existing);
if (!differences.empty())
cm_msg(MERROR, "frontend_init", "Settings differ:%s", differences.c_str());
For example, a different threshold produces a diagnostic such as:
Threshold[0]: differs
The comparison recursively checks missing keys on either side, MIDAS types, array sizes, and values. It reports every differing array element. Key order, root names, access modes, timestamps, and reserved string capacity do not affect equality. Floating-point values are compared exactly, with two NaNs treated as equal.
By default, every key and value is checked. The optional ignore_values list skips values at exact relative key paths, while still checking that those keys exist and have matching types and array sizes. For example, operational switches can retain their current state while their array lengths are checked:
std::string differences = expected.compare(existing, {"Output On", "Enabled"});
Application-specific context belongs in the caller's error message:
std::string differences = expected.compare(existing, {"Output On", "Enabled"});
if (!differences.empty())
cm_msg(MERROR, "frontend_init", "Settings differ between frontend code and ODB:%s",
differences.c_str());
A key present in only one object is reported as Threshold: missing; use compare_details() to identify which object lacks the key.
Use a path such as Subdir/Enabled for a nested value. Listing a directory does not exclude its descendants. A size mismatch is included in the returned diagnostics even for an excluded value; the caller can report it with cm_msg(MERROR, ...) and throw to stop initialization.
For decisions based on the kind of difference, use the structured result from compare_details():
std::vector<midas::odb::difference> differences = expected.compare_details(existing);
for (const auto& entry : differences) {
if (entry.kind == midas::odb::difference_kind::missing_in_other)
continue; // This key may be added later with expected.connect(path).
std::cerr << entry.message() << "\n";
}
Each entry contains a relative path and a kind: missing_in_this, missing_in_other, type, array_size, or value. this is the object on which the method is called; other is its argument. entry.message() returns the same neutral diagnostic text used by compare(). A completely missing directory is reported once at its path rather than once per descendant. Both methods accept the same ignore_values argument and leave the objects unchanged.
For example, a frontend can allow missing_in_other when comparing its code defaults with existing ODB settings, while treating all other differences as errors. Only after validating all differences should it unlock the settings and call expected.connect(path) to add missing keys and retain existing values. Comparison itself never creates the missing keys.
If automatic reads are enabled on an input object, compare() refreshes a private copy from its backing ODB before comparing. If automatic reads are disabled, it compares the current local values. Neither input object is modified. The method also works with file- and string-backed objects. A mismatch is returned as text; ODB read failures can still throw the usual exceptions.
Arrays filled with a default value
Use midas::odb::array(value, size) to construct an array of a runtime size, with every element initialized to the same value:
const size_t channels = 18;
midas::odb settings = {
{"Enabled", midas::odb::array(true, channels)},
{"Output On", midas::odb::array(false, channels)},
{"Voltage limit", midas::odb::array(60.f, channels)},
{"Names", midas::odb::array(std::string(31, '\0'), channels)}
};
settings.connect("/Equipment/HV/Settings");
The MIDAS type is inferred from value, just as for scalar defaults: true produces TID_BOOL, 60.f produces TID_FLOAT, and 60.0 produces TID_DOUBLE. Strings are copied independently for each element. A string beginning with / is a literal value, not an ODB path.
The factory allocates and fills the array directly in local memory, leaving automatic reads and writes at their normal default of true. Once connected, the array therefore has the same automatic read/write behavior as other ODB values; no explicit flag changes are needed. To build or edit a local tree without writing changes, explicitly disable automatic reads and writes on that tree.
size must be between 1 and INT_MAX, inclusive; zero and oversized lengths throw midas::odb_out_of_range. A size of 1 produces a single-value key. A null-filled string such as std::string(31, '\0') reserves the initial string length for every element.
Automatic reads and writes
By default, every read of a value fetches it from the ODB, and every assignment writes it to the ODB. This means your values are always up to date, but each access costs an ODB operation. For a program connected to a remote experiment, each operation is a network round trip, so reading 1000 values one at a time can take several seconds.
There are two ways to reduce this cost:
- Read a tree in one go: pass
trueas the second constructor argument (midas::odb o("/Test/Settings", true)). This fetches the whole tree as a single XML transfer, instead of one read per value. It only speeds up creating the object; later reads and writes are still individual ODB operations - Turn off automatic reads and writes: call
set_auto_refresh_read(false)and/orset_auto_refresh_write(false). Reads then return the local copy, and assignments only change the local copy. Callread()to refresh the local copy from the ODB, andwrite()to send it to the ODB
midas::odb o("/Test/Settings", true);
o.set_auto_refresh_read(false);
o.set_auto_refresh_write(false);
for (int i = 0; i < 10; i++)
o["Values"][i] = i; // Only changes the local copy
o.write(true); // Write only the values that have changed
While automatic writes are off, every change marks the value as "dirty". write() writes every value in the tree, while write(true) only writes the dirty values and clears their dirty flags. Arrays have one dirty flag for the whole array, so changing any element writes the whole array.
To read or write a single array element explicitly, use read(index) and write(index, str_size) (str_size sets the ODB string length for strings, or 0 for the default). Note that if you have selected an element with [] since the last write, write() only writes that element.
When automatic reads and writes are off, keeping the local copy in step with the ODB is your responsibility. Your reads won't see changes made by other programs until you call read() (use a watch if you need to know when that happens), and a later write() can overwrite newer ODB values with your older local values.
midas::odb::set_debug(true) prints every ODB operation that midas::odb performs, which is a useful way to check how many you're making.
Behaviour flags
Each object has a set of flags that control its behaviour. They are read with is_xxx() and changed with set_xxx(), and changing a flag on a directory also changes it for everything inside it.
| Flag | Default | Effect when set |
|---|---|---|
auto_refresh_read |
true |
Every read fetches the value from the ODB |
auto_refresh_write |
true |
Every assignment writes the value to the ODB |
auto_create |
true |
Accessing a missing subkey creates it, rather than throwing midas::odb_missing_key |
auto_enlarge_array |
true |
Writing past the end of an array enlarges it, rather than throwing midas::odb_out_of_range |
write_protect |
false |
Any change throws midas::odb_read_only |
trigger_hotlink |
true |
Writes notify other programs that have hotlinks on the value |
preserve_string_size |
false |
Assigning a shorter string keeps the ODB string length |
dirty |
false |
The value was changed while automatic writes were off |
Objects that read a saved ODB dump use different defaults; see Offline use.
Watching for changes
watch() registers a function that is called whenever a value in the object changes in the ODB, whoever changed it. It's passed the midas::odb object of the key that changed, which for a directory may be a subkey rather than the directory you watched:
midas::odb settings("/Equipment/Trigger/Settings");
settings.watch([](midas::odb& changed) {
std::cout << changed.get_full_path() << " = " << changed << "\n";
});
while (cm_yield(100) != RPC_SHUTDOWN) {
// Callbacks are called from within cm_yield()
}
Callbacks are only called from within cm_yield(), so your program must call it regularly. Frontends using mfe or TMFE do this for you.
The callback can be a lambda, a free function, or a member function bound to an object with std::bind:
class MyEquipment {
public:
void settings_changed(midas::odb& changed) {
// Apply the changed value to the hardware
}
void init() {
midas::odb settings("/Equipment/Trigger/Settings");
settings.watch(std::bind(&MyEquipment::settings_changed, this, std::placeholders::_1));
}
};
For an array, get_last_index() inside the callback returns the index of the element that changed (0 is the first element), or a negative value if the whole array was written. Call it inside the callback, as it is reset afterwards:
settings.watch([](midas::odb& changed) {
int index = changed.get_last_index();
if (changed.is_array() && index >= 0) {
int value = changed[index];
std::cout << changed.get_full_path() << "[" << index << "] = " << value << "\n";
}
});
watch() keeps its own copy of the tree, so the callback carries on after the original object is destroyed (as in the init() example above). To remove it, call unwatch() on any object for the same ODB key.
Offline use
The same code can read a saved ODB dump instead of the live ODB, which is useful in analysis programs. Call set_odb_source() before creating your objects:
midas::odb::set_odb_source(midas::odb::FILE, "run00123.json"); // JSON or XML file
// or: midas::odb::set_odb_source(midas::odb::STRING, dump); // JSON or XML in a string
midas::odb settings("/Equipment/Trigger/Settings");
int threshold = settings["Threshold (mV)"];
midas::odb::set_odb_source(midas::odb::ONLINE); // Back to the live ODB
ODB: programming shows how to get the dump from a midas data file.
If you need the live ODB and a dump at the same time, use midas::odb::file() or midas::odb::string() instead. These return an independent tree for a JSON file or string, without changing the source used by other objects:
midas::odb live("/Equipment/Trigger/Settings");
midas::odb saved = midas::odb::file("run00123.json");
int live_threshold = live["Threshold (mV)"];
int saved_threshold = saved["Equipment"]["Trigger"]["Settings"]["Threshold (mV)"];
Offline objects never change the live ODB. Automatic reads, writes, key creation, array enlargement and hotlink triggering are all off, and assigning to a value only changes the in-memory copy. read() and write() only work with the live ODB (write() throws an exception for an offline object). To keep your changes, use:
save(filename)to write the object to a JSON file. Saving/keeps the full hierarchy of the original dump, while saving a subtree writes that subtree as the top-level keysave()to write an object fromfile()back to the file it was read fromdump()to get the object as a JSON string, whichstring()can load again
A saved file can be loaded into the live ODB with midas::odb::load(). save() writes the object's directory itself as the top-level key, so load the file into the parent directory to restore it in the same place. See ODB: programming for saving and loading with the other APIs.
Errors
midas::odb reports errors by throwing exceptions. All of them can be caught as midas::odb_error, and there are more specific classes for the common types of error (listed under Exceptions):
try {
settings.set_auto_create(false);
int threshold = settings["Threshold"];
} catch (const midas::odb_missing_key& e) {
std::cerr << "Missing setting: " << e.what() << "\n";
} catch (const midas::odb_error& e) {
std::cerr << "Other ODB error: " << e.what() << "\n";
}
For compatibility with older code, midas::odb_out_of_range also derives from std::out_of_range, and all the other exceptions derive from mexception (and so can be caught as std::runtime_error).
Example
This program defines its settings with default values, prints them, and then prints any changes until it is stopped:
#include <iostream>
#include "midas.h"
#include "odbxx.h"
void settings_changed(midas::odb& changed) {
std::cout << changed.get_full_path() << " changed to " << changed << "\n";
}
int main() {
cm_connect_experiment("", "", "odbxx_example", nullptr);
// Create any settings that don't exist yet, and keep the values of those that do
midas::odb settings = {
{"Threshold (mV)", -30},
{"Width (ns)", 20},
{"Coincidence", true},
{"Gains", std::array<float, 16>{}},
{"Channel labels", std::array<std::string, 16>{}}
};
settings.connect("/Equipment/Trigger/Settings");
int threshold = settings["Threshold (mV)"];
std::vector<float> gains = settings["Gains"];
std::cout << "Threshold is " << threshold << " mV, gain[0] is " << gains[0] << "\n";
settings.watch(settings_changed);
// cm_yield() calls settings_changed() when a setting changes
while (true) {
int status = cm_yield(100);
if (status == SS_ABORT || status == RPC_SHUTDOWN)
break;
}
cm_disconnect_experiment();
return 0;
}
Reference
Creating and connecting
odb
Note: this method has 10 different signatures.
odb
odb()
Default constructor
Defined in include/odbxx.h:680
odb
odb(const odb &o)
Deep copy constructor
Declared in include/odbxx.h:702, defined in src/odbxx.cxx:375
odb
template<typename T>
odb(T v)
Constructor for single basic types
Defined in include/odbxx.h:708
odb
odb(std::initializer_list<std::pair<const char *, midas::odb>> list)
Constructor with std::initializer_list
Defined in include/odbxx.h:734
odb
template<typename T>
odb(std::initializer_list<T> list)
Constructor with basic type array
Defined in include/odbxx.h:762
odb
template<typename T, size_t SIZE>
odb(const std::array<T, SIZE> &arr)
Constructor with basic explicit array
Defined in include/odbxx.h:780
odb
template<size_t SIZE>
odb(const std::array<std::string, SIZE> &arr)
Constructor with explicit array of std::string
Defined in include/odbxx.h:796
odb
odb(const std::string &path, bool init_via_xml = false)
Constructor for std::string
Defined in include/odbxx.h:813
odb
odb(const char *s)
Constructor for C string
Defined in include/odbxx.h:892
odb
odb(std::initializer_list<const char *> list)
Constructor with const char * array
Defined in include/odbxx.h:896
connect
Note: this method has 2 different signatures.
connect
void connect(const std::string &path, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults = false)
connect function with separated path and key name
Declared in include/odbxx.h:1599, defined in src/odbxx.cxx:1519
connect
void connect(std::string str, bool write_defaults = false, bool delete_keys_not_in_defaults = false)
send key definitions and data with optional subkeys to certain path in ODB
Declared in include/odbxx.h:1600, defined in src/odbxx.cxx:1570
connect_and_fix_structure
void connect_and_fix_structure(std::string path)
shorthand for the same behavior as db_check_record:
- keep values of keys that already exist with the correct type
- add keys that user provided but aren't in ODB already
- delete keys that are in ODB but not in user's settings
- re-order ODB keys to match user's order
Declared in include/odbxx.h:1601, defined in src/odbxx.cxx:1601
exists
static
static bool exists(const std::string &name)
check if a key exists in the ODB
Declared in include/odbxx.h:1590, defined in src/odbxx.cxx:80
create
static
static int create(const char *name, int type = TID_KEY)
create ODB key
Declared in include/odbxx.h:1589, defined in src/odbxx.cxx:182
delete_key
Note: this method has 2 different signatures.
delete_key
static
static int delete_key(const std::string &name)
delete a key in the ODB
Declared in include/odbxx.h:1591, defined in src/odbxx.cxx:89
delete_key
void delete_key()
Declared in include/odbxx.h:1629, defined in src/odbxx.cxx:1615
load
static
static void load(const std::string &filename, const std::string &odb_path)
load file into ODB
Declared in include/odbxx.h:1592, defined in src/odbxx.cxx:106
Values and arrays
operator T
template<typename T, typename std::enable_if< std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value || std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value || std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value || std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value || std::is_same<T, bool>::value || std::is_same<T, float>::value || std::is_same<T, double>::value, T>::type * = nullptr>
operator T()
overload all other conversion operators
Defined in include/odbxx.h:1082
operator std::string
operator std::string()
overload conversion operator for std::string
Defined in include/odbxx.h:1052
operator std::vector<T>
template<typename T>
operator std::vector<T>()
overload conversion operator for std::vector<T>
Defined in include/odbxx.h:1062
operator std::vector<std::string>
operator std::vector<std::string>()
Defined in include/odbxx.h:1072
operator=
Note: this method has 4 different signatures.
operator=
deleted
odb operator=(odb &&o) = delete
Delete shallow assignment operator
Defined in include/odbxx.h:705
operator=
template<typename T>
const T &operator=(const T &v)
Overload the Assignment Operators
Defined in include/odbxx.h:948
operator=
template<typename T>
const std::vector<T> &operator=(const std::vector<T> &v)
Overload the Assignment Operators for std::vector
Defined in include/odbxx.h:971
operator=
template<typename T, size_t SIZE>
const std::array<T, SIZE> &operator=(const std::array<T, SIZE> &arr)
Overload the Assignment Operators for std::array
Defined in include/odbxx.h:1018
operator()
template <typename T>
odb&operator()(T v)
overload the call operator
Defined in include/odbxx.h:1166
operator[]
Note: this method has 3 different signatures.
operator[]
u_odb &operator[](int index)
overload index operator for arrays
Defined in include/odbxx.h:1112
operator[]
odb &operator[](std::string str)
overload index operator for subkeys
Defined in include/odbxx.h:1157
operator[]
odb &operator[](const char *str)
Defined in include/odbxx.h:1161
operator+
template<typename T>
T operator+(T i)
overload arithmetic operators
Defined in include/odbxx.h:1197
operator-
template<typename T>
T operator-(T i)
Defined in include/odbxx.h:1219
operator*
template<typename T>
T operator*(const T i)
Defined in include/odbxx.h:1241
operator/
template<typename T>
T operator/(const T i)
Defined in include/odbxx.h:1252
operator++
Note: this method has 2 different signatures.
operator++
odb &operator++()
Defined in include/odbxx.h:1263
operator++
odb operator++(int)
Defined in include/odbxx.h:1274
operator--
Note: this method has 2 different signatures.
operator--
odb &operator--()
Defined in include/odbxx.h:1289
operator--
odb operator--(int)
Defined in include/odbxx.h:1300
operator+=
odb &operator+=(double d)
Defined in include/odbxx.h:1315
operator-=
odb &operator-=(double d)
Defined in include/odbxx.h:1326
operator*=
odb &operator*=(double d)
Defined in include/odbxx.h:1337
operator/=
odb &operator/=(double d)
Defined in include/odbxx.h:1348
operator<<
std::ostream &operator<<(std::ostream &output, odb &o)
overload stream out operator
Defined in include/odbxx.h:1101
size
int size()
return size of ODB key
Declared in include/odbxx.h:1630, defined in src/odbxx.cxx:462
resize
Note: this method has 2 different signatures.
resize
void resize(int size)
Resize an ODB key
Declared in include/odbxx.h:1631, defined in src/odbxx.cxx:467
resize
void resize(int size, bool b)
Resize an ODB key with default value
Declared in include/odbxx.h:1632, defined in src/odbxx.cxx:481
array
static
template<typename T>
static odb array(T value, size_t size)
Build a local, uniformly initialized array without accessing ODB.
Defined in include/odbxx.h:717
s
std::string s()
Defined in include/odbxx.h:1659
set
Note: this method has 2 different signatures.
set
void set(std::string str)
Declared in include/odbxx.h:1635, defined in src/odbxx.cxx:1736
set
void set(std::string s, int i)
Declared in include/odbxx.h:1636, defined in src/odbxx.cxx:1754
set_string_size
void set_string_size(std::string s, int size)
Declared in include/odbxx.h:1638, defined in src/odbxx.cxx:1771
deep_copy
void deep_copy(odb &d, const odb &s)
Deep copy
Declared in include/odbxx.h:1538, defined in src/odbxx.cxx:406
Subkeys
begin
const
iterator begin() const
iterator support
Defined in include/odbxx.h:1193
end
const
iterator end() const
Defined in include/odbxx.h:1194
items
odb&items()
Defined in include/odbxx.h:1652
named_items
named_item_range named_items()
Defined in include/odbxx.h:1653
contains
bool contains(std::string str)
check if key contains a certain subkey
Declared in include/odbxx.h:1640, defined in src/odbxx.cxx:634
is_subkey
bool is_subkey(std::string str)
Preserve the original API name while contains() becomes the preferred spelling.
Declared in include/odbxx.h:1641, defined in src/odbxx.cxx:659
fix_order
void fix_order(std::vector<std::string> target_subkey_order)
Fix the order of ODB keys to match that specified in target_order. The in-ODB representation is simple, as we can just use db_reorder_key() on anything that's in the wrong place. The in-memory representation is a little trickier, but we just copy raw memory into a temporary array, so we don't have to delete/recreate the u_odb objects.
Declared in include/odbxx.h:1665, defined in src/odbxx.cxx:1456
Comparing
compare
const
std::string compare(const odb &other, const std::vector<std::string> &ignore_values = {}) const
Preserve the text API for callers that do not need structured results.
Declared in include/odbxx.h:1695, defined in include/odbxx.h:1765
compare_details
const
std::vector<difference> compare_details(const odb &other, const std::vector<std::string> &ignore_values = {}) const
Compare snapshots without modifying either object or its backing ODB/file. Key order, root names, access modes and timestamps do not affect equality.
Declared in include/odbxx.h:1688, defined in include/odbxx.h:1705
Reading, writing and saving
read
Note: this method has 2 different signatures.
read
void read()
retrieve data from ODB and assign it to this object
Declared in include/odbxx.h:1618, defined in src/odbxx.cxx:901
read
void read(int index)
retrieve individual member of array
Declared in include/odbxx.h:1619, defined in src/odbxx.cxx:1044
write
Note: this method has 3 different signatures.
write
void write(bool dirty = false, int str_size = 0)
write all members of an array to the ODB
Declared in include/odbxx.h:1620, defined in src/odbxx.cxx:1267
write
void write(int str_size)
Defined in include/odbxx.h:1621
write
void write(int index, int str_size)
push individual member of an array
Declared in include/odbxx.h:1622, defined in src/odbxx.cxx:1166
save
Note: this method has 2 different signatures.
save
void save()
save ODB tree into file in JSON format
Declared in include/odbxx.h:1627, defined in src/odbxx.cxx:601
save
void save(const std::string &filename)
Declared in include/odbxx.h:1628, defined in src/odbxx.cxx:607
dump
Note: this method has 2 different signatures.
dump
std::string dump()
Declared in include/odbxx.h:1624, defined in src/odbxx.cxx:509
dump
void dump(std::string &s, int indent = 0)
dump current object in the same way as odbedit saves as json
Declared in include/odbxx.h:1626, defined in src/odbxx.cxx:551
print
Note: this method has 2 different signatures.
print
std::string print()
Declared in include/odbxx.h:1623, defined in src/odbxx.cxx:501
print
void print(std::string &s, int indent = 0)
print current object with all sub-objects nicely indented
Declared in include/odbxx.h:1625, defined in src/odbxx.cxx:518
Watching
watch
void watch(std::function<void(midas::odb &)> f)
Declared in include/odbxx.h:1633, defined in src/odbxx.cxx:1697
unwatch
void unwatch()
Declared in include/odbxx.h:1634, defined in src/odbxx.cxx:1715
get_last_index
int get_last_index()
indexed access, internal use only
Defined in include/odbxx.h:1189
set_last_index
void set_last_index(int i)
Defined in include/odbxx.h:1190
Key information
get_mode() and set_mode() use MODE_READ (1, R), MODE_WRITE (2, W), MODE_DELETE (4, D) and MODE_EXCLUSIVE (8, X in the ODB browser). The browser's H indicates an active hotlink from the notification count; it is not a mode bit and is not set with set_mode(). See changing permissions.
get_name
std::string get_name()
Defined in include/odbxx.h:1651
get_full_path
std::string get_full_path()
return full path from ODB
Declared in include/odbxx.h:1643, defined in src/odbxx.cxx:438
get_parent_path
std::string get_parent_path()
return parent object
Declared in include/odbxx.h:1644, defined in src/odbxx.cxx:454
get_hkey
HNDLE get_hkey()
Defined in include/odbxx.h:1642
get_tid
int get_tid()
Defined in include/odbxx.h:1649
type_name
const
std::string type_name() const
Defined in include/odbxx.h:1648
get_num_values
int get_num_values()
Defined in include/odbxx.h:1650
is_directory
const
bool is_directory() const
Defined in include/odbxx.h:1645
is_array
const
bool is_array() const
Defined in include/odbxx.h:1646
is_scalar
const
bool is_scalar() const
Defined in include/odbxx.h:1647
get_last_written
unsigned int get_last_written()
Declared in include/odbxx.h:1700, defined in src/odbxx.cxx:1681
get_mode
int get_mode()
Declared in include/odbxx.h:1698, defined in src/odbxx.cxx:1665
set_mode
void set_mode(int mode)
set mode of ODB key default is MODE_READ | MODE_WRITE | MODE_DELETE
Declared in include/odbxx.h:1697, defined in src/odbxx.cxx:1646
Flags
is_auto_refresh_read
const
bool is_auto_refresh_read() const
Defined in include/odbxx.h:1547
set_auto_refresh_read
void set_auto_refresh_read(bool f)
Defined in include/odbxx.h:1548
is_auto_refresh_write
const
bool is_auto_refresh_write() const
Defined in include/odbxx.h:1553
set_auto_refresh_write
void set_auto_refresh_write(bool f)
Defined in include/odbxx.h:1554
is_auto_create
const
bool is_auto_create() const
Defined in include/odbxx.h:1562
set_auto_create
void set_auto_create(bool f)
Defined in include/odbxx.h:1563
is_auto_enlarge_array
const
bool is_auto_enlarge_array() const
Defined in include/odbxx.h:1568
set_auto_enlarge_array
void set_auto_enlarge_array(bool f)
Defined in include/odbxx.h:1569
is_write_protect
const
bool is_write_protect() const
Defined in include/odbxx.h:1574
set_write_protect
void set_write_protect(bool f)
Defined in include/odbxx.h:1575
is_trigger_hotlink
const
bool is_trigger_hotlink() const
Defined in include/odbxx.h:1580
set_trigger_hotlink
void set_trigger_hotlink(bool f)
Defined in include/odbxx.h:1581
is_preserve_string_size
const
bool is_preserve_string_size() const
Setters and Getters
Defined in include/odbxx.h:1541
set_preserve_string_size
void set_preserve_string_size(bool f)
Defined in include/odbxx.h:1542
is_dirty
const
bool is_dirty() const
Defined in include/odbxx.h:1559
set_dirty
void set_dirty(bool f)
Defined in include/odbxx.h:1560
ODB source and debugging
odb_source
enum odb_source
| Enumerator | Value | Description |
|---|---|---|
ONLINE |
0 |
|
STRING |
||
FILE |
Defined in include/odbxx.h:488
set_odb_source
Note: this method has 2 different signatures.
set_odb_source
static
static void set_odb_source(odb::odb_source s, std::string str)
Declared in include/odbxx.h:1604, defined in src/odbxx.cxx:1800
set_odb_source
static
static void set_odb_source(odb::odb_source s)
Defined in include/odbxx.h:1605
get_odb_source
static
static odb::odb_source get_odb_source()
Defined in include/odbxx.h:1603
is_connected_odb
static
static bool is_connected_odb()
Defined in include/odbxx.h:1616
file
static
static odb file(const std::string &filename)
Open an independent file-backed ODB tree without changing the default source.
Declared in include/odbxx.h:1593, defined in src/odbxx.cxx:128
string
static
static odb string(const std::string &buffer)
Open an independent ODB tree from a reloadable JSON string.
Declared in include/odbxx.h:1594, defined in src/odbxx.cxx:155
set_debug
static
static void set_debug(bool flag)
Static functions
Defined in include/odbxx.h:1587
get_debug
static
static bool get_debug()
Defined in include/odbxx.h:1588
Exceptions
odb_error
Defined in include/odbxx.h:51
~odb_error
virtualdefaulted
virtual ~odb_error() = default
Defined in include/odbxx.h:53
what
virtualconstnoexceptpure virtual
virtual const char *what() const noexcept = 0
Defined in include/odbxx.h:54
odb_runtime_error
class odb_runtime_error : public odb_error, public mexception
Defined in include/odbxx.h:57
what
constnoexceptoverride
const char *what() const noexcept override
Defined in include/odbxx.h:60
odb_missing_key
class odb_missing_key : public odb_runtime_error
Defined in include/odbxx.h:63
odb_type_error
class odb_type_error : public odb_runtime_error
Defined in include/odbxx.h:68
odb_connection_error
class odb_connection_error : public odb_runtime_error
Defined in include/odbxx.h:73
odb_io_error
class odb_io_error : public odb_runtime_error
Defined in include/odbxx.h:78
odb_read_only
class odb_read_only : public odb_runtime_error
Defined in include/odbxx.h:83
odb_out_of_range
class odb_out_of_range : public odb_error, public std::out_of_range
Defined in include/odbxx.h:88
what
constnoexceptoverride
const char *what() const noexcept override
Defined in include/odbxx.h:91
mexception
class mexception : public std::runtime_error
Defined in include/mexcept.h:32
Methods
mexception
Note: this method has 2 different signatures.
mexception
mexception(const std::string &arg, bool stack_trace, const char *file, int line)
Defined in include/mexcept.h:35
mexception
noexcept
mexception(const mexception &ex) noexcept
Defined in include/mexcept.h:84
operator<<
std::ostream &operator<<(std::ostream &output, mexception &m)
Defined in include/mexcept.h:79
what
const
const char *what() const
Defined in include/mexcept.h:75
~mexception
~mexception()
Defined in include/mexcept.h:73
Comparisons
operator==
Note: this function has 2 different signatures.
operator==
template<typename T>
bool operator==(const midas::odb &o, const T &d)
overload comparison operators
Defined in include/odbxx.h:1775
operator==
template<typename T>
bool operator==(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1785
operator!=
Note: this function has 2 different signatures.
operator!=
template<typename T>
bool operator!=(const midas::odb &o, const T &d)
Defined in include/odbxx.h:1793
operator!=
template<typename T>
bool operator!=(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1801
operator<
Note: this function has 2 different signatures.
operator<
template<typename T>
bool operator<(const midas::odb &o, const T &d)
Defined in include/odbxx.h:1809
operator<
template<typename T>
bool operator<(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1817
operator<=
Note: this function has 2 different signatures.
operator<=
template<typename T>
bool operator<=(const midas::odb &o, const T &d)
Defined in include/odbxx.h:1825
operator<=
template<typename T>
bool operator<=(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1833
operator>
Note: this function has 2 different signatures.
operator>
template<typename T>
bool operator>(const midas::odb &o, const T &d)
Defined in include/odbxx.h:1841
operator>
template<typename T>
bool operator>(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1849
operator>=
Note: this function has 2 different signatures.
operator>=
template<typename T>
bool operator>=(const midas::odb &o, const T &d)
Defined in include/odbxx.h:1857
operator>=
template<typename T>
bool operator>=(const T &d, const midas::odb &o)
Defined in include/odbxx.h:1865