Skip to content

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 throw midas::odb_out_of_range instead
  • Arithmetic operators applied to a whole array apply to every element, so o["Gains"] *= 2.0 doubles all the gains
  • Strings are returned as std::string, and string arrays as std::vector<std::string>. Assigning a shorter string may shrink the ODB string length; call set_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 true as 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/or set_auto_refresh_write(false). Reads then return the local copy, and assignments only change the local copy. Call read() to refresh the local copy from the ODB, and write() 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 key
  • save() to write an object from file() back to the file it was read from
  • dump() to get the object as a JSON string, which string() 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

bool is_trigger_hotlink() const

Defined in include/odbxx.h:1580

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
EnumeratorValueDescription
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