Line data Source code
1 : /********************************************************************\
2 :
3 : Name: odbxx_test.cxx
4 : Created by: Stefan Ritt
5 :
6 : Contents: Test and Demo of Object oriented interface to ODB
7 :
8 : \********************************************************************/
9 :
10 : #include <string>
11 : #include <iostream>
12 : #include <array>
13 :
14 : #include "midas.h"
15 : #include "odbxx.h"
16 :
17 : /*------------------------------------------------------------------*/
18 :
19 0 : int main() {
20 :
21 0 : cm_connect_experiment(nullptr, nullptr, "test", nullptr);
22 0 : midas::odb::set_debug(true);
23 :
24 : // delete /Test/Settings to start from scratch
25 0 : midas::odb::delete_key("/Test/Settings");
26 :
27 : // create ODB structure...
28 : midas::odb o = {
29 0 : {"Int32 Key", 42},
30 : {"Bool Key", true},
31 0 : {"Subdir", {
32 0 : {"Int32 key", 123 },
33 0 : {"Double Key", 1.2},
34 0 : {"Subsub", {
35 0 : {"Float key", 1.2f}, // floats must be explicitly specified
36 : {"String Key", "Hello"},
37 : }}
38 : }},
39 0 : {"Int Array", {1, 2, 3}},
40 0 : {"Double Array", {1.2, 2.3, 3.4}},
41 0 : {"String Array", {"Hello1", "Hello2", "Hello3"}},
42 0 : {"Large Array", std::array<int, 10>{} }, // array with explicit size
43 0 : {"Large String", std::string(63, '\0') }, // string with explicit size
44 0 : {"String Array 10", std::array<std::string, 10>{}}, // string array with explicit size
45 : // string array with 10 strings of each 63 chars
46 0 : {"Large String Array 10", std::array<std::string, 10>{std::string(63, '\0')}}
47 0 : };
48 :
49 : // ...and push it to ODB. If keys are present in the
50 : // ODB, their value is kept. If not, the default values
51 : // from above are copied to the ODB
52 0 : o.connect("/Test/Settings");
53 :
54 : // alternatively, a structure can be created from an existing ODB subtree
55 0 : midas::odb o2("/Test/Settings");
56 0 : std::cout << o2 << std::endl;
57 :
58 : // set, retrieve, and change ODB value
59 0 : o["Int32 Key"] = 42;
60 0 : int i = o["Int32 Key"];
61 0 : o["Int32 Key"] = i+1;
62 0 : o["Int32 Key"]++;
63 0 : o["Int32 Key"] *= 1.3;
64 0 : std::cout << "Should be 57: " << o["Int32 Key"] << std::endl;
65 :
66 : // test with 64-bit variables
67 0 : o["Int64 Key"] = -1LL;
68 0 : int64_t i64 = o["Int64 Key"];
69 0 : std::cout << std::hex << "0x" << i64 << std::dec << std::endl;
70 :
71 0 : o["UInt64 Key"] = 0x1234567812345678u;
72 0 : uint64_t ui64 = o["UInt64 Key"];
73 0 : std::cout << std::hex << "0x" << ui64 << std::dec << std::endl;
74 :
75 : // test with bool
76 0 : o["Bool Key"] = false;
77 0 : o["Bool Key"] = !o["Bool Key"];
78 :
79 : // test with std::string
80 0 : o["Subdir"]["Subsub"]["String Key"] = "Hello";
81 0 : std::string s = o["Subdir"]["Subsub"]["String Key"];
82 0 : s += " world!";
83 0 : o["Subdir"]["Subsub"]["String Key"] = s;
84 0 : s = s + o["Subdir"]["Subsub"]["String Key"].s(); // need .s() for concatenations
85 0 : std::cout << s << std::endl;
86 :
87 : // use std::string as index
88 0 : std::string substr("Int32 Key");
89 0 : o[substr] = 43;
90 :
91 : // test with a vector
92 0 : std::vector<int> v = o["Int Array"]; // read vector
93 0 : std::fill(v.begin(), v.end(), 10);
94 0 : o["Int Array"] = v; // assign vector to ODB array
95 0 : o["Int Array"][1] = 2; // modify array element
96 0 : i = o["Int Array"][1]; // read from array element
97 0 : std::cout << i <<std::endl;
98 0 : o["Int Array"].resize(5); // resize array
99 0 : o["Int Array"]++; // increment all values of array
100 0 : std::cout << "Arrays size is " << o["Int Array"].size() << std::endl;
101 :
102 : // auto-enlarge arrays
103 0 : o["Int Array"][10] = 10;
104 :
105 : // test with a string vector
106 0 : std::vector<std::string> sv;
107 0 : sv = o["String Array"];
108 0 : sv[1] = "New String";
109 0 : o["String Array"] = sv;
110 0 : o["String Array"][2] = "Another String";
111 0 : o["String Array"][3] = std::string("One more");
112 0 : s = o["String Array"][1].s(); // need .s() to explicitly convert to std::string
113 0 : std::cout << s << std::endl;
114 :
115 : // test with strings with given size
116 0 : o["String Array 2"][0].set_string_size("Hello", 64);
117 0 : o["String Array 2"][1] = "Second string";
118 0 : o["String Array 2"][2] = "Third string";
119 :
120 : // test with bool arrays/vectors
121 0 : o["Bool Array"] = std::array<bool, 3>{true, false, true};
122 0 : o["Bool Array from Vector"] = std::vector<bool>{true, false, true};
123 :
124 : // iterate over array
125 0 : int sum = 0;
126 0 : for (int e : o["Int Array"])
127 0 : sum += e;
128 0 : std::cout << "Sum should be 37: " << sum << std::endl;
129 :
130 : // create key from other key
131 0 : midas::odb oi(o["Int32 Key"]);
132 0 : oi = 123;
133 :
134 : // test auto refresh read
135 0 : std::cout << oi << std::endl; // each read access reads value from ODB
136 0 : oi.set_auto_refresh_read(false); // turn off auto refresh
137 0 : std::cout << oi << std::endl; // this does not read value from ODB
138 0 : oi.read(); // this forces a manual read
139 0 : std::cout << oi << std::endl;
140 :
141 : // test auto refresh write
142 0 : oi.set_auto_refresh_write(false); // turn off auto refresh write
143 0 : oi = 321; // this does not write a value to the ODB
144 0 : oi.write(); // this forces a manual write
145 :
146 : // create ODB entries on-the-fly
147 0 : midas::odb ot;
148 0 : ot.connect("/Test/Settings/OTF");// this forces /Test/OTF to be created if not already there
149 0 : ot["Int32 Key"] = 1; // create all these keys with different types
150 0 : ot["Double Key"] = 1.23;
151 0 : ot["String Key"] = "Hello";
152 0 : ot["Int Array"] = std::array<int, 10>{};
153 0 : ot["Subdir"]["Int32 Key"] = 42;
154 0 : ot["String Array"] = std::vector<std::string>{"S1", "S2", "S3"};
155 0 : ot["Other String Array"][0] = "OSA0";
156 0 : ot["Other String Array"][1] = "OSA1";
157 :
158 : // create key with default value
159 0 : i = ot["Int32 Key"](123); // key exists already (created above) -> use key value i=1
160 0 : std::cout << i << std::endl;
161 0 : i = ot["New Int32 Key"](123); // key does not exist -> set it to default value 123 i=123
162 0 : std::cout << i << std::endl;
163 :
164 : // std::string s1 = ot["New String Key"]("Hi"); // same for strings
165 0 : std::cout << ot << std::endl;
166 :
167 0 : o.read(); // re-read the underlying ODB tree which got changed by above OTF code
168 0 : std::cout << o.print() << std::endl;
169 :
170 : // iterate over sub-keys
171 0 : midas::odb::set_debug(false);
172 0 : for (midas::odb& oit : o)
173 0 : std::cout << oit.get_name() << ": " << oit << std::endl;
174 :
175 : // print whole sub-tree
176 0 : std::cout << o.print() << std::endl;
177 :
178 : // print whole subtree
179 0 : std::cout << o.dump() << std::endl;
180 :
181 : // update structure - create keys if needed, keep existing values if key already exists,
182 : // delete keys that are in ODB but not the list of defaults.
183 : midas::odb o3 = {
184 0 : {"Int32 Key", 456},
185 : {"New Bool Key", true},
186 0 : {"String Array", {"Hello1", "Hello2", "Hello3"}},
187 : {"Bool Key", true},
188 0 : {"Subdir", {
189 0 : {"Int32 key", 135 },
190 : {"New Sub Bool Key", false},
191 0 : {"Double Key", 1.5}
192 : }}
193 0 : };
194 0 : o3.connect_and_fix_structure("/Test/Settings");
195 :
196 : // Print new structure
197 0 : std::cout << "After changing structure with o3:" << std::endl;
198 0 : std::cout << o3.print() << std::endl;
199 :
200 : // delete test key from ODB
201 0 : o.delete_key();
202 :
203 : // don't clutter watch callbacks
204 0 : midas::odb::set_debug(false);
205 :
206 : // watch ODB key for any change with lambda function
207 0 : midas::odb ow("/Experiment");
208 0 : ow.watch([](midas::odb &o) {
209 0 : std::cout << "Value of key \"" + o.get_full_path() + "\" changed to " << o << std::endl;
210 0 : });
211 :
212 : do {
213 0 : int status = cm_yield(100);
214 0 : if (status == SS_ABORT || status == RPC_SHUTDOWN)
215 : break;
216 0 : } while (!ss_kbhit());
217 :
218 0 : cm_disconnect_experiment();
219 0 : return 1;
220 0 : }
|