MIDAS
Loading...
Searching...
No Matches
odbxx.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: odbxx.cxx
4 Created by: Stefan Ritt
5
6 Contents: Object oriented interface to ODB implementation file
7
8\********************************************************************/
9
10#include <string>
11#include <iostream>
12#include <fstream>
13#include <sstream>
14#include <map>
15#include <stdexcept>
16#include <algorithm>
17#include <initializer_list>
18#include <cstring>
19#include <bitset>
20#include <functional>
21
22#include "midas.h"
23#include "odbxx.h"
24#include "mexcept.h"
25#include "mstrlcpy.h"
26#include "mjson.h"
27
28// #include "mleak.hxx" // un-comment for memory leak debugging
29
30/*------------------------------------------------------------------*/
31
32namespace midas {
33
34 //----------------------------------------------------------------
35
36 //---- static initializers ---------------------------------------
38 thread_local std::string odb::s_odb_source_str = std::string("");
39 thread_local odb* odb::s_odb = nullptr;
40
41 // initialize static variables
42 HNDLE odb::s_hDB = 0;
43 bool odb::s_debug = false;
44 bool odb::s_connected_odb = false;
45 std::vector<midas::odb *> g_watchlist = {};
46
47 // static functions ----------------------------------------------
48
49 // initialize s_hDB, internal use only
52 mthrow("Operation only possible if connected to an online ODB");
53
54 if (s_hDB == 0)
56 if (s_hDB == 0)
57 mthrow("Please call cm_connect_experiment() before accessing the ODB");
58 s_connected_odb = true;
59 }
60
61 // search for a key with a specific hKey, needed for callbacks
63 if (po->m_hKey == hKey)
64 return po;
65 if (po->m_tid == TID_KEY) {
66 for (int i = 0; i < po->m_num_values; i++) {
68 if (pot != nullptr)
69 return pot;
70 }
71 }
72 return nullptr;
73 }
74
75 // check if a key exists in the ODB
76 bool odb::exists(const std::string &name) {
77 init_hdb();
79 return false;
80 HNDLE hkey;
81 return db_find_key(s_hDB, 0, name.c_str(), &hkey) == DB_SUCCESS;
82 }
83
84 // delete a key in the ODB
85 int odb::delete_key(const std::string &name) {
86 init_hdb();
88 return false;
89 HNDLE hkey;
90 auto status = db_find_key(s_hDB, 0, name.c_str(), &hkey);
91 if (status != DB_SUCCESS) {
92 if (s_debug)
93 std::cout << "Delete key " + name << " not found in ODB" << std::endl;
94 return status;
95 }
96 if (s_debug)
97 std::cout << "Delete ODB key " + name << std::endl;
98 return db_delete_key(s_hDB, hkey);
99 }
100
101 // load file into ODB
102 void odb::load(const std::string &filename, const std::string &odb_path) {
103 init_hdb();
105 mthrow("Cannot connect to ODB");
106
107 HNDLE hkey;
108 auto status = db_find_key(s_hDB, 0, odb_path.c_str(), &hkey);
109 if (status == DB_NO_KEY)
110 db_create_key(s_hDB, 0, odb_path.c_str(), TID_KEY);
111 status = db_find_key(s_hDB, 0, odb_path.c_str(), &hkey);
112 if (status != DB_SUCCESS)
113 mthrow("ODB path " + odb_path + " not found in ODB");
114
115 KEY key;
116 db_get_key(s_hDB, hkey, &key);
117 if (key.type != TID_KEY)
118 mthrow("ODB path " + odb_path + " does not point to a directory");
119
120 db_load(s_hDB, hkey, filename.c_str(), false);
121 }
122
123 // global callback function for db_watch()
124 void odb::watch_callback(int hDB, int hKey, int index, void *info) {
125 midas::odb *po = static_cast<midas::odb *>(info);
126 if (po->m_data == nullptr)
127 mthrow("Callback received for a midas::odb object which went out of scope");
128 midas::odb *poh = search_hkey(po, hKey);
129 if (poh == nullptr) {
130 auto s = db_get_path(hDB, hKey);
131 mthrow("New key \"" + s + "\" has been created in ODB after calling watch()");
132 }
133
134 poh->m_last_index = index;
135 po->m_watch_callback(*poh);
136 poh->m_last_index = -1;
137 }
138
139 // create ODB key
140 int odb::create(const char *name, int type) {
141 init_hdb();
142 int status = -1;
143 if (is_connected_odb())
146 mthrow("Cannot create key " + std::string(name) + ", db_create_key() status = " + std::to_string(status));
147 return status;
148 }
149
150 // private functions ---------------------------------------------
151
152 void odb::set_flags_recursively(uint32_t f) {
153 m_flags = f;
154 if (m_tid == TID_KEY) {
155 for (int i = 0; i < m_num_values; i++)
156 m_data[i].get_odb().set_flags_recursively(f);
157 }
158 }
159
160 void odb::odb_from_xml_remote(const std::string &str) {
161 init_hdb();
162
163 HNDLE hKey;
164 int status = db_find_key(s_hDB, 0, str.c_str(), &hKey);
165 if (status != DB_SUCCESS)
166 mthrow("ODB key \"" + str + "\" not found in ODB");
167
168 int bsize = 1000000;
169 char *buffer = (char *)malloc(bsize);
170 do {
171 int size = bsize;
172 status = db_copy_xml(s_hDB, hKey, buffer, &size, false);
173 if (status == DB_TRUNCATED) {
174 bsize *= 2;
175 buffer = (char *)realloc(buffer, bsize);
176 }
177 } while (status == DB_TRUNCATED);
178
179 if (status != DB_SUCCESS)
180 mthrow("Cannot retrieve XML data, status = " + std::to_string(status));
181
182 if (s_debug)
183 std::cout << "Retrieved XML tree for \"" + str + "\"" << std::endl;
184
185 char error[256] = "";
186 PMXML_NODE tree = mxml_parse_buffer(buffer, error, sizeof(error), NULL);
187 if (error[0]) {
188 std::cout << "MXML error, buffer =\n" << buffer << std::endl;
189 mthrow("MXML error: " + std::string(error));
190 }
191 free(buffer);
192
193 odb_from_xml(&tree->child[2], this);
194 m_hKey = hKey;
195
196 mxml_free_tree(tree);
197 }
198
199 void odb::odb_from_xml_string(const std::string &str) {
200 char error[256] = "";
201 PMXML_NODE tree = mxml_parse_buffer(str.c_str(), error, sizeof(error), NULL);
202 if (error[0]) {
203 std::cout << "MXML error, buffer =\n" << str << std::endl;
204 mthrow("MXML error: " + std::string(error));
205 }
206
207 PMXML_NODE root;
208 root = &tree->child[2];
209
210 odb_from_xml(root, s_odb);
211
212 mxml_free_tree(tree);
213
214 s_odb->set_auto_create(false);
220 }
221
222 std::vector<std::string> split(std::string input, char delimiter = '/') {
223 std::vector<std::string> result;
224 std::string item;
225
226 if (!input.empty() && input.front() == '/')
227 input.erase(0, 1);
228 if (!input.empty() && input.back() == '/')
229 input.pop_back();
230
231 std::stringstream ss(input);
232
233 while (std::getline(ss, item, delimiter)) {
234 result.push_back(item);
235 }
236
237 return result;
238 }
239
240 void odb::odb_from_json_string(const std::string &str) {
241
242 MJsonNode* node = MJsonNode::Parse(str.c_str());
243 if (node->GetType() == MJSON_ERROR)
244 mthrow("Error parsing JSON: " + node->GetError());
245
246 // node->Dump();
247
248 odb_from_json(node, "root", TID_KEY, s_odb);
249
250 delete node;
251
252 s_odb->set_auto_create(false);
258 }
259
260 // resize internal m_data array, keeping old values
261 void odb::resize_mdata(int size) {
262 auto new_array = new u_odb[size]{};
263 int i;
264 for (i = 0; i < m_num_values && i < size; i++) {
265 new_array[i] = m_data[i];
266 if (m_tid == TID_KEY)
267 m_data[i].set_odb(nullptr); // move odb*
268 if (m_tid == TID_STRING || m_tid == TID_LINK)
269 m_data[i].set_string_ptr(nullptr); // move std::string*
270 }
271 for (; i < size; i++) {
272 if (m_tid == TID_STRING || m_tid == TID_LINK)
273 new_array[i].set_string(""); // allocates new string
274 }
275 delete[] m_data;
276 m_data = new_array;
278 for (i = 0; i < m_num_values; i++) {
280 m_data[i].set_parent(this);
281 }
282 }
283
284 // get function for strings
285 void odb::get(std::string &s, bool quotes, bool refresh) {
286 if (refresh && is_auto_refresh_read())
287 read();
288
289 // put value into quotes
290 s = "";
291 std::string sd;
292 for (int i = 0; i < m_num_values; i++) {
293 m_data[i].get(sd);
294 if (quotes)
295 s += "\"";
296 s += sd;
297 if (quotes)
298 s += "\"";
299 if (i < m_num_values - 1)
300 s += ",";
301 }
302 }
303
304 // public functions ----------------------------------------------
305
306 // Deep copy constructor
307 odb::odb(const odb &o) : odb() {
308 m_tid = o.m_tid;
309 m_name = o.m_name;
311 m_hKey = o.m_hKey;
314 for (int i = 0; i < m_num_values; i++) {
316 m_data[i].set_parent(this);
317 if (m_tid == TID_STRING || m_tid == TID_LINK) {
318 // set_string() creates a copy of our string
320 } else if (m_tid == TID_KEY) {
321 // recursive call to create a copy of the odb object
322 midas::odb *po = o.m_data[i].get_podb();
323 midas::odb *pc = new midas::odb(*po);
324 pc->set_parent(this);
325 m_data[i].set(pc);
326 } else {
327 // simply pass basic types
328 m_data[i] = o.m_data[i];
329 m_data[i].set_parent(this);
330 }
331 }
332 }
333
334 void odb::deep_copy(odb &d, const odb &s) {
335 d.m_tid = s.m_tid;
336 d.m_name = s.m_name;
337 d.m_num_values = s.m_num_values;
338 d.m_hKey = s.m_hKey;
339 d.m_watch_callback = s.m_watch_callback;
340 d.m_data = new midas::u_odb[d.m_num_values]{};
341 for (int i = 0; i < d.m_num_values; i++) {
342 d.m_data[i].set_tid(d.m_tid);
343 d.m_data[i].set_parent(&d);
344 if (d.m_tid == TID_STRING || d.m_tid == TID_LINK) {
345 // set_string() creates a copy of our string
346 d.m_data[i].set_string(s.m_data[i]);
347 } else if (d.m_tid == TID_KEY) {
348 // recursive call to create a copy of the odb object
349 midas::odb *po = s.m_data[i].get_podb();
350 midas::odb *pc = new midas::odb(*po);
351 pc->set_parent(&d);
352 d.m_data[i].set(pc);
353 } else {
354 // simply pass basic types
355 d.m_data[i] = s.m_data[i];
356 d.m_data[i].set_parent(this);
357 }
358 }
359 }
360
361 // return full path from ODB
362 std::string odb::get_full_path() {
363 if (m_name[0] == '/')
364 return m_name;
365 if (m_parent)
366 return m_parent->get_full_path() + "/" + m_name;
367
368 if (!is_connected_odb() || m_hKey == -1)
369 return m_name;
370
371 std::string str = db_get_path(s_hDB, m_hKey);
372 if (str == "/") // change "/" to ""
373 str = "";
374 return str;
375 }
376
377 // return parent object
378 std::string odb::get_parent_path() {
379 std::string s = get_full_path();
380 std::size_t i = s.find_last_of("/");
381 s = s.substr(0, i);
382 return s;
383 }
384
385 // return size of ODB key
386 int odb::size() {
387 return m_num_values;
388 }
389
390 // Resize an ODB key
391 void odb::resize(int size) {
393 if (this->is_auto_refresh_write()) {
394 int status = db_set_num_values(s_hDB, m_hKey, size);
395 if (status != DB_SUCCESS)
396 mthrow("db_set_num_values for ODB key \"" + get_full_path() +
397 "\" failed with status " + std::to_string(status));
398 }
399 }
400
401 // Resize an ODB key with default value
402 void odb::resize(int size, bool b) {
403 int old_size = m_num_values;
405 if (this->is_auto_refresh_write()) {
406 int status = db_set_num_values(s_hDB, m_hKey, size);
407 if (status != DB_SUCCESS)
408 mthrow("db_set_num_values for ODB key \"" + get_full_path() +
409 "\" failed with status " + std::to_string(status));
410 }
411 if (size > old_size) {
412 for (int i=old_size ; i<size ; i++)
413 m_data[i] = b;
414 if (this->is_auto_refresh_write())
415 write();
416 }
417 }
418
419 std::string odb::print() {
420 std::string s;
421 s = "{\n";
422 print(s, 1);
423 s += "\n}";
424 return s;
425 }
426
427 std::string odb::dump() {
428 std::string s;
429 s = "{\n";
430 dump(s, 1);
431 s += "\n}";
432 return s;
433 }
434
435 // print current object with all sub-objects nicely indented
436 void odb::print(std::string &s, int indent) {
437 for (int i = 0; i < indent; i++)
438 s += " ";
439 if (m_tid == TID_KEY) {
440 s += "\"" + m_name + "\": {\n";
441 for (int i = 0; i < m_num_values; i++) {
442 std::string v;
443 // recursive call
444 m_data[i].get_odb().print(v, indent + 1);
445 s += v;
446 if (i < m_num_values - 1)
447 s += ",\n";
448 else
449 s += "\n";
450 }
451 for (int i = 0; i < indent; i++)
452 s += " ";
453 s += "}";
454 } else {
455 s += "\"" + m_name + "\": ";
456 if (m_num_values > 1)
457 s += "[";
458 std::string v;
459 get(v, m_tid == TID_STRING || m_tid == TID_LINK);
460 if (m_tid == TID_LINK)
461 s += " -> ";
462 s += v;
463 if (m_num_values > 1)
464 s += "]";
465 }
466 }
467
468 // dump current object in the same way as odbedit saves as json
469 void odb::dump(std::string &s, int indent) {
470 if (m_name != "root")
471 for (int i = 0; i < indent; i++)
472 s += " ";
473 if (m_tid == TID_KEY) {
474 if (m_name == "root")
475 indent--;
476 else {
477 s += "\"" + m_name + "\": {\n";
478 }
479 for (int i = 0; i < m_num_values; i++) {
480 std::string v;
481 m_data[i].get_odb().dump(v, indent + 1);
482 s += v;
483 if (i < m_num_values - 1)
484 s += ",\n";
485 else
486 s += "\n";
487 }
488 if (m_name != "root") {
489 for (int i = 0; i < indent; i++)
490 s += " ";
491 s += "}";
492 }
493 } else {
494 s += "\"" + m_name + "/key\": ";
495 s += "{ \"type\": " + std::to_string(m_tid) + ", ";
496
498 KEY key;
500 s += "\"access_mode\": " + std::to_string(key.access_mode) + ", ";
501 s += "\"last_written\": " + std::to_string(key.last_written) + "},\n";
502 }
503
504 for (int i = 0; i < indent; i++)
505 s += " ";
506 s += "\"" + m_name + "\": ";
507 if (m_num_values > 1)
508 s += "[";
509 std::string v;
510 get(v, m_tid == TID_STRING || m_tid == TID_LINK);
511 s += v;
512 if (m_num_values > 1)
513 s += "]";
514 }
515 }
516
517 // save ODB tree into file in JSON format
518 void odb::save(const std::string &filename) {
519 std::string buffer;
520
521 std::string header = "{\n";
522 header += " \"/MIDAS version\" : \"2.1\",\n";
523 header += " \"/filename\" : \"" + filename + "\",\n";
524
525 std::string path = get_full_path();
526 if (path == "")
527 path = "/";
528 header += " \"/ODB path\" : \"" + path + "\",\n\n";
529
530 odb::dump(buffer, 1);
531
532 buffer += "\n}\n";
533
534 std::ofstream f(filename);
535 if (!f.is_open())
536 mthrow("Cannot open file \"" + filename);
537
538 f << header << buffer;
539 f.close();
540 }
541
542
543 // check if key contains a certain subkey
544 bool odb::is_subkey(std::string str) {
545 if (m_tid != TID_KEY)
546 return false;
547
548 std::string first = str;
549 std::string tail{};
550 if (str.find('/') != std::string::npos) {
551 first = str.substr(0, str.find('/'));
552 tail = str.substr(str.find('/') + 1);
553 }
554
555 int i;
556 for (i = 0; i < m_num_values; i++)
557 if (m_data[i].get_odb().get_name() == first)
558 break;
559 if (i == m_num_values)
560 return false;
561
562 if (!tail.empty())
563 return m_data[i].get_odb().is_subkey(tail);
564
565 return true;
566 }
567
568 odb &odb::get_subkey(std::string str) {
569 if (m_tid == 0) {
570 if (is_auto_create()) {
571 m_tid = TID_KEY;
572 int status = db_create_key(s_hDB, 0, m_name.c_str(), m_tid);
574 mthrow("Cannot create ODB key \"" + m_name + "\", status" + std::to_string(status));
575 db_find_key(s_hDB, 0, m_name.c_str(), &m_hKey);
576 if (s_debug) {
577 if (m_name[0] == '/')
578 std::cout << "Created ODB key \"" + m_name + "\"" << std::endl;
579 else
580 std::cout << "Created ODB key \"" + get_full_path() + "\"" << std::endl;
581 }
582 // strip path from name
583 if (m_name.find_last_of('/') != std::string::npos)
584 m_name = m_name.substr(m_name.find_last_of('/') + 1);
585 } else
586 mthrow("Invalid key \"" + m_name + "\" does not have subkeys");
587
588 }
589 if (m_tid != TID_KEY)
590 mthrow("ODB key \"" + get_full_path() + "\" does not have subkeys");
591
592 std::string first = str;
593 std::string tail{};
594 if (str.find('/') != std::string::npos) {
595 first = str.substr(0, str.find('/'));
596 tail = str.substr(str.find('/') + 1);
597 }
598
599 int i;
600 for (i = 0; i < m_num_values; i++)
601 if (equal_ustring(first.c_str(), m_data[i].get_odb().get_name().c_str()))
602 break;
603 if (i == m_num_values) {
604 if (is_auto_create()) {
605 if (m_num_values == 0) {
606 m_num_values = 1;
607 m_data = new u_odb[1]{};
608 i = 0;
609 } else {
610 // resize array
612 i = m_num_values - 1;
613 }
614 midas::odb *o = new midas::odb();
616 m_data[i].set_parent(this);
617 o->set_name(get_full_path() + "/" + str);
618 o->set_tid(0); // tid is currently undefined
619 o->set_flags(get_flags());
620 o->set_parent(this);
621 m_data[i].set(o);
622 } else
623 mthrow("ODB key \"" + get_full_path() + "\" does not contain subkey \"" + first + "\"");
624 }
625 if (!tail.empty())
626 return m_data[i].get_odb().get_subkey(tail);
627
628 return *m_data[i].get_podb();
629 }
630
631 // get number of subkeys in ODB, return number and vector of names
632 int odb::get_subkeys(std::vector<std::string> &name) {
633 if (m_tid != TID_KEY)
634 return 0;
635 if (m_hKey == 0 || m_hKey == -1)
636 mthrow("get_sub-keys called with invalid m_hKey for ODB key \"" + m_name + "\"");
637
638 // count number of subkeys in ODB
639 std::vector<HNDLE> hlist;
640 int n = 0;
641 for (int i = 0;; i++) {
642 HNDLE h;
643 int status = db_enum_key(s_hDB, m_hKey, i, &h);
644 if (status != DB_SUCCESS)
645 break;
646 KEY key;
647 db_get_key(s_hDB, h, &key);
648 hlist.push_back(h);
649 name.push_back(key.name);
650 n = i + 1;
651 }
652
653 return n;
654 }
655
656 // obtain key definition from ODB and allocate local data array
657 bool odb::read_key(const std::string &path) {
658 init_hdb();
659
660 int status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
661 if (status != DB_SUCCESS)
662 return false;
663
664 KEY key;
666 if (status != DB_SUCCESS)
667 mthrow("db_get_key for ODB key \"" + path +
668 "\" failed with status " + std::to_string(status));
669
670 // check for correct type if given as parameter
671 if (m_tid > 0 && m_tid != (int) key.type)
672 mthrow("ODB key \"" + get_full_path() +
673 "\" has different type than specified");
674
675 if (s_debug)
676 std::cout << "Get definition for ODB key \"" + get_full_path() + "\"" << std::endl;
677
678 m_tid = key.type;
679 m_name = key.name;
680 if (m_tid == TID_KEY) {
681
682 // merge ODB keys with local keys
683 for (int i = 0; i < m_num_values; i++) {
684 std::string p(path);
685 if (p.back() != '/')
686 p += "/";
687 p += m_data[i].get_odb().get_name();
688 HNDLE h;
689 status = db_find_key(s_hDB, 0, p.c_str(), &h);
690 if (status != DB_SUCCESS) {
691 // if key does not exist in ODB write it
692 m_data[i].get_odb().write_key(p, true);
693 m_data[i].get_odb().write();
694 } else {
695 // check key type
696 KEY key;
697 status = db_get_key(s_hDB, h, &key);
698 if (status != DB_SUCCESS)
699 mthrow("db_get_key for ODB key \"" + get_full_path() +
700 "\" failed with status " + std::to_string(status));
701 if (m_data[i].get_odb().get_tid() != (int)key.type) {
702 // write key if different
703 m_data[i].get_odb().write_key(p, true);
704 m_data[i].get_odb().write();
705 }
706 if (m_data[i].get_odb().get_tid() == TID_KEY) {
707 // update subkey structure
708 m_data[i].get_odb().read_key(p);
709 }
710 }
711 }
712
713 // read back everything from ODB
714 std::vector<std::string> name;
716 delete[] m_data;
718 for (int i = 0; i < m_num_values; i++) {
719 std::string p(path);
720 if (p.back() != '/')
721 p += "/";
722 p += name[i];
723 midas::odb *o = new midas::odb(p.c_str());
724 o->set_parent(this);
726 m_data[i].set_parent(this);
727 m_data[i].set(o);
728 }
729 } else {
731 delete[] m_data;
733 for (int i = 0; i < m_num_values; i++) {
735 m_data[i].set_parent(this);
736 }
737 }
738
739 return true;
740 }
741
742 // create key in ODB if it does not exist, otherwise check key type
743 bool odb::write_key(std::string &path, bool force_write) {
744 int status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
745 if (status != DB_SUCCESS) {
746 if (m_tid == 0) // auto-create subdir
747 m_tid = TID_KEY;
748 if (m_tid > 0 && m_tid < TID_LAST) {
749 status = db_create_key(s_hDB, 0, path.c_str(), m_tid);
750 if (status != DB_SUCCESS)
751 mthrow("ODB key \"" + path + "\" cannot be created");
752 status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
753 if (status != DB_SUCCESS)
754 mthrow("ODB key \"" + path + "\" not found after creation");
755 if (s_debug) {
756 if (path[0] == '/')
757 std::cout << "Created ODB key \"" + path + "\"" << std::endl;
758 else
759 std::cout << "Created ODB key \"" + get_full_path() + "\"" << std::endl;
760 }
761 } else
762 mthrow("ODB key \"" + path + "\" cannot be found");
763 return true;
764 } else {
765 KEY key;
767 if (status != DB_SUCCESS)
768 mthrow("db_get_key for ODB key \"" + path +
769 "\" failed with status " + std::to_string(status));
770 if (m_tid == 0)
771 m_tid = key.type;
772
773 // check for correct type
774 if (m_tid > 0 && m_tid != (int) key.type) {
775 if (force_write) {
776 // delete and recreate key
778 if (status != DB_SUCCESS)
779 mthrow("db_delete_key for ODB key \"" + path +
780 "\" failed with status " + std::to_string(status));
781 status = db_create_key(s_hDB, 0, path.c_str(), m_tid);
782 if (status != DB_SUCCESS)
783 mthrow("ODB key \"" + path + "\" cannot be created");
784 status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
785 if (status != DB_SUCCESS)
786 mthrow("ODB key \"" + path + "\" not found after creation");
787 if (s_debug)
788 std::cout << "Re-created ODB key \"" + get_full_path() << "\" with different type" << std::endl;
789 } else
790 // abort
791 mthrow("ODB key \"" + get_full_path() +
792 "\" has differnt type than specified");
793 } else if (s_debug)
794 std::cout << "Validated ODB key \"" + get_full_path() + "\"" << std::endl;
795
796 return false;
797 }
798 }
799
800
801 // retrieve data from ODB and assign it to this object
802 void odb::read() {
803 if (!is_connected_odb())
804 return;
805
806 // check if deleted
807 if (is_deleted())
808 mthrow("ODB key \"" + m_name + "\" cannot be pulled because it has been deleted");
809
810 if (m_hKey == 0)
811 return; // needed to print un-connected objects
812
813 if (m_tid == 0)
814 mthrow("Read of invalid ODB key \"" + m_name + "\"");
815
816 if (m_hKey == -1) {
817 // connect un-connected object (crated via XML)
818 std::string path = get_full_path();
819
820 int status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
821 if (status != DB_SUCCESS)
822 mthrow("Cannot connect key \"" + path + "\" to ODB");
823 }
824
825 int status{};
826 if (m_tid == TID_STRING) {
827 KEY key;
829 char *str = (char *) malloc(key.total_size);
830 int size = key.total_size;
832 for (int i = 0; i < m_num_values; i++)
833 m_data[i].set(str + i * key.item_size);
834 free(str);
835 } else if (m_tid == TID_KEY) {
836 std::vector<std::string> name;
837 int n = get_subkeys(name);
838 if (n != m_num_values) {
839 // if subdirs have changed, rebuild it
840 delete[] m_data;
841 m_num_values = n;
843 for (int i = 0; i < m_num_values; i++) {
844 std::string k(get_full_path());
845 k += "/" + name[i];
846 midas::odb *o = new midas::odb(k.c_str());
847 o->set_parent(this);
849 m_data[i].set_parent(this);
850 m_data[i].set(o);
851 }
852 }
853 for (int i = 0; i < m_num_values; i++)
854 m_data[i].get_odb().read();
856 } else {
857 // resize local array if number of values has changed
858 KEY key;
860 if (key.num_values != m_num_values) {
861 delete[] m_data;
864 for (int i = 0; i < m_num_values; i++) {
866 m_data[i].set_parent(this);
867 }
868 }
869
871 void *buffer = malloc(size);
872 void *p = buffer;
874 for (int i = 0; i < m_num_values; i++) {
875 if (m_tid == TID_UINT8)
876 m_data[i].set(*static_cast<uint8_t *>(p));
877 else if (m_tid == TID_INT8)
878 m_data[i].set(*static_cast<int8_t *>(p));
879 else if (m_tid == TID_UINT16)
880 m_data[i].set(*static_cast<uint16_t *>(p));
881 else if (m_tid == TID_INT16)
882 m_data[i].set(*static_cast<int16_t *>(p));
883 else if (m_tid == TID_UINT32)
884 m_data[i].set(*static_cast<uint32_t *>(p));
885 else if (m_tid == TID_INT32)
886 m_data[i].set(*static_cast<int32_t *>(p));
887 else if (m_tid == TID_UINT64)
888 m_data[i].set(*static_cast<uint64_t *>(p));
889 else if (m_tid == TID_INT64)
890 m_data[i].set(*static_cast<int64_t *>(p));
891 else if (m_tid == TID_BOOL)
892 m_data[i].set(*static_cast<bool *>(p));
893 else if (m_tid == TID_FLOAT)
894 m_data[i].set(*static_cast<float *>(p));
895 else if (m_tid == TID_DOUBLE)
896 m_data[i].set(*static_cast<double *>(p));
897 else if (m_tid == TID_STRING)
898 m_data[i].set(std::string(static_cast<const char *>(p)));
899 else if (m_tid == TID_LINK)
900 m_data[i].set(std::string(static_cast<const char *>(p)));
901 else
902 mthrow("Invalid type ID " + std::to_string(m_tid));
903
904 p = static_cast<char *>(p) + rpc_tid_size(m_tid);
905 }
906 free(buffer);
907 }
908
909 if (status != DB_SUCCESS)
910 mthrow("db_get_data for ODB key \"" + get_full_path() +
911 "\" failed with status " + std::to_string(status));
912 if (s_debug) {
913 if (m_tid == TID_KEY) {
914 std::cout << "Get ODB key \"" + get_full_path() + "[0..." +
915 std::to_string(m_num_values - 1) + "]\"" << std::endl;
916 } else {
917 std::string s;
918 get(s, false, false);
919 if (m_num_values > 1) {
920 if (m_tid == TID_STRING || m_tid == TID_LINK)
921 std::cout << "Get ODB key \"" + get_full_path() + "[0..." +
922 std::to_string(m_num_values - 1) + "]\": [\"" + s + "\"]" << std::endl;
923 else
924 std::cout << "Get ODB key \"" + get_full_path() + "[0..." +
925 std::to_string(m_num_values - 1) + "]\": [" + s + "]" << std::endl;
926 } else {
927 if (m_tid == TID_STRING || m_tid == TID_LINK)
928 std::cout << "Get ODB key \"" + get_full_path() + "\": \"" + s + "\"" << std::endl;
929 else
930 std::cout << "Get ODB key \"" + get_full_path() + "\": " + s << std::endl;
931 }
932 }
933 }
934 }
935
936 // retrieve individual member of array
937 void odb::read(int index) {
938 if (!is_connected_odb())
939 return;
940
941 if (m_hKey == 0 || m_hKey == -1)
942 return; // needed to print un-connected objects
943
944 if (m_tid == 0)
945 mthrow("Pull of invalid ODB key \"" + m_name + "\"");
946
947 int status{};
948 if (m_tid == TID_STRING || m_tid == TID_LINK) {
949 KEY key;
951 char *str = (char *) malloc(key.item_size);
952 int size = key.item_size;
955 free(str);
956 } else if (m_tid == TID_KEY) {
959 } else {
960 int size = rpc_tid_size(m_tid);
961 void *buffer = malloc(size);
962 void *p = buffer;
964 if (m_tid == TID_UINT8)
965 m_data[index].set(*static_cast<uint8_t *>(p));
966 else if (m_tid == TID_INT8)
967 m_data[index].set(*static_cast<int8_t *>(p));
968 else if (m_tid == TID_UINT16)
969 m_data[index].set(*static_cast<uint16_t *>(p));
970 else if (m_tid == TID_INT16)
971 m_data[index].set(*static_cast<int16_t *>(p));
972 else if (m_tid == TID_UINT32)
973 m_data[index].set(*static_cast<uint32_t *>(p));
974 else if (m_tid == TID_INT32)
975 m_data[index].set(*static_cast<int32_t *>(p));
976 else if (m_tid == TID_UINT64)
977 m_data[index].set(*static_cast<uint64_t *>(p));
978 else if (m_tid == TID_INT64)
979 m_data[index].set(*static_cast<int64_t *>(p));
980 else if (m_tid == TID_BOOL)
981 m_data[index].set(*static_cast<bool *>(p));
982 else if (m_tid == TID_FLOAT)
983 m_data[index].set(*static_cast<float *>(p));
984 else if (m_tid == TID_DOUBLE)
985 m_data[index].set(*static_cast<double *>(p));
986 else if (m_tid == TID_STRING)
987 m_data[index].set(std::string(static_cast<const char *>(p)));
988 else if (m_tid == TID_LINK)
989 m_data[index].set(std::string(static_cast<const char *>(p)));
990 else
991 mthrow("Invalid type ID " + std::to_string(m_tid));
992
993 free(buffer);
994 }
995
996 if (status != DB_SUCCESS)
997 mthrow("db_get_data for ODB key \"" + get_full_path() +
998 "\" failed with status " + std::to_string(status));
999 if (s_debug) {
1000 std::string s;
1001 m_data[index].get(s);
1002 if (m_tid == TID_STRING || m_tid == TID_LINK)
1003 std::cout << "Get ODB key \"" + get_full_path() + "[" +
1004 std::to_string(index) + "]\": [\"" + s + "\"]" << std::endl;
1005 else
1006 std::cout << "Get ODB key \"" + get_full_path() + "[" +
1007 std::to_string(index) + "]\": [" + s + "]" << std::endl;
1008 }
1009 }
1010
1011 // push individual member of an array
1012 void odb::write(int index, int str_size) {
1013 if (!is_connected_odb())
1014 return;
1015
1016 if (m_hKey == -1) {
1017 // connect un-connected object (crated via XML)
1018 std::string path = get_full_path();
1019
1020 int status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
1021 if (status != DB_SUCCESS)
1022 mthrow("Cannot connect key \"" + path + "\" to ODB");
1023
1024 } else if (m_hKey == 0) {
1025 if (is_auto_create()) {
1026 std::string to_create = m_name[0] == '/' ? m_name : get_full_path();
1027 int status = db_create_key(s_hDB, 0, to_create.c_str(), m_tid);
1029 mthrow("Cannot create ODB key \"" + to_create + "\", status =" + std::to_string(status));
1030 db_find_key(s_hDB, 0, to_create.c_str(), &m_hKey);
1031 if (s_debug) {
1032 std::cout << "Created ODB key \"" + to_create + "\"" << std::endl;
1033 }
1034 // strip path from name
1035 if (m_name.find_last_of('/') != std::string::npos)
1036 m_name = m_name.substr(m_name.find_last_of('/') + 1);
1037 } else
1038 mthrow("Write of un-connected ODB key \"" + m_name + "\" not possible");
1039 }
1040
1041 // don't write keys
1042 if (m_tid == TID_KEY)
1043 return;
1044
1045 int status{};
1046 if (m_tid == TID_STRING || m_tid == TID_LINK) {
1047 KEY key;
1049 std::string s;
1050 m_data[index].get(s);
1051 if (m_num_values == 1) {
1052 int size = key.item_size;
1053 if (key.item_size == 0 || !is_preserve_string_size())
1054 size = s.size() + 1;
1055 if (str_size > 0)
1056 size = str_size;
1057 char *ss = (char *)malloc(size+1);
1058 mstrlcpy(ss, s.c_str(), size);
1059 if (is_trigger_hotlink())
1060 status = db_set_data(s_hDB, m_hKey, ss, size, 1, m_tid);
1061 else
1063 free(ss);
1064 } else {
1065 if (key.item_size == 0)
1066 key.item_size = s.size() + 1;
1067 if (str_size > 0) {
1068 if (key.item_size > 0 && key.item_size != str_size) {
1069 std::cout << "ODB string size mismatch for \"" << get_full_path() <<
1070 "\" (" << key.item_size << " vs " << str_size << "). ODB key recreated."
1071 << std::endl;
1072 if (is_trigger_hotlink())
1073 status = db_set_data(s_hDB, m_hKey, s.c_str(), str_size, 1, m_tid);
1074 else
1075 status = db_set_data1(s_hDB, m_hKey, s.c_str(), str_size, 1, m_tid);
1076 }
1077 key.item_size = str_size;
1078 }
1080 }
1081 if (s_debug) {
1082 if (m_num_values > 1)
1083 std::cout << "Set ODB key \"" + get_full_path() + "[" + std::to_string(index) + "]\" = \"" + s
1084 + "\"" << std::endl;
1085 else
1086 std::cout << "Set ODB key \"" + get_full_path() + "\" = \"" + s + "\""<< std::endl;
1087 }
1088 } else {
1089 u_odb u = m_data[index];
1090 if (m_tid == TID_BOOL) {
1091 u.set_parent(nullptr);
1092 BOOL b = static_cast<bool>(u); // "bool" is only 1 Byte, BOOL is 4 Bytes
1094 } else {
1096 }
1097 if (s_debug) {
1098 std::string s;
1099 u.get(s);
1100 if (m_num_values > 1)
1101 std::cout << "Set ODB key \"" + get_full_path() + "[" + std::to_string(index) + "]\" = " + s
1102 << std::endl;
1103 else
1104 std::cout << "Set ODB key \"" + get_full_path() + "\" = " + s << std::endl;
1105 }
1106 }
1107 if (status != DB_SUCCESS)
1108 mthrow("db_set_data_index for ODB key \"" + get_full_path() +
1109 "\" failed with status " + std::to_string(status));
1110 }
1111
1112 // write all members of an array to the ODB
1113 void odb::write(int str_size) {
1114
1115 // check if deleted
1116 if (is_deleted())
1117 mthrow("ODB key \"" + m_name + "\" cannot be written because it has been deleted");
1118
1119 // write subkeys
1120 if (m_tid == TID_KEY) {
1121 for (int i = 0; i < m_num_values; i++)
1122 m_data[i].get_odb().write();
1123 return;
1124 }
1125
1126 if (m_tid == 0 && m_data[0].get_tid() != 0)
1127 m_tid = m_data[0].get_tid();
1128
1129 if (m_tid < 1 || m_tid >= TID_LAST)
1130 mthrow("Invalid TID for ODB key \"" + get_full_path() + "\"");
1131
1132 if ((m_hKey == 0 || m_hKey == -1) && !is_auto_create())
1133 mthrow("Writing ODB key \"" + m_name +
1134 "\" is not possible because of invalid key handle");
1135
1136 // if index operator [] returned previously a certain index, write only this one
1137 if (m_last_index != -1) {
1138 write(m_last_index, str_size);
1139 m_last_index = -1;
1140 return;
1141 }
1142
1143 if (m_num_values == 1) {
1144 write(0, str_size);
1145 return;
1146 }
1147
1148 if (m_hKey == -1) {
1149 // connect un-connected object (crated via XML)
1150 std::string path = get_full_path();
1151
1152 int status = db_find_key(s_hDB, 0, path.c_str(), &m_hKey);
1153 if (status != DB_SUCCESS)
1154 mthrow("Cannot connect key \"" + path + "\" to ODB");
1155
1156 } else if (m_hKey == 0) {
1157 if (is_auto_create()) {
1158 std::string to_create = m_name[0] == '/' ? m_name : get_full_path();
1159 int status = db_create_key(s_hDB, 0, to_create.c_str(), m_tid);
1161 mthrow("Cannot create ODB key \"" + to_create + "\", status" + std::to_string(status));
1162 db_find_key(s_hDB, 0, to_create.c_str(), &m_hKey);
1163 if (s_debug) {
1164 std::cout << "Created ODB key \"" + to_create + "\"" << std::endl;
1165 }
1166 // strip path from name
1167 if (m_name.find_last_of('/') != std::string::npos)
1168 m_name = m_name.substr(m_name.find_last_of('/') + 1);
1169 } else
1170 mthrow("Write of un-connected ODB key \"" + m_name + "\" not possible");
1171 }
1172
1173 int status{};
1174 if (m_tid == TID_STRING || m_tid == TID_LINK) {
1175 if (m_num_values > 1) {
1176 KEY key;
1178
1179 // get longest string size of local vector
1180 int size = 1;
1181 for (int i = 0; i < m_num_values; i++)
1182 if ((int)m_data[i].string_size() + 1 > size)
1183 size = m_data[i].string_size() + 1;
1184
1185 // increase key size if necessary
1186 if (size > key.item_size) {
1187 key.item_size = size;;
1189 }
1190
1191 char *str = (char *) calloc((size_t)m_num_values, key.item_size);
1192 if (str == nullptr)
1193 mthrow("calloc failed");
1194 for (int i = 0; i < m_num_values; i++) {
1195 std::string d;
1196 m_data[i].get(d);
1197 strncpy(str + i * key.item_size, d.c_str(), key.item_size);
1198 }
1199 if (is_trigger_hotlink())
1201 else
1203 free(str);
1204 if (s_debug) {
1205 std::string s;
1206 get(s, true, false);
1207 std::cout << "Set ODB key \"" + get_full_path() +
1208 "[0..." + std::to_string(m_num_values - 1) + "]\" = [" + s + "]" << std::endl;
1209 }
1210 } else {
1211 std::string s;
1212 m_data[0].get(s);
1213 if (is_trigger_hotlink())
1214 status = db_set_data(s_hDB, m_hKey, s.c_str(), s.length() + 1, 1, m_tid);
1215 else
1216 status = db_set_data1(s_hDB, m_hKey, s.c_str(), s.length() + 1, 1, m_tid);
1217 if (s_debug)
1218 std::cout << "Set ODB key \"" + get_full_path() + "\" = " + s << std::endl;
1219 }
1220 } else {
1222 uint8_t *buffer = (uint8_t *) malloc(size);
1223 uint8_t *p = buffer;
1224 for (int i = 0; i < m_num_values; i++) {
1225 if (m_tid == TID_BOOL) {
1226 // bool has 1 Byte, BOOL has 4 Bytes
1227 BOOL b = static_cast<bool>(m_data[i]);
1228 memcpy(p, &b, rpc_tid_size(m_tid));
1229 } else {
1230 memcpy(p, (void*)&m_data[i], rpc_tid_size(m_tid));
1231 }
1232 p += rpc_tid_size(m_tid);
1233 }
1234 if (is_trigger_hotlink())
1236 else
1238 free(buffer);
1239 if (s_debug) {
1240 std::string s;
1241 get(s, false, false);
1242 if (m_num_values > 1)
1243 std::cout << "Set ODB key \"" + get_full_path() + "[0..." + std::to_string(m_num_values - 1) +
1244 "]\" = [" + s + "]" << std::endl;
1245 else
1246 std::cout << "Set ODB key \"" + get_full_path() + "\" = " + s << std::endl;
1247 }
1248 }
1249
1250 if (status != DB_SUCCESS)
1251 mthrow("db_set_data for ODB key \"" + get_full_path() +
1252 "\" failed with status " + std::to_string(status));
1253 }
1254
1255 void recurse_del_keys_not_in_defaults(std::string path, HNDLE hDB, HNDLE hKey, midas::odb& default_odb) {
1256 // Delete any subkeys that are not in the list of defaults.
1257 KEY key;
1258 db_get_key(hDB, hKey, &key);
1259
1260 if (key.type == TID_KEY) {
1261 std::vector<std::string> to_delete;
1262
1263 for (int i = 0;; i++) {
1264 HNDLE hSubKey;
1265 int status = db_enum_key(hDB, hKey, i, &hSubKey);
1266 if (status != DB_SUCCESS)
1267 break;
1268
1269 KEY subKey;
1270 db_get_key(hDB, hSubKey, &subKey);
1271 std::string full_path = path + "/" + subKey.name;
1272
1273 if (!default_odb.is_subkey(subKey.name)) {
1274 to_delete.push_back(subKey.name);
1275
1276 if (default_odb.get_debug()) {
1277 std::cout << "Deleting " << full_path << " as not in list of defaults" << std::endl;
1278 }
1279 } else if (key.type == TID_KEY) {
1280 recurse_del_keys_not_in_defaults(full_path, hDB, hSubKey, default_odb[(const char *)(subKey.name)]);
1281 }
1282 }
1283
1284 for (auto name : to_delete) {
1285 HNDLE hSubKey;
1286 db_find_key(hDB, hKey, name.c_str(), &hSubKey);
1287 db_delete_key(hDB, hSubKey);
1288 }
1289 }
1290 }
1291
1292 void recurse_get_defaults_order(std::string path, midas::odb& default_odb, std::map<std::string, std::vector<std::string> >& retval) {
1293 for (midas::odb& sub : default_odb) {
1294 if (sub.get_tid() == TID_KEY) {
1295 recurse_get_defaults_order(path + "/" + sub.get_name(), sub, retval);
1296 }
1297
1298 retval[path].push_back(sub.get_name());
1299 }
1300 }
1301
1302 void recurse_fix_order(midas::odb& default_odb, std::map<std::string, std::vector<std::string> >& user_order) {
1303 std::string path = default_odb.get_full_path();
1304
1305 if (user_order.find(path) != user_order.end()) {
1306 default_odb.fix_order(user_order[path]);
1307 }
1308
1309 for (midas::odb& it : default_odb) {
1310 if (it.get_tid() == TID_KEY) {
1311 recurse_fix_order(it, user_order);
1312 }
1313 }
1314 }
1315
1316 void odb::fix_order(std::vector<std::string> target_order) {
1317 // Fix the order of ODB keys to match that specified in target_order.
1318 // The in-ODB representation is simple, as we can just use db_reorder_key()
1319 // on anything that's in the wrong place.
1320 // The in-memory representation is a little trickier, but we just copy raw
1321 // memory into a temporary array, so we don't have to delete/recreate the
1322 // u_odb objects.
1323 std::vector<std::string> curr_order;
1324
1325 if (get_subkeys(curr_order) <= 0) {
1326 // Not a TID_KEY (or no keys)
1327 return;
1328 }
1329
1330 if (target_order.size() != curr_order.size() || (int)target_order.size() != m_num_values) {
1331 return;
1332 }
1333
1334 HNDLE hKey = get_hkey();
1335 bool force_order = false;
1336
1337 // Temporary location where we'll store in-memory u_odb objects in th
1338 // correct order.
1339 u_odb* new_m_data = new u_odb[m_num_values];
1340
1341 for (int i = 0; i < m_num_values; i++) {
1342 if (force_order || curr_order[i] != target_order[i]) {
1343 force_order = true;
1344 HNDLE hSubKey;
1345
1346 // Fix the order in the ODB
1347 db_find_key(s_hDB, hKey, target_order[i].c_str(), &hSubKey);
1348 db_reorder_key(s_hDB, hSubKey, i);
1349 }
1350
1351 // Fix the order in memory
1352 auto curr_it = std::find(curr_order.begin(), curr_order.end(), target_order[i]);
1353
1354 if (curr_it == curr_order.end()) {
1355 // Logic error - bail to avoid doing any damage to the in-memory version.
1356 delete[] new_m_data;
1357 return;
1358 }
1359
1360 int curr_idx = curr_it - curr_order.begin();
1361 new_m_data[i] = m_data[curr_idx];
1362 }
1363
1364 // Final update of the in-memory version so they are in the correct order
1365 for (int i = 0; i < m_num_values; i++) {
1366 m_data[i] = new_m_data[i];
1367
1368 // Nullify pointers that point to the same object in
1369 // m_data and new_m_data, so the underlying object doesn't
1370 // get destroyed when we delete new_m_data.
1371 new_m_data[i].set_string_ptr(nullptr);
1372 new_m_data[i].set_odb(nullptr);
1373 }
1374
1375 delete[] new_m_data;
1376 }
1377
1378 // connect function with separated path and key name
1379 void odb::connect(const std::string &p, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults) {
1380 init_hdb();
1381
1382 if (!name.empty())
1383 m_name = name;
1384 std::string path(p);
1385
1386 if (path.empty())
1387 mthrow("odb::connect() cannot be called with an empty ODB path");
1388
1389 if (path[0] != '/')
1390 mthrow("odb::connect(\"" + path + "\"): path must start with leading \"/\"");
1391
1392 if (path.back() != '/')
1393 path += "/";
1394
1395 path += m_name;
1396
1397 HNDLE hKey;
1398 int status = db_find_key(s_hDB, 0, path.c_str(), &hKey);
1399 bool key_exists = (status == DB_SUCCESS);
1400 bool created = false;
1401
1402 if (key_exists && delete_keys_not_in_defaults) {
1403 // Recurse down to delete keys as needed.
1404 // We need to do this recursively BEFORE calling read/read_key for the first time
1405 // to ensure that subdirectories get handled correctly.
1407 }
1408
1409 if (!key_exists || write_defaults) {
1410 created = write_key(path, write_defaults);
1411 } else {
1412 read_key(path);
1413 }
1414
1415 // correct wrong parent ODB from initializer_list
1416 for (int i = 0; i < m_num_values; i++)
1417 m_data[i].set_parent(this);
1418
1419 if (m_tid == TID_KEY) {
1420 for (int i = 0; i < m_num_values; i++)
1421 m_data[i].get_odb().connect(get_full_path(), m_data[i].get_odb().get_name(), write_defaults);
1422 } else if (created || write_defaults) {
1423 write();
1424 } else {
1425 read();
1426 }
1427 }
1428
1429 // send key definitions and data with optional subkeys to certain path in ODB
1430 void odb::connect(std::string str, bool write_defaults, bool delete_keys_not_in_defaults) {
1431
1432 if (str.empty())
1433 mthrow("odb::connect() cannot be called with an empty ODB path");
1434
1435 if (str[0] != '/')
1436 mthrow("odb::connect(\"" + str + "\"): path must start with leading \"/\"");
1437
1438 if (str == "/")
1439 mthrow("odb::connect(\"" + str + "\"): root ODB tree is not allowed");
1440
1442 mthrow("odb::connect(\"" + str + "\"): not allowed in STRING or FILE mode");
1443
1444 if (str.back() == '/')
1445 str = str.substr(0, str.size()-1);
1446
1447 // separate ODB path and key nam
1448 std::string name;
1449 std::string path;
1450 name = str.substr(str.find_last_of('/') + 1);
1451 path = str.substr(0, str.find_last_of('/') + 1);
1452
1453 connect(path, name, write_defaults, delete_keys_not_in_defaults);
1454 }
1455
1456 // shorthand for the same behavior as db_check_record:
1457 // - keep values of keys that already exist with the correct type
1458 // - add keys that user provided but aren't in ODB already
1459 // - delete keys that are in ODB but not in user's settings
1460 // - re-order ODB keys to match user's order
1461 void odb::connect_and_fix_structure(std::string path) {
1462 // Store the order the user specified.
1463 // Need to do this recursively before calling connect(), as the first
1464 // read() in that function merges user keys and existing keys.
1465 std::map<std::string, std::vector<std::string> > user_order;
1466 recurse_get_defaults_order(path, *this, user_order);
1467
1468 // Main connect() that adds/deletes/updates keys as needed.
1469 connect(path, false, true);
1470
1471 // Fix order in ODB (and memory)
1472 recurse_fix_order(*this, user_order);
1473 }
1474
1476 init_hdb();
1477
1479
1480 if (this->is_write_protect())
1481 mthrow("Cannot modify write protected key \"" + m_name + "\"");
1482
1483
1484 // delete key in ODB
1486 if (status != DB_SUCCESS && status != DB_INVALID_HANDLE)
1487 mthrow("db_delete_key for ODB key \"" + m_name +
1488 "\" returnd error code " + std::to_string(status));
1489
1490 if (s_debug)
1491 std::cout << "Deleted ODB key \"" + m_name + "\"" << std::endl;
1492
1493 // invalidate this object
1494 delete[] m_data;
1495 m_data = nullptr;
1496 m_num_values = 0;
1497 m_tid = 0;
1498 m_hKey = 0;
1499
1500 // set flag that this object has been deleted
1501 set_deleted(true);
1502 }
1503
1504 void odb::set_mode(int mode) {
1505 // set mode of ODB key
1506 // default is MODE_READ | MODE_WRITE | MODE_DELETE
1507
1508 init_hdb();
1509
1510 // set mode in ODB
1511 int status = db_set_mode(s_hDB, m_hKey, mode, TRUE);
1512
1514 mthrow("db_set_mode for ODB key \"" + get_full_path() +
1515 "\" returnd error code " + std::to_string(status));
1516
1517 if (s_debug)
1518 std::cout << "Set mode of ODB key \"" + get_full_path() + "\" to " << mode << std::endl;
1519 }
1520
1522 init_hdb();
1523
1524 // set mode in ODB
1525 KEY key;
1526 int status = db_get_key(s_hDB, m_hKey, &key);
1527
1529 mthrow("db_get_key for ODB key \"" + get_full_path() +
1530 "\" returnd error code " + std::to_string(status));
1531
1532 return key.access_mode;
1533 }
1534
1535 unsigned int odb::get_last_written() {
1536 init_hdb();
1537
1538 // set mode in ODB
1539 KEY key;
1540 int status = db_get_key(s_hDB, m_hKey, &key);
1541
1543 mthrow("db_get_key for ODB key \"" + get_full_path() +
1544 "\" returnd error code " + std::to_string(status));
1545
1546 return (unsigned int) (key.last_written);
1547 }
1548
1549 void odb::watch(std::function<void(midas::odb &)> f) {
1550 if (m_hKey == 0 || m_hKey == -1)
1551 mthrow("watch() called for ODB key \"" + m_name +
1552 "\" which is not connected to ODB");
1553
1554 // create a deep copy of current object in case it
1555 // goes out of scope
1556 midas::odb* ow = new midas::odb(*this);
1557
1558 ow->m_watch_callback = f;
1560
1561 // put object into watchlist
1562 g_watchlist.push_back(ow);
1563 }
1564
1566 {
1567 for (int i=0 ; i<(int) g_watchlist.size() ; i++) {
1568 if (g_watchlist[i]->get_hkey() == this->get_hkey()) {
1569 db_unwatch(s_hDB, g_watchlist[i]->get_hkey());
1570 delete g_watchlist[i];
1571 g_watchlist.erase(g_watchlist.begin() + i);
1572 i--;
1573 }
1574 }
1575 }
1576
1578 {
1579 for (int i=0 ; i<(int) g_watchlist.size() ; i++) {
1581 delete g_watchlist[i];
1582 }
1583 g_watchlist.clear();
1584 }
1585
1586 void odb::set(std::string s)
1587 {
1588 if (this->is_write_protect())
1589 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1590
1591 if (m_tid == TID_BOOL)
1592 s = (s == "y" || s == "1") ? "1" : "0";
1593
1594 m_num_values = 1;
1595 m_data = new u_odb[1];
1596 m_data[0].set_parent(this);
1597 m_data[0].set_tid(m_tid);
1598 m_data[0].set(s);
1599 }
1600
1601 void odb::set(std::string s, int i)
1602 {
1603 if (this->is_write_protect())
1604 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1605
1606 if (m_tid == TID_BOOL)
1607 s = (s == "y" || s == "1") ? "1" : "0";
1608
1609 if (m_data == nullptr)
1610 m_data = new u_odb[m_num_values];
1611 m_data[i].set_parent(this);
1613 m_data[i].set(s);
1614 }
1615
1616 void odb::set_string_size(std::string s, int size)
1617 {
1618 if (this->is_write_protect())
1619 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1620
1621 m_num_values = 1;
1622 m_tid = TID_STRING;
1623 m_data = new u_odb[1];
1624 m_data[0].set_parent(this);
1625 m_data[0].set_tid(m_tid);
1628 }
1629
1630 void odb::set_odb(odb *o, int i)
1631 {
1632 if (this->is_write_protect())
1633 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1634
1635 if (m_data == nullptr)
1636 m_data = new u_odb[m_num_values];
1637 m_data[i].set_parent(this);
1639 m_data[i].set_odb(o);
1640 }
1641
1642 void odb::set_odb_source(const odb::odb_source s, const std::string str) {
1643
1644 s_odb_source = s;
1646
1647 if (s_odb != nullptr)
1648 delete s_odb;
1649 s_odb = nullptr;
1650
1651 if (s == odb::FILE) {
1652 // check file contents
1653 std::ifstream file(str);
1654 if (!file)
1655 mthrow("File \"" + str + "\" not found");
1656 std::ostringstream ss;
1657 ss << file.rdbuf();
1658 file.close();
1659
1660 // create new root ODB object
1661 s_odb = new midas::odb();
1662
1663 // populate object from file string
1664 if (s_odb_source_str.find(".xml") != std::string::npos ||
1665 s_odb_source_str.find(".XML") != std::string::npos)
1666 odb_from_xml_string(ss.str());
1667 else if (s_odb_source_str.find(".json") != std::string::npos ||
1668 s_odb_source_str.find(".JSON") != std::string::npos)
1669 odb_from_json_string(ss.str());
1670 else
1671 mthrow("File type of \"" +s_odb_source_str + "\" is not supported");
1672 }
1673
1674 if (s == odb::STRING) {
1675
1676 // create new root ODB object
1677 s_odb = new midas::odb();
1678
1679 // populate object from string
1680 if (s_odb_source_str.substr(0, 19) == "<?xml version=\"1.0\"")
1682 else if (s_odb_source_str.substr(0, 1) == "{")
1684 else
1685 mthrow("Unknown string format: \"" + s_odb_source_str + "\"");
1686 }
1687
1688 // std::cout << s_odb->dump() << std::endl;
1689 }
1690
1691 //-----------------------------------------------
1692
1693 //---- u_odb implementations calling functions from odb
1694
1696 if (m_tid == TID_STRING || m_tid == TID_LINK)
1697 delete m_string;
1698 else if (m_tid == TID_KEY)
1699 delete m_odb;
1700 }
1701
1702 // get function for strings
1703 void u_odb::get(std::string &s) {
1704 if (m_tid == TID_UINT8)
1705 s = std::to_string(m_uint8);
1706 else if (m_tid == TID_INT8)
1707 s = std::to_string(m_int8);
1708 else if (m_tid == TID_UINT16)
1709 s = std::to_string(m_uint16);
1710 else if (m_tid == TID_INT16)
1711 s = std::to_string(m_int16);
1712 else if (m_tid == TID_UINT32)
1713 s = std::to_string(m_uint32);
1714 else if (m_tid == TID_INT32)
1715 s = std::to_string(m_int32);
1716 else if (m_tid == TID_UINT64)
1717 s = std::to_string(m_uint64);
1718 else if (m_tid == TID_INT64)
1719 s = std::to_string(m_int64);
1720 else if (m_tid == TID_BOOL)
1721 s = std::string(m_bool ? "true" : "false");
1722 else if (m_tid == TID_FLOAT)
1723 s = std::to_string(m_float);
1724 else if (m_tid == TID_DOUBLE)
1725 s = std::to_string(m_double);
1726 else if (m_tid == TID_STRING)
1727 s = *m_string;
1728 else if (m_tid == TID_LINK)
1729 s = *m_string;
1730 else if (m_tid == TID_KEY)
1731 m_odb->print(s, 0);
1732 else if (m_tid == 0)
1733 mthrow("Subkey \"" + m_parent_odb->get_name() + "\" not found");
1734 else
1735 mthrow("Invalid type ID " + std::to_string(m_tid));
1736 }
1737
1738 //---- u_odb assignment and arithmetic operators overloads which call odb::write()
1739
1740 // overload assignment operators
1741 uint8_t u_odb::operator=(uint8_t v) {
1742 if (m_tid == 0)
1743 m_tid = TID_UINT8;
1744 set(v);
1747 return v;
1748 }
1749 int8_t u_odb::operator=(int8_t v) {
1750 if (m_tid == 0)
1751 m_tid = TID_INT8;
1752 set(v);
1755 return v;
1756 }
1757 uint16_t u_odb::operator=(uint16_t v) {
1758 if (m_tid == 0)
1759 m_tid = TID_UINT16;
1760 set(v);
1763 return v;
1764 }
1765 int16_t u_odb::operator=(int16_t v) {
1766 if (m_tid == 0)
1767 m_tid = TID_INT16;
1768 set(v);
1771 return v;
1772 }
1773 uint32_t u_odb::operator=(uint32_t v) {
1774 if (m_tid == 0)
1775 m_tid = TID_UINT32;
1776 set(v);
1779 return v;
1780 }
1781 int32_t u_odb::operator=(int32_t v) {
1782 if (m_tid == 0)
1783 m_tid = TID_INT32;
1784 set(v);
1787 return v;
1788 }
1789 uint64_t u_odb::operator=(uint64_t v) {
1790 if (m_tid == 0)
1791 m_tid = TID_UINT64;
1792 set(v);
1795 return v;
1796 }
1797 int64_t u_odb::operator=(int64_t v) {
1798 if (m_tid == 0)
1799 m_tid = TID_INT64;
1800 set(v);
1803 return v;
1804 }
1805 bool u_odb::operator=(bool v) {
1806 if (m_tid == 0)
1807 m_tid = TID_BOOL;
1808 set(v);
1811 return v;
1812 }
1813 float u_odb::operator=(float v) {
1814 if (m_tid == 0)
1815 m_tid = TID_FLOAT;
1816 set(v);
1819 return v;
1820 }
1821 double u_odb::operator=(double v) {
1822 if (m_tid == 0)
1823 m_tid = TID_DOUBLE;
1824 set(v);
1827 return v;
1828 }
1829 const char * u_odb::operator=(const char * v) {
1830 if (m_tid == 0)
1831 m_tid = TID_STRING;
1832 set(v);
1835 return v;
1836 }
1837
1838 std::string * u_odb::operator=(std::string * v){
1839 if (m_tid == 0)
1840 m_tid = TID_STRING;
1841 set(*v);
1844 return v;
1845 }
1846
1847 std::string u_odb::operator=(std::string v){
1848 if (m_tid == 0)
1849 m_tid = TID_STRING;
1850 set(v);
1853 return v;
1854 }
1855
1856 void u_odb::set_string_size(std::string v, int size) {
1857 m_tid = TID_STRING;
1858 set(v);
1860 m_parent_odb->write(size);
1861 }
1862
1863 // overload all standard conversion operators
1864 u_odb::operator uint8_t() {
1865 if (m_parent_odb)
1866 m_parent_odb->set_last_index(-1);
1867 return get<uint8_t>();
1868 }
1869 u_odb::operator int8_t() {
1870 if (m_parent_odb)
1871 m_parent_odb->set_last_index(-1);
1872 return get<int8_t>();
1873 }
1874 u_odb::operator uint16_t() {
1875 if (m_parent_odb)
1876 m_parent_odb->set_last_index(-1);
1877 return get<uint16_t>();
1878 }
1879 u_odb::operator int16_t() {
1880 if (m_parent_odb)
1881 m_parent_odb->set_last_index(-1);
1882 return get<int16_t>();
1883 }
1884 u_odb::operator uint32_t() {
1885 if (m_parent_odb)
1886 m_parent_odb->set_last_index(-1);
1887 return get<uint32_t>();
1888 }
1889 u_odb::operator int32_t() {
1890 if (m_parent_odb)
1891 m_parent_odb->set_last_index(-1);
1892 return get<int32_t>();
1893 }
1894 u_odb::operator uint64_t() {
1895 if (m_parent_odb)
1896 m_parent_odb->set_last_index(-1);
1897 return get<uint64_t>();
1898 }
1899 u_odb::operator int64_t() {
1900 if (m_parent_odb)
1901 m_parent_odb->set_last_index(-1);
1902 return get<int64_t>();
1903 }
1904 u_odb::operator bool() {
1905 if (m_parent_odb)
1906 m_parent_odb->set_last_index(-1);
1907 return get<bool>();
1908 }
1909 u_odb::operator float() {
1910 if (m_parent_odb)
1911 m_parent_odb->set_last_index(-1);
1912 return get<float>();
1913 }
1914 u_odb::operator double() {
1915 if (m_parent_odb)
1916 m_parent_odb->set_last_index(-1);
1917 return get<double>();
1918 }
1919 u_odb::operator std::string() {
1920 if (m_parent_odb)
1921 m_parent_odb->set_last_index(-1);
1922 std::string s;
1923 get(s);
1924 return s;
1925 }
1926 u_odb::operator const char *() {
1927 if (m_parent_odb)
1928 m_parent_odb->set_last_index(-1);
1929 if (m_tid != TID_STRING && m_tid != TID_LINK)
1930 mthrow("Only ODB string keys can be converted to \"const char *\"");
1931 return m_string->c_str();
1932 }
1933 u_odb::operator midas::odb&() {
1934 if (m_parent_odb)
1935 m_parent_odb->set_last_index(-1);
1936 if (m_tid != TID_KEY)
1937 mthrow("Only ODB directories can be converted to \"midas::odb &\"");
1938 return *m_odb;
1939 }
1940
1941
1942 void u_odb::add(double inc, bool write) {
1943 if (m_tid == TID_UINT8)
1944 m_uint8 += inc;
1945 else if (m_tid == TID_INT8)
1946 m_int8 += inc;
1947 else if (m_tid == TID_UINT16)
1948 m_uint16 += inc;
1949 else if (m_tid == TID_INT16)
1950 m_int16 += inc;
1951 else if (m_tid == TID_UINT32)
1952 m_uint32 += inc;
1953 else if (m_tid == TID_INT32)
1954 m_int32 += inc;
1955 else if (m_tid == TID_FLOAT)
1956 m_float += static_cast<float>(inc);
1957 else if (m_tid == TID_DOUBLE)
1958 m_double += inc;
1959 else
1960 mthrow("Invalid arithmetic operation for ODB key \"" +
1961 m_parent_odb->get_full_path() + "\"");
1964 }
1965
1966 void u_odb::mult(double f, bool write) {
1967 int tid = m_parent_odb->get_tid();
1968 if (tid == TID_UINT8)
1969 m_uint8 *= f;
1970 else if (tid == TID_INT8)
1971 m_int8 *= f;
1972 else if (tid == TID_UINT16)
1973 m_uint16 *= f;
1974 else if (tid == TID_INT16)
1975 m_int16 *= f;
1976 else if (tid == TID_UINT32)
1977 m_uint32 *= f;
1978 else if (tid == TID_INT32)
1979 m_int32 *= f;
1980 else if (tid == TID_FLOAT)
1981 m_float *= f;
1982 else if (tid == TID_DOUBLE)
1983 m_double *= f;
1984 else
1985 mthrow("Invalid operation for ODB key \"" +
1986 m_parent_odb->get_full_path() + "\"");
1989 }
1990
1991}; // namespace midas
void set_string_size(std::string s, int size)
Definition odbxx.cxx:1616
std::string get_parent_path()
Definition odbxx.cxx:378
std::string get_full_path()
Definition odbxx.cxx:362
void set(std::string str)
Definition odbxx.cxx:1586
int m_num_values
Definition odbxx.h:475
static bool exists(const std::string &name)
Definition odbxx.cxx:76
std::string get_name()
Definition odbxx.h:1462
void write(int str_size=0)
Definition odbxx.cxx:1113
int m_tid
Definition odbxx.h:469
void set_mode(int mode)
Definition odbxx.cxx:1504
void set_auto_refresh_read(bool f)
Definition odbxx.h:1368
void set_auto_enlarge_array(bool f)
Definition odbxx.h:1389
void delete_key()
Definition odbxx.cxx:1475
void set_odb(odb *o, int i)
Definition odbxx.cxx:1630
u_odb * m_data
Definition odbxx.h:471
void deep_copy(odb &d, const odb &s)
Definition odbxx.cxx:334
bool is_deleted() const
Definition odbxx.h:536
static midas::odb * odb_from_xml(PMXML_NODE node, odb *o)
Definition odbxx.h:1207
bool is_auto_refresh_read() const
Definition odbxx.h:1367
static void unwatch_all()
Definition odbxx.cxx:1577
static HNDLE s_hDB
Definition odbxx.h:458
HNDLE get_hkey()
Definition odbxx.h:1457
static void set_odb_source(odb::odb_source s)
Definition odbxx.h:1422
std::function< void(midas::odb &)> m_watch_callback
Definition odbxx.h:481
bool is_auto_create() const
Definition odbxx.h:1382
bool is_preserve_string_size() const
Definition odbxx.h:1361
static void watch_callback(int hDB, int hKey, int index, void *info)
Definition odbxx.cxx:124
void unwatch()
Definition odbxx.cxx:1565
T get()
Definition odbxx.h:500
int get_tid()
Definition odbxx.h:1460
static midas::odb * odb_from_json(const MJsonNode *node, std::string name, int tid, odb *o)
Definition odbxx.h:1284
static bool get_debug()
Definition odbxx.h:1408
bool is_auto_refresh_write() const
Definition odbxx.h:1373
void set_tid(int tid)
Definition odbxx.h:539
bool read_key(const std::string &path)
Definition odbxx.cxx:657
void resize(int size)
Definition odbxx.cxx:391
void set_preserve_string_size(bool f)
Definition odbxx.h:1362
static thread_local odb_source s_odb_source
Definition odbxx.h:453
void set_trigger_hotlink(bool f)
Definition odbxx.h:1401
int size()
Definition odbxx.cxx:386
void set_flags(uint32_t f)
Definition odbxx.h:533
void set_auto_refresh_write(bool f)
Definition odbxx.h:1374
int get_mode()
Definition odbxx.cxx:1521
void odb_from_xml_remote(const std::string &str)
Definition odbxx.cxx:160
void set_auto_create(bool f)
Definition odbxx.h:1383
static thread_local std::string s_odb_source_str
Definition odbxx.h:454
void odb_from_xml_string(const std::string &str, const std::string &subkey)
void read()
Definition odbxx.cxx:802
void resize_mdata(int size)
Definition odbxx.cxx:261
odb & get_subkey(std::string str)
Definition odbxx.cxx:568
void odb_from_json_string(const std::string &str, const std::string &subkey)
void set_flags_recursively(uint32_t f)
Definition odbxx.cxx:152
unsigned int get_last_written()
Definition odbxx.cxx:1535
void set_name(std::string s)
Definition odbxx.h:542
int get_subkeys(std::vector< std::string > &name)
Definition odbxx.cxx:632
void watch(std::function< void(midas::odb &)> f)
Definition odbxx.cxx:1549
static thread_local odb * s_odb
Definition odbxx.h:456
std::string s()
Definition odbxx.h:1465
void save(const std::string &filename)
Definition odbxx.cxx:518
void set_last_index(int i)
Definition odbxx.h:1021
static int create(const char *name, int type=TID_KEY)
Definition odbxx.cxx:140
bool is_subkey(std::string str)
Definition odbxx.cxx:544
static bool s_debug
Definition odbxx.h:460
void fix_order(std::vector< std::string > target_subkey_order)
Definition odbxx.cxx:1316
std::string dump()
Definition odbxx.cxx:427
int m_last_index
Definition odbxx.h:477
void connect_and_fix_structure(std::string path)
Definition odbxx.cxx:1461
static bool s_connected_odb
Definition odbxx.h:462
static void init_hdb()
Definition odbxx.cxx:50
uint32_t get_flags()
Definition odbxx.h:534
bool is_trigger_hotlink() const
Definition odbxx.h:1400
bool write_key(std::string &path, bool write_defaults)
Definition odbxx.cxx:743
std::string print()
Definition odbxx.cxx:419
static midas::odb * search_hkey(midas::odb *po, int hKey)
Definition odbxx.cxx:62
static bool is_connected_odb()
Definition odbxx.h:1434
std::bitset< 9 > m_flags
Definition odbxx.h:467
void set_deleted(bool f)
Definition odbxx.h:537
static void load(const std::string &filename, const std::string &odb_path)
Definition odbxx.cxx:102
void set_parent(midas::odb *p)
Definition odbxx.h:544
HNDLE m_hKey
Definition odbxx.h:479
void set_write_protect(bool f)
Definition odbxx.h:1395
std::string m_name
Definition odbxx.h:473
bool is_write_protect() const
Definition odbxx.h:1394
void connect(const std::string &path, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults=false)
Definition odbxx.cxx:1379
midas::odb * m_parent
Definition odbxx.h:483
uint8_t m_uint8
Definition odbxx.h:52
bool m_bool
Definition odbxx.h:60
uint8_t operator=(uint8_t v)
Definition odbxx.cxx:1741
void set_tid(int tid)
Definition odbxx.h:105
void mult(double f, bool push=true)
Definition odbxx.cxx:1966
void set_string(std::string s)
Definition odbxx.h:172
int8_t m_int8
Definition odbxx.h:53
uint64_t m_uint64
Definition odbxx.h:58
int32_t m_int32
Definition odbxx.h:57
int64_t m_int64
Definition odbxx.h:59
void set(T v)
Definition odbxx.h:142
double m_double
Definition odbxx.h:62
odb * m_parent_odb
Definition odbxx.h:68
void set_odb(odb *v)
Definition odbxx.h:189
int m_tid
Definition odbxx.h:67
void add(double inc, bool push=true)
Definition odbxx.cxx:1942
void set_parent(odb *o)
Definition odbxx.h:102
uint16_t m_uint16
Definition odbxx.h:54
odb * get_podb()
Definition odbxx.h:375
void set_string_size(std::string s, int size)
Definition odbxx.cxx:1856
int16_t m_int16
Definition odbxx.h:55
odb & get_odb()
Definition odbxx.h:381
std::string s()
Definition odbxx.h:367
std::string * m_string
Definition odbxx.h:63
void set_string_ptr(std::string *s)
Definition odbxx.h:179
odb * m_odb
Definition odbxx.h:64
float m_float
Definition odbxx.h:61
uint32_t m_uint32
Definition odbxx.h:56
size_t string_size() const
Definition odbxx.h:360
int get_tid()
Definition odbxx.h:107
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3027
#define DB_KEY_EXIST
Definition midas.h:642
#define DB_INVALID_HANDLE
Definition midas.h:636
#define DB_SUCCESS
Definition midas.h:632
#define DB_NO_KEY
Definition midas.h:643
#define DB_CREATED
Definition midas.h:633
#define DB_TRUNCATED
Definition midas.h:645
#define TID_DOUBLE
Definition midas.h:343
#define TID_KEY
Definition midas.h:349
#define TID_BOOL
Definition midas.h:340
#define TID_UINT64
Definition midas.h:352
#define TID_INT64
Definition midas.h:351
#define TID_INT32
Definition midas.h:339
#define TID_UINT8
Definition midas.h:328
#define TID_LINK
Definition midas.h:350
#define TID_STRING
Definition midas.h:346
#define TID_INT8
Definition midas.h:330
#define TID_UINT32
Definition midas.h:337
#define TID_UINT16
Definition midas.h:333
#define TID_INT16
Definition midas.h:335
#define TID_FLOAT
Definition midas.h:341
#define TID_LAST
Definition midas.h:354
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3285
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6917
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
Definition odb.cxx:3933
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
Definition odb.cxx:6385
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
Definition odb.cxx:4775
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6563
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3392
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
Definition odb.cxx:9055
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13920
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:8040
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6043
INT db_load(HNDLE hDB, HNDLE hKeyRoot, const char *filename, BOOL bRemote)
Definition odb.cxx:8139
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
Definition odb.cxx:13845
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7239
INT db_set_data1(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7337
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
Definition odb.cxx:7844
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
Definition odb.cxx:7523
INT rpc_tid_size(INT id)
Definition midas.cxx:11888
void ** info
Definition fesimdaq.cxx:41
HNDLE hKey
DWORD n[4]
Definition mana.cxx:247
INT index
Definition mana.cxx:271
INT type
Definition mana.cxx:269
HNDLE hDB
main ODB handle
Definition mana.cxx:207
KEY key
Definition mdump.cxx:34
INT i
Definition mdump.cxx:32
#define mthrow(arg)
Definition mexcept.h:24
INT HNDLE
Definition midas.h:132
DWORD BOOL
Definition midas.h:105
#define TRUE
Definition midas.h:182
#define write(n, a, f, d)
#define name(x)
Definition midas_macro.h:24
#define set(var, value)
static std::string indent(int x, const char *p=" ")
std::vector< std::string > split(std::string input, char delimiter='/')
Definition odbxx.cxx:222
void recurse_fix_order(midas::odb &default_odb, std::map< std::string, std::vector< std::string > > &user_order)
Definition odbxx.cxx:1302
void recurse_get_defaults_order(std::string path, midas::odb &default_odb, std::map< std::string, std::vector< std::string > > &retval)
Definition odbxx.cxx:1292
std::vector< midas::odb * > g_watchlist
Definition odbxx.cxx:45
void recurse_del_keys_not_in_defaults(std::string path, HNDLE hDB, HNDLE hKey, midas::odb &default_odb)
Definition odbxx.cxx:1255
INT k
Definition odbhist.cxx:40
char str[256]
Definition odbhist.cxx:33
DWORD status
Definition odbhist.cxx:39
Definition midas.h:1027
INT num_values
Definition midas.h:1029
DWORD type
Definition midas.h:1028
INT total_size
Definition midas.h:1032
WORD access_mode
Definition midas.h:1034
INT last_written
Definition midas.h:1038
char name[NAME_LENGTH]
Definition midas.h:1030
INT item_size
Definition midas.h:1033
double d
Definition system.cxx:1313
static double sub(double a, double b)
Definition tinyexpr.c:244