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) {
1176 KEY key;
1178 if (key.item_size == 0 || key.total_size == 0) {
1179 int size = 1;
1180 for (int i = 0; i < m_num_values; i++) {
1181 std::string d;
1182 m_data[i].get(d);
1183 if ((int) d.size() + 1 > size)
1184 size = d.size() + 1;
1185 }
1186 // round up to multiples of 32
1187 size = (((size - 1) / 32) + 1) * 32;
1188 key.item_size = size;
1190 }
1191 char *str = (char *) calloc(m_num_values, key.item_size);
1192 for (int i = 0; i < m_num_values; i++) {
1193 std::string d;
1194 m_data[i].get(d);
1195 strncpy(str + i * key.item_size, d.c_str(), key.item_size);
1196 }
1197 if (is_trigger_hotlink())
1199 else
1201 free(str);
1202 if (s_debug) {
1203 std::string s;
1204 get(s, true, false);
1205 std::cout << "Set ODB key \"" + get_full_path() +
1206 "[0..." + std::to_string(m_num_values - 1) + "]\" = [" + s + "]" << std::endl;
1207 }
1208 } else {
1209 std::string s;
1210 m_data[0].get(s);
1211 if (is_trigger_hotlink())
1212 status = db_set_data(s_hDB, m_hKey, s.c_str(), s.length() + 1, 1, m_tid);
1213 else
1214 status = db_set_data1(s_hDB, m_hKey, s.c_str(), s.length() + 1, 1, m_tid);
1215 if (s_debug)
1216 std::cout << "Set ODB key \"" + get_full_path() + "\" = " + s << std::endl;
1217 }
1218 } else {
1220 uint8_t *buffer = (uint8_t *) malloc(size);
1221 uint8_t *p = buffer;
1222 for (int i = 0; i < m_num_values; i++) {
1223 if (m_tid == TID_BOOL) {
1224 // bool has 1 Byte, BOOL has 4 Bytes
1225 BOOL b = static_cast<bool>(m_data[i]);
1226 memcpy(p, &b, rpc_tid_size(m_tid));
1227 } else {
1228 memcpy(p, (void*)&m_data[i], rpc_tid_size(m_tid));
1229 }
1230 p += rpc_tid_size(m_tid);
1231 }
1232 if (is_trigger_hotlink())
1234 else
1236 free(buffer);
1237 if (s_debug) {
1238 std::string s;
1239 get(s, false, false);
1240 if (m_num_values > 1)
1241 std::cout << "Set ODB key \"" + get_full_path() + "[0..." + std::to_string(m_num_values - 1) +
1242 "]\" = [" + s + "]" << std::endl;
1243 else
1244 std::cout << "Set ODB key \"" + get_full_path() + "\" = " + s << std::endl;
1245 }
1246 }
1247
1248 if (status != DB_SUCCESS)
1249 mthrow("db_set_data for ODB key \"" + get_full_path() +
1250 "\" failed with status " + std::to_string(status));
1251 }
1252
1253 void recurse_del_keys_not_in_defaults(std::string path, HNDLE hDB, HNDLE hKey, midas::odb& default_odb) {
1254 // Delete any subkeys that are not in the list of defaults.
1255 KEY key;
1256 db_get_key(hDB, hKey, &key);
1257
1258 if (key.type == TID_KEY) {
1259 std::vector<std::string> to_delete;
1260
1261 for (int i = 0;; i++) {
1262 HNDLE hSubKey;
1263 int status = db_enum_key(hDB, hKey, i, &hSubKey);
1264 if (status != DB_SUCCESS)
1265 break;
1266
1267 KEY subKey;
1268 db_get_key(hDB, hSubKey, &subKey);
1269 std::string full_path = path + "/" + subKey.name;
1270
1271 if (!default_odb.is_subkey(subKey.name)) {
1272 to_delete.push_back(subKey.name);
1273
1274 if (default_odb.get_debug()) {
1275 std::cout << "Deleting " << full_path << " as not in list of defaults" << std::endl;
1276 }
1277 } else if (key.type == TID_KEY) {
1278 recurse_del_keys_not_in_defaults(full_path, hDB, hSubKey, default_odb[(const char *)(subKey.name)]);
1279 }
1280 }
1281
1282 for (auto name : to_delete) {
1283 HNDLE hSubKey;
1284 db_find_key(hDB, hKey, name.c_str(), &hSubKey);
1285 db_delete_key(hDB, hSubKey);
1286 }
1287 }
1288 }
1289
1290 void recurse_get_defaults_order(std::string path, midas::odb& default_odb, std::map<std::string, std::vector<std::string> >& retval) {
1291 for (midas::odb& sub : default_odb) {
1292 if (sub.get_tid() == TID_KEY) {
1293 recurse_get_defaults_order(path + "/" + sub.get_name(), sub, retval);
1294 }
1295
1296 retval[path].push_back(sub.get_name());
1297 }
1298 }
1299
1300 void recurse_fix_order(midas::odb& default_odb, std::map<std::string, std::vector<std::string> >& user_order) {
1301 std::string path = default_odb.get_full_path();
1302
1303 if (user_order.find(path) != user_order.end()) {
1304 default_odb.fix_order(user_order[path]);
1305 }
1306
1307 for (midas::odb& it : default_odb) {
1308 if (it.get_tid() == TID_KEY) {
1309 recurse_fix_order(it, user_order);
1310 }
1311 }
1312 }
1313
1314 void odb::fix_order(std::vector<std::string> target_order) {
1315 // Fix the order of ODB keys to match that specified in target_order.
1316 // The in-ODB representation is simple, as we can just use db_reorder_key()
1317 // on anything that's in the wrong place.
1318 // The in-memory representation is a little trickier, but we just copy raw
1319 // memory into a temporary array, so we don't have to delete/recreate the
1320 // u_odb objects.
1321 std::vector<std::string> curr_order;
1322
1323 if (get_subkeys(curr_order) <= 0) {
1324 // Not a TID_KEY (or no keys)
1325 return;
1326 }
1327
1328 if (target_order.size() != curr_order.size() || (int)target_order.size() != m_num_values) {
1329 return;
1330 }
1331
1332 HNDLE hKey = get_hkey();
1333 bool force_order = false;
1334
1335 // Temporary location where we'll store in-memory u_odb objects in th
1336 // correct order.
1337 u_odb* new_m_data = new u_odb[m_num_values];
1338
1339 for (int i = 0; i < m_num_values; i++) {
1340 if (force_order || curr_order[i] != target_order[i]) {
1341 force_order = true;
1342 HNDLE hSubKey;
1343
1344 // Fix the order in the ODB
1345 db_find_key(s_hDB, hKey, target_order[i].c_str(), &hSubKey);
1346 db_reorder_key(s_hDB, hSubKey, i);
1347 }
1348
1349 // Fix the order in memory
1350 auto curr_it = std::find(curr_order.begin(), curr_order.end(), target_order[i]);
1351
1352 if (curr_it == curr_order.end()) {
1353 // Logic error - bail to avoid doing any damage to the in-memory version.
1354 delete[] new_m_data;
1355 return;
1356 }
1357
1358 int curr_idx = curr_it - curr_order.begin();
1359 new_m_data[i] = m_data[curr_idx];
1360 }
1361
1362 // Final update of the in-memory version so they are in the correct order
1363 for (int i = 0; i < m_num_values; i++) {
1364 m_data[i] = new_m_data[i];
1365
1366 // Nullify pointers that point to the same object in
1367 // m_data and new_m_data, so the underlying object doesn't
1368 // get destroyed when we delete new_m_data.
1369 new_m_data[i].set_string_ptr(nullptr);
1370 new_m_data[i].set_odb(nullptr);
1371 }
1372
1373 delete[] new_m_data;
1374 }
1375
1376 // connect function with separated path and key name
1377 void odb::connect(const std::string &p, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults) {
1378 init_hdb();
1379
1380 if (!name.empty())
1381 m_name = name;
1382 std::string path(p);
1383
1384 if (path.empty())
1385 mthrow("odb::connect() cannot be called with an empty ODB path");
1386
1387 if (path[0] != '/')
1388 mthrow("odb::connect(\"" + path + "\"): path must start with leading \"/\"");
1389
1390 if (path.back() != '/')
1391 path += "/";
1392
1393 path += m_name;
1394
1395 HNDLE hKey;
1396 int status = db_find_key(s_hDB, 0, path.c_str(), &hKey);
1397 bool key_exists = (status == DB_SUCCESS);
1398 bool created = false;
1399
1400 if (key_exists && delete_keys_not_in_defaults) {
1401 // Recurse down to delete keys as needed.
1402 // We need to do this recursively BEFORE calling read/read_key for the first time
1403 // to ensure that subdirectories get handled correctly.
1405 }
1406
1407 if (!key_exists || write_defaults) {
1408 created = write_key(path, write_defaults);
1409 } else {
1410 read_key(path);
1411 }
1412
1413 // correct wrong parent ODB from initializer_list
1414 for (int i = 0; i < m_num_values; i++)
1415 m_data[i].set_parent(this);
1416
1417 if (m_tid == TID_KEY) {
1418 for (int i = 0; i < m_num_values; i++)
1419 m_data[i].get_odb().connect(get_full_path(), m_data[i].get_odb().get_name(), write_defaults);
1420 } else if (created || write_defaults) {
1421 write();
1422 } else {
1423 read();
1424 }
1425 }
1426
1427 // send key definitions and data with optional subkeys to certain path in ODB
1428 void odb::connect(std::string str, bool write_defaults, bool delete_keys_not_in_defaults) {
1429
1430 if (str.empty())
1431 mthrow("odb::connect() cannot be called with an empty ODB path");
1432
1433 if (str[0] != '/')
1434 mthrow("odb::connect(\"" + str + "\"): path must start with leading \"/\"");
1435
1436 if (str == "/")
1437 mthrow("odb::connect(\"" + str + "\"): root ODB tree is not allowed");
1438
1440 mthrow("odb::connect(\"" + str + "\"): not allowed in STRING or FILE mode");
1441
1442 if (str.back() == '/')
1443 str = str.substr(0, str.size()-1);
1444
1445 // separate ODB path and key nam
1446 std::string name;
1447 std::string path;
1448 name = str.substr(str.find_last_of('/') + 1);
1449 path = str.substr(0, str.find_last_of('/') + 1);
1450
1451 connect(path, name, write_defaults, delete_keys_not_in_defaults);
1452 }
1453
1454 // shorthand for the same behavior as db_check_record:
1455 // - keep values of keys that already exist with the correct type
1456 // - add keys that user provided but aren't in ODB already
1457 // - delete keys that are in ODB but not in user's settings
1458 // - re-order ODB keys to match user's order
1459 void odb::connect_and_fix_structure(std::string path) {
1460 // Store the order the user specified.
1461 // Need to do this recursively before calling connect(), as the first
1462 // read() in that function merges user keys and existing keys.
1463 std::map<std::string, std::vector<std::string> > user_order;
1464 recurse_get_defaults_order(path, *this, user_order);
1465
1466 // Main connect() that adds/deletes/updates keys as needed.
1467 connect(path, false, true);
1468
1469 // Fix order in ODB (and memory)
1470 recurse_fix_order(*this, user_order);
1471 }
1472
1474 init_hdb();
1475
1477
1478 if (this->is_write_protect())
1479 mthrow("Cannot modify write protected key \"" + m_name + "\"");
1480
1481
1482 // delete key in ODB
1484 if (status != DB_SUCCESS && status != DB_INVALID_HANDLE)
1485 mthrow("db_delete_key for ODB key \"" + m_name +
1486 "\" returnd error code " + std::to_string(status));
1487
1488 if (s_debug)
1489 std::cout << "Deleted ODB key \"" + m_name + "\"" << std::endl;
1490
1491 // invalidate this object
1492 delete[] m_data;
1493 m_data = nullptr;
1494 m_num_values = 0;
1495 m_tid = 0;
1496 m_hKey = 0;
1497
1498 // set flag that this object has been deleted
1499 set_deleted(true);
1500 }
1501
1502 void odb::set_mode(int mode) {
1503 // set mode of ODB key
1504 // default is MODE_READ | MODE_WRITE | MODE_DELETE
1505
1506 init_hdb();
1507
1508 // set mode in ODB
1509 int status = db_set_mode(s_hDB, m_hKey, mode, TRUE);
1510
1512 mthrow("db_set_mode for ODB key \"" + get_full_path() +
1513 "\" returnd error code " + std::to_string(status));
1514
1515 if (s_debug)
1516 std::cout << "Set mode of ODB key \"" + get_full_path() + "\" to " << mode << std::endl;
1517 }
1518
1520 init_hdb();
1521
1522 // set mode in ODB
1523 KEY key;
1524 int status = db_get_key(s_hDB, m_hKey, &key);
1525
1527 mthrow("db_get_key for ODB key \"" + get_full_path() +
1528 "\" returnd error code " + std::to_string(status));
1529
1530 return key.access_mode;
1531 }
1532
1533 unsigned int odb::get_last_written() {
1534 init_hdb();
1535
1536 // set mode in ODB
1537 KEY key;
1538 int status = db_get_key(s_hDB, m_hKey, &key);
1539
1541 mthrow("db_get_key for ODB key \"" + get_full_path() +
1542 "\" returnd error code " + std::to_string(status));
1543
1544 return (unsigned int) (key.last_written);
1545 }
1546
1547 void odb::watch(std::function<void(midas::odb &)> f) {
1548 if (m_hKey == 0 || m_hKey == -1)
1549 mthrow("watch() called for ODB key \"" + m_name +
1550 "\" which is not connected to ODB");
1551
1552 // create a deep copy of current object in case it
1553 // goes out of scope
1554 midas::odb* ow = new midas::odb(*this);
1555
1556 ow->m_watch_callback = f;
1558
1559 // put object into watchlist
1560 g_watchlist.push_back(ow);
1561 }
1562
1564 {
1565 for (int i=0 ; i<(int) g_watchlist.size() ; i++) {
1566 if (g_watchlist[i]->get_hkey() == this->get_hkey()) {
1567 db_unwatch(s_hDB, g_watchlist[i]->get_hkey());
1568 delete g_watchlist[i];
1569 g_watchlist.erase(g_watchlist.begin() + i);
1570 i--;
1571 }
1572 }
1573 }
1574
1576 {
1577 for (int i=0 ; i<(int) g_watchlist.size() ; i++) {
1579 delete g_watchlist[i];
1580 }
1581 g_watchlist.clear();
1582 }
1583
1584 void odb::set(std::string s)
1585 {
1586 if (this->is_write_protect())
1587 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1588
1589 if (m_tid == TID_BOOL)
1590 s = (s == "y" || s == "1") ? "1" : "0";
1591
1592 m_num_values = 1;
1593 m_data = new u_odb[1];
1594 m_data[0].set_parent(this);
1595 m_data[0].set_tid(m_tid);
1596 m_data[0].set(s);
1597 }
1598
1599 void odb::set(std::string s, int i)
1600 {
1601 if (this->is_write_protect())
1602 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1603
1604 if (m_tid == TID_BOOL)
1605 s = (s == "y" || s == "1") ? "1" : "0";
1606
1607 if (m_data == nullptr)
1608 m_data = new u_odb[m_num_values];
1609 m_data[i].set_parent(this);
1611 m_data[i].set(s);
1612 }
1613
1614 void odb::set_string_size(std::string s, int size)
1615 {
1616 if (this->is_write_protect())
1617 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1618
1619 m_num_values = 1;
1620 m_tid = TID_STRING;
1621 m_data = new u_odb[1];
1622 m_data[0].set_parent(this);
1623 m_data[0].set_tid(m_tid);
1626 }
1627
1628 void odb::set_odb(odb *o, int i)
1629 {
1630 if (this->is_write_protect())
1631 mthrow("Cannot modify write protected key \"" + get_full_path() + "\"");
1632
1633 if (m_data == nullptr)
1634 m_data = new u_odb[m_num_values];
1635 m_data[i].set_parent(this);
1637 m_data[i].set_odb(o);
1638 }
1639
1640 void odb::set_odb_source(const odb::odb_source s, const std::string str) {
1641
1642 s_odb_source = s;
1644
1645 if (s_odb != nullptr)
1646 delete s_odb;
1647 s_odb = nullptr;
1648
1649 if (s == odb::FILE) {
1650 // check file contents
1651 std::ifstream file(str);
1652 if (!file)
1653 mthrow("File \"" + str + "\" not found");
1654 std::ostringstream ss;
1655 ss << file.rdbuf();
1656 file.close();
1657
1658 // create new root ODB object
1659 s_odb = new midas::odb();
1660
1661 // populate object from file string
1662 if (s_odb_source_str.find(".xml") != std::string::npos ||
1663 s_odb_source_str.find(".XML") != std::string::npos)
1664 odb_from_xml_string(ss.str());
1665 else if (s_odb_source_str.find(".json") != std::string::npos ||
1666 s_odb_source_str.find(".JSON") != std::string::npos)
1667 odb_from_json_string(ss.str());
1668 else
1669 mthrow("File type of \"" +s_odb_source_str + "\" is not supported");
1670 }
1671
1672 if (s == odb::STRING) {
1673
1674 // create new root ODB object
1675 s_odb = new midas::odb();
1676
1677 // populate object from string
1678 if (s_odb_source_str.substr(0, 19) == "<?xml version=\"1.0\"")
1680 else if (s_odb_source_str.substr(0, 1) == "{")
1682 else
1683 mthrow("Unknown string format: \"" + s_odb_source_str + "\"");
1684 }
1685
1686 // std::cout << s_odb->dump() << std::endl;
1687 }
1688
1689 //-----------------------------------------------
1690
1691 //---- u_odb implementations calling functions from odb
1692
1694 if (m_tid == TID_STRING || m_tid == TID_LINK)
1695 delete m_string;
1696 else if (m_tid == TID_KEY)
1697 delete m_odb;
1698 }
1699
1700 // get function for strings
1701 void u_odb::get(std::string &s) {
1702 if (m_tid == TID_UINT8)
1703 s = std::to_string(m_uint8);
1704 else if (m_tid == TID_INT8)
1705 s = std::to_string(m_int8);
1706 else if (m_tid == TID_UINT16)
1707 s = std::to_string(m_uint16);
1708 else if (m_tid == TID_INT16)
1709 s = std::to_string(m_int16);
1710 else if (m_tid == TID_UINT32)
1711 s = std::to_string(m_uint32);
1712 else if (m_tid == TID_INT32)
1713 s = std::to_string(m_int32);
1714 else if (m_tid == TID_UINT64)
1715 s = std::to_string(m_uint64);
1716 else if (m_tid == TID_INT64)
1717 s = std::to_string(m_int64);
1718 else if (m_tid == TID_BOOL)
1719 s = std::string(m_bool ? "true" : "false");
1720 else if (m_tid == TID_FLOAT)
1721 s = std::to_string(m_float);
1722 else if (m_tid == TID_DOUBLE)
1723 s = std::to_string(m_double);
1724 else if (m_tid == TID_STRING)
1725 s = *m_string;
1726 else if (m_tid == TID_LINK)
1727 s = *m_string;
1728 else if (m_tid == TID_KEY)
1729 m_odb->print(s, 0);
1730 else if (m_tid == 0)
1731 mthrow("Subkey \"" + m_parent_odb->get_name() + "\" not found");
1732 else
1733 mthrow("Invalid type ID " + std::to_string(m_tid));
1734 }
1735
1736 //---- u_odb assignment and arithmetic operators overloads which call odb::write()
1737
1738 // overload assignment operators
1739 uint8_t u_odb::operator=(uint8_t v) {
1740 if (m_tid == 0)
1741 m_tid = TID_UINT8;
1742 set(v);
1745 return v;
1746 }
1747 int8_t u_odb::operator=(int8_t v) {
1748 if (m_tid == 0)
1749 m_tid = TID_INT8;
1750 set(v);
1753 return v;
1754 }
1755 uint16_t u_odb::operator=(uint16_t v) {
1756 if (m_tid == 0)
1757 m_tid = TID_UINT16;
1758 set(v);
1761 return v;
1762 }
1763 int16_t u_odb::operator=(int16_t v) {
1764 if (m_tid == 0)
1765 m_tid = TID_INT16;
1766 set(v);
1769 return v;
1770 }
1771 uint32_t u_odb::operator=(uint32_t v) {
1772 if (m_tid == 0)
1773 m_tid = TID_UINT32;
1774 set(v);
1777 return v;
1778 }
1779 int32_t u_odb::operator=(int32_t v) {
1780 if (m_tid == 0)
1781 m_tid = TID_INT32;
1782 set(v);
1785 return v;
1786 }
1787 uint64_t u_odb::operator=(uint64_t v) {
1788 if (m_tid == 0)
1789 m_tid = TID_UINT64;
1790 set(v);
1793 return v;
1794 }
1795 int64_t u_odb::operator=(int64_t v) {
1796 if (m_tid == 0)
1797 m_tid = TID_INT64;
1798 set(v);
1801 return v;
1802 }
1803 bool u_odb::operator=(bool v) {
1804 if (m_tid == 0)
1805 m_tid = TID_BOOL;
1806 set(v);
1809 return v;
1810 }
1811 float u_odb::operator=(float v) {
1812 if (m_tid == 0)
1813 m_tid = TID_FLOAT;
1814 set(v);
1817 return v;
1818 }
1819 double u_odb::operator=(double v) {
1820 if (m_tid == 0)
1821 m_tid = TID_DOUBLE;
1822 set(v);
1825 return v;
1826 }
1827 const char * u_odb::operator=(const char * v) {
1828 if (m_tid == 0)
1829 m_tid = TID_STRING;
1830 set(v);
1833 return v;
1834 }
1835
1836 std::string * u_odb::operator=(std::string * v){
1837 if (m_tid == 0)
1838 m_tid = TID_STRING;
1839 set(*v);
1842 return v;
1843 }
1844
1845 std::string u_odb::operator=(std::string v){
1846 if (m_tid == 0)
1847 m_tid = TID_STRING;
1848 set(v);
1851 return v;
1852 }
1853
1854 void u_odb::set_string_size(std::string v, int size) {
1855 m_tid = TID_STRING;
1856 set(v);
1858 m_parent_odb->write(size);
1859 }
1860
1861 // overload all standard conversion operators
1862 u_odb::operator uint8_t() {
1863 if (m_parent_odb)
1864 m_parent_odb->set_last_index(-1);
1865 return get<uint8_t>();
1866 }
1867 u_odb::operator int8_t() {
1868 if (m_parent_odb)
1869 m_parent_odb->set_last_index(-1);
1870 return get<int8_t>();
1871 }
1872 u_odb::operator uint16_t() {
1873 if (m_parent_odb)
1874 m_parent_odb->set_last_index(-1);
1875 return get<uint16_t>();
1876 }
1877 u_odb::operator int16_t() {
1878 if (m_parent_odb)
1879 m_parent_odb->set_last_index(-1);
1880 return get<int16_t>();
1881 }
1882 u_odb::operator uint32_t() {
1883 if (m_parent_odb)
1884 m_parent_odb->set_last_index(-1);
1885 return get<uint32_t>();
1886 }
1887 u_odb::operator int32_t() {
1888 if (m_parent_odb)
1889 m_parent_odb->set_last_index(-1);
1890 return get<int32_t>();
1891 }
1892 u_odb::operator uint64_t() {
1893 if (m_parent_odb)
1894 m_parent_odb->set_last_index(-1);
1895 return get<uint64_t>();
1896 }
1897 u_odb::operator int64_t() {
1898 if (m_parent_odb)
1899 m_parent_odb->set_last_index(-1);
1900 return get<int64_t>();
1901 }
1902 u_odb::operator bool() {
1903 if (m_parent_odb)
1904 m_parent_odb->set_last_index(-1);
1905 return get<bool>();
1906 }
1907 u_odb::operator float() {
1908 if (m_parent_odb)
1909 m_parent_odb->set_last_index(-1);
1910 return get<float>();
1911 }
1912 u_odb::operator double() {
1913 if (m_parent_odb)
1914 m_parent_odb->set_last_index(-1);
1915 return get<double>();
1916 }
1917 u_odb::operator std::string() {
1918 if (m_parent_odb)
1919 m_parent_odb->set_last_index(-1);
1920 std::string s;
1921 get(s);
1922 return s;
1923 }
1924 u_odb::operator const char *() {
1925 if (m_parent_odb)
1926 m_parent_odb->set_last_index(-1);
1927 if (m_tid != TID_STRING && m_tid != TID_LINK)
1928 mthrow("Only ODB string keys can be converted to \"const char *\"");
1929 return m_string->c_str();
1930 }
1931 u_odb::operator midas::odb&() {
1932 if (m_parent_odb)
1933 m_parent_odb->set_last_index(-1);
1934 if (m_tid != TID_KEY)
1935 mthrow("Only ODB directories can be converted to \"midas::odb &\"");
1936 return *m_odb;
1937 }
1938
1939
1940 void u_odb::add(double inc, bool write) {
1941 if (m_tid == TID_UINT8)
1942 m_uint8 += inc;
1943 else if (m_tid == TID_INT8)
1944 m_int8 += inc;
1945 else if (m_tid == TID_UINT16)
1946 m_uint16 += inc;
1947 else if (m_tid == TID_INT16)
1948 m_int16 += inc;
1949 else if (m_tid == TID_UINT32)
1950 m_uint32 += inc;
1951 else if (m_tid == TID_INT32)
1952 m_int32 += inc;
1953 else if (m_tid == TID_FLOAT)
1954 m_float += static_cast<float>(inc);
1955 else if (m_tid == TID_DOUBLE)
1956 m_double += inc;
1957 else
1958 mthrow("Invalid arithmetic operation for ODB key \"" +
1959 m_parent_odb->get_full_path() + "\"");
1962 }
1963
1964 void u_odb::mult(double f, bool write) {
1965 int tid = m_parent_odb->get_tid();
1966 if (tid == TID_UINT8)
1967 m_uint8 *= f;
1968 else if (tid == TID_INT8)
1969 m_int8 *= f;
1970 else if (tid == TID_UINT16)
1971 m_uint16 *= f;
1972 else if (tid == TID_INT16)
1973 m_int16 *= f;
1974 else if (tid == TID_UINT32)
1975 m_uint32 *= f;
1976 else if (tid == TID_INT32)
1977 m_int32 *= f;
1978 else if (tid == TID_FLOAT)
1979 m_float *= f;
1980 else if (tid == TID_DOUBLE)
1981 m_double *= f;
1982 else
1983 mthrow("Invalid operation for ODB key \"" +
1984 m_parent_odb->get_full_path() + "\"");
1987 }
1988
1989}; // namespace midas
void set_string_size(std::string s, int size)
Definition odbxx.cxx:1614
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:1584
int m_num_values
Definition odbxx.h:469
static bool exists(const std::string &name)
Definition odbxx.cxx:76
std::string get_name()
Definition odbxx.h:1456
void write(int str_size=0)
Definition odbxx.cxx:1113
int m_tid
Definition odbxx.h:463
void set_mode(int mode)
Definition odbxx.cxx:1502
void set_auto_refresh_read(bool f)
Definition odbxx.h:1362
void set_auto_enlarge_array(bool f)
Definition odbxx.h:1383
void delete_key()
Definition odbxx.cxx:1473
void set_odb(odb *o, int i)
Definition odbxx.cxx:1628
u_odb * m_data
Definition odbxx.h:465
void deep_copy(odb &d, const odb &s)
Definition odbxx.cxx:334
bool is_deleted() const
Definition odbxx.h:530
static midas::odb * odb_from_xml(PMXML_NODE node, odb *o)
Definition odbxx.h:1201
bool is_auto_refresh_read() const
Definition odbxx.h:1361
static void unwatch_all()
Definition odbxx.cxx:1575
static HNDLE s_hDB
Definition odbxx.h:452
HNDLE get_hkey()
Definition odbxx.h:1451
static void set_odb_source(odb::odb_source s)
Definition odbxx.h:1416
std::function< void(midas::odb &)> m_watch_callback
Definition odbxx.h:475
bool is_auto_create() const
Definition odbxx.h:1376
bool is_preserve_string_size() const
Definition odbxx.h:1355
static void watch_callback(int hDB, int hKey, int index, void *info)
Definition odbxx.cxx:124
void unwatch()
Definition odbxx.cxx:1563
T get()
Definition odbxx.h:494
int get_tid()
Definition odbxx.h:1454
static midas::odb * odb_from_json(const MJsonNode *node, std::string name, int tid, odb *o)
Definition odbxx.h:1278
static bool get_debug()
Definition odbxx.h:1402
bool is_auto_refresh_write() const
Definition odbxx.h:1367
void set_tid(int tid)
Definition odbxx.h:533
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:1356
static thread_local odb_source s_odb_source
Definition odbxx.h:447
void set_trigger_hotlink(bool f)
Definition odbxx.h:1395
int size()
Definition odbxx.cxx:386
void set_flags(uint32_t f)
Definition odbxx.h:527
void set_auto_refresh_write(bool f)
Definition odbxx.h:1368
int get_mode()
Definition odbxx.cxx:1519
void odb_from_xml_remote(const std::string &str)
Definition odbxx.cxx:160
void set_auto_create(bool f)
Definition odbxx.h:1377
static thread_local std::string s_odb_source_str
Definition odbxx.h:448
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:1533
void set_name(std::string s)
Definition odbxx.h:536
int get_subkeys(std::vector< std::string > &name)
Definition odbxx.cxx:632
void watch(std::function< void(midas::odb &)> f)
Definition odbxx.cxx:1547
static thread_local odb * s_odb
Definition odbxx.h:450
std::string s()
Definition odbxx.h:1459
void save(const std::string &filename)
Definition odbxx.cxx:518
void set_last_index(int i)
Definition odbxx.h:1015
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:454
void fix_order(std::vector< std::string > target_subkey_order)
Definition odbxx.cxx:1314
std::string dump()
Definition odbxx.cxx:427
int m_last_index
Definition odbxx.h:471
void connect_and_fix_structure(std::string path)
Definition odbxx.cxx:1459
static bool s_connected_odb
Definition odbxx.h:456
static void init_hdb()
Definition odbxx.cxx:50
uint32_t get_flags()
Definition odbxx.h:528
bool is_trigger_hotlink() const
Definition odbxx.h:1394
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:1428
std::bitset< 9 > m_flags
Definition odbxx.h:461
void set_deleted(bool f)
Definition odbxx.h:531
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:538
HNDLE m_hKey
Definition odbxx.h:473
void set_write_protect(bool f)
Definition odbxx.h:1389
std::string m_name
Definition odbxx.h:467
bool is_write_protect() const
Definition odbxx.h:1388
void connect(const std::string &path, const std::string &name, bool write_defaults, bool delete_keys_not_in_defaults=false)
Definition odbxx.cxx:1377
midas::odb * m_parent
Definition odbxx.h:477
uint8_t m_uint8
Definition odbxx.h:52
bool m_bool
Definition odbxx.h:60
uint8_t operator=(uint8_t v)
Definition odbxx.cxx:1739
void set_tid(int tid)
Definition odbxx.h:105
void mult(double f, bool push=true)
Definition odbxx.cxx:1964
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:1940
void set_parent(odb *o)
Definition odbxx.h:102
uint16_t m_uint16
Definition odbxx.h:54
odb * get_podb()
Definition odbxx.h:369
void set_string_size(std::string s, int size)
Definition odbxx.cxx:1854
int16_t m_int16
Definition odbxx.h:55
odb & get_odb()
Definition odbxx.h:375
std::string s()
Definition odbxx.h:361
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
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:1300
void recurse_get_defaults_order(std::string path, midas::odb &default_odb, std::map< std::string, std::vector< std::string > > &retval)
Definition odbxx.cxx:1290
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:1253
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