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