Line data Source code
1 : /// Including QT Headers
2 : #include "dbe/Sorting.hpp"
3 : #include "dbe/Exceptions.hpp"
4 : #include "dbe/dbaccessor.hpp"
5 : #include "dbe/confaccessor.hpp"
6 : #include "dbe/messenger.hpp"
7 :
8 : #include "dbe/change_attribute.hpp"
9 : #include "dbe/change_enum.hpp"
10 : #include "dbe/config_api.hpp"
11 : #include "dbe/config_ui_info.hpp"
12 : #include "dbe/version.hpp"
13 :
14 : #include "conffwk/Configuration.hpp"
15 :
16 : #include <QFileInfo>
17 : #include <QStringList>
18 : #include <QVector>
19 :
20 : #include <unordered_set>
21 : #include <functional>
22 : #include <memory>
23 : #include <vector>
24 : #include <stack>
25 :
26 : using namespace dunedaq::conffwk;
27 :
28 : char const * const dbe_lib_internal_version = dbe_compiled_version;
29 :
30 : //------------------------------------------------------------------------------------------
31 21 : dbe::confaccessor & dbe::confaccessor::ref()
32 : {
33 21 : static confaccessor me;
34 21 : return me;
35 : }
36 :
37 : //------------------------------------------------------------------------------------------
38 :
39 : //------------------------------------------------------------------------------------------
40 3 : dbe::confaccessor::confaccessor()
41 3 : : CallId ( nullptr ),
42 3 : internal_change_stack ( new t_internal_changes_stack
43 3 : { } ),
44 3 : sequenced_command_stack ( new QUndoStack() ),
45 3 : editconfig ( new datahandler() ),
46 3 : coreconfig ( nullptr ),
47 3 : this_change_enabled ( false ),
48 9 : this_total_objects ( 0 )
49 3 : {}
50 :
51 3 : dbe::confaccessor::~confaccessor()
52 : {
53 3 : delete editconfig;
54 3 : delete coreconfig;
55 3 : {
56 3 : dbholder::t_lock l ( dbholder::database_lock );
57 3 : delete dbholder::database;
58 3 : }
59 3 : }
60 :
61 : //------------------------------------------------------------------------------------------
62 :
63 : //------------------------------------------------------------------------------------------
64 0 : bool dbe::confaccessor::enabled()
65 : {
66 0 : t_lock l ( ref().this_change_enabled_mutex );
67 0 : return ref().this_change_enabled;
68 0 : }
69 :
70 9 : void dbe::confaccessor::setenabled()
71 : {
72 9 : t_lock l ( this_change_enabled_mutex );
73 9 : this_change_enabled = true;
74 9 : }
75 :
76 0 : void dbe::confaccessor::setdisabled()
77 : {
78 0 : t_lock l ( this_change_enabled_mutex );
79 0 : this_change_enabled = false;
80 0 : }
81 :
82 : //------------------------------------------------------------------------------------------
83 :
84 : //------------------------------------------------------------------------------------------
85 0 : void dbe::confaccessor::force_emit_object_created ( QString const & src, dref const obj )
86 : {
87 0 : t_lock l ( force_mut );
88 0 : emit object_created ( src, obj );
89 0 : }
90 :
91 0 : void dbe::confaccessor::force_emit_object_renamed ( QString const & src, dref const obj )
92 : {
93 0 : t_lock l ( force_mut );
94 0 : emit object_renamed ( src, obj );
95 0 : }
96 :
97 0 : void dbe::confaccessor::force_emit_object_deleted ( QString const & src, dref const obj )
98 : {
99 0 : t_lock l ( force_mut );
100 0 : emit object_deleted ( src, obj );
101 0 : }
102 :
103 0 : void dbe::confaccessor::force_emit_object_changed ( QString const & src, dref const obj )
104 : {
105 0 : t_lock l ( force_mut );
106 0 : emit object_changed ( src, obj );
107 0 : }
108 :
109 : //------------------------------------------------------------------------------------------
110 :
111 : //------------------------------------------------------------------------------------------
112 0 : void dbe::confaccessor::GetFileCache ( QList<QStringList> & FileCache )
113 : {
114 0 : IncludedFileCache = FileCache;
115 0 : }
116 :
117 : //------------------------------------------------------------------------------------------
118 :
119 : //------------------------------------------------------------------------------------------
120 0 : QString dbe::confaccessor::dbfullname()
121 : {
122 0 : return ref().this_dblocation;
123 : }
124 :
125 0 : QString dbe::confaccessor::db_implementation_name()
126 : {
127 0 : return ref().this_resource_location;
128 : }
129 :
130 : //------------------------------------------------------------------------------------------
131 :
132 : //------------------------------------------------------------------------------------------
133 0 : cptr<dbe::datahandler> dbe::confaccessor::gethandler()
134 : {
135 0 : static cptr<datahandler> r ( ref().editconfig );
136 0 : return r;
137 : }
138 :
139 0 : cptr<dbe::ui::config::info> dbe::confaccessor::guiconfig()
140 : {
141 0 : static cptr<dbe::ui::config::info> r ( confaccessor::ref().coreconfig );
142 0 : return r;
143 : }
144 :
145 0 : dbe::confaccessor::t_undo_stack_cptr dbe::confaccessor::get_commands()
146 : {
147 0 : static t_undo_stack_cptr rp ( ref().sequenced_command_stack );
148 0 : return rp;
149 : }
150 :
151 : //------------------------------------------------------------------------------------------
152 :
153 : //------------------------------------------------------------------------------------------
154 0 : int dbe::confaccessor::get_total_objects()
155 : {
156 0 : return ref().this_total_objects;
157 : }
158 :
159 0 : void dbe::confaccessor::increase_total_objects ( int const i )
160 : {
161 0 : ref().this_total_objects += i;
162 0 : }
163 :
164 0 : void dbe::confaccessor::set_total_objects ( int const i )
165 : {
166 0 : ref().this_total_objects = i;
167 0 : }
168 :
169 : //------------------------------------------------------------------------------------------
170 :
171 : //------------------------------------------------------------------------------------------
172 :
173 : template<>
174 9 : void dbe::confaccessor::set_dbinfo<dbe::dbinfo::oks> ( QString const & location )
175 : {
176 9 : static QString const implementation ( "oksconflibs" );
177 :
178 9 : this_dblocation = location;
179 9 : this_resource_location = implementation + ":" + location;
180 :
181 9 : setenabled();
182 9 : }
183 :
184 : template<>
185 0 : void dbe::confaccessor::set_dbinfo<dbe::dbinfo::roks> ( QString const & location )
186 : {
187 0 : this_dblocation = location;
188 0 : static QString const implementation ( "roksconflibs" );
189 0 : this_resource_location = implementation + ":" + location;
190 0 : t_lock l ( this_change_enabled_mutex );
191 0 : this_change_enabled = true;
192 0 : }
193 :
194 : template<>
195 0 : void dbe::confaccessor::set_dbinfo<dbe::dbinfo::rdb> ( QString const & location )
196 : {
197 0 : static QString const implementation ( "rdbconfig" );
198 0 : this_resource_location = implementation + ":" + location;
199 0 : this_dblocation = this_resource_location;
200 0 : t_lock l ( this_change_enabled_mutex );
201 0 : this_change_enabled = true;
202 0 : }
203 :
204 9 : void dbe::confaccessor::setdbinfo ( QString const & location, dbinfo const itype )
205 : {
206 9 : switch ( itype )
207 : {
208 :
209 9 : case dbinfo::oks:
210 9 : ref().set_dbinfo<dbinfo::oks> ( location );
211 9 : break;
212 :
213 0 : case dbinfo::roks:
214 0 : ref().set_dbinfo<dbinfo::roks> ( location );
215 0 : break;
216 :
217 0 : case dbinfo::rdb:
218 0 : ref().set_dbinfo<dbinfo::rdb> ( location );
219 0 : break;
220 :
221 0 : default:
222 0 : ref().setenabled();
223 0 : break;
224 : }
225 9 : }
226 :
227 0 : void dbe::confaccessor::setdblocation ( QString const & Implementation )
228 : {
229 0 : ref().this_resource_location = Implementation;
230 0 : }
231 :
232 7 : bool dbe::confaccessor::is_database_loaded()
233 : {
234 7 : return dbaccessor::dbptr().get() != nullptr;
235 : }
236 :
237 : //------------------------------------------------------------------------------------------
238 :
239 : //------------------------------------------------------------------------------------------
240 0 : bool dbe::confaccessor::check_file_rw ( QString const & fn )
241 : {
242 0 : try
243 : {
244 0 : if ( not fn.endsWith ( ".schema.xml" ) )
245 : {
246 0 : return dbaccessor::dbptr()->is_writable ( fn.toStdString() );
247 : }
248 : }
249 0 : catch ( dunedaq::conffwk::Generic const & ex )
250 : {
251 0 : ERROR ( "Not possible to operate on file", dbe::config::errors::parse ( ex ),
252 0 : "\n\nCheck filename:", fn.toStdString() );
253 0 : }
254 :
255 : return false;
256 : }
257 :
258 : //------------------------------------------------------------------------------------------
259 0 : void dbe::confaccessor::clear_commands()
260 : {
261 0 : if ( ref().get_commands().get() )
262 : {
263 0 : ref().get_commands()->clear();
264 0 : t_internal_changes_stack cleared{ };
265 0 : ref().get_internal_change_stack()->swap ( cleared );
266 0 : }
267 0 : }
268 :
269 : //------------------------------------------------------------------------------------------
270 :
271 : //------------------------------------------------------------------------------------------
272 0 : void dbe::confaccessor::abort()
273 : {
274 0 : dbaccessor::dbptr()->abort();
275 0 : }
276 :
277 :
278 0 : std::list<std::string> dbe::confaccessor::uncommitted_files() {
279 0 : std::list<std::string> dbs;
280 0 : dbaccessor::dbptr()->get_updated_dbs(dbs);
281 0 : return dbs;
282 0 : }
283 : //------------------------------------------------------------------------------------------
284 :
285 : //------------------------------------------------------------------------------------------
286 9 : bool dbe::confaccessor::load(bool subscribeToChanges)
287 : {
288 9 : try
289 : {
290 9 : dbholder::t_lock l ( dbholder::database_lock );
291 :
292 9 : if ( dbholder::database == nullptr )
293 : {
294 3 : dbholder::database = new Configuration ( ref().this_resource_location.toStdString() );
295 :
296 3 : if ( subscribeToChanges == true ) {
297 3 : ref().CallId = dbholder::database->subscribe (
298 6 : ConfigurationSubscriptionCriteria(),
299 : &confaccessor::CallbackFunction,
300 : reinterpret_cast<void *> ( dbholder::database ) );
301 : }
302 : }
303 : else
304 : {
305 6 : dbe::inner::dbcontroller::flush();
306 6 : delete dbholder::database;
307 6 : dbholder::database = new Configuration ( ref().this_resource_location.toStdString() );
308 : }
309 :
310 9 : dbholder::database->prefetch_all_data();
311 :
312 9 : dbholder::database_concurrent_ptr = cptr<Configuration> ( dbholder::database );
313 9 : return true;
314 9 : }
315 0 : catch ( dunedaq::conffwk::Exception const & e )
316 : {
317 0 : FAIL ( "Database loading failed", dbe::config::errors::parse ( e ).c_str() );
318 0 : return false;
319 0 : }
320 :
321 : }
322 :
323 0 : std::list<std::string> dbe::confaccessor::save ( const QString & CommitMessage )
324 : {
325 0 : try
326 : {
327 0 : std::list<std::string> tobecommited{};
328 :
329 0 : if ( ref().is_database_loaded() )
330 : {
331 0 : dbaccessor::dbptr()->get_updated_dbs ( tobecommited );
332 0 : dbaccessor::dbptr()->commit ( CommitMessage.toStdString() );
333 0 : confaccessor::ref().db_committed(tobecommited, CommitMessage.toStdString());
334 : }
335 :
336 0 : return tobecommited;
337 0 : }
338 0 : catch ( dunedaq::conffwk::Exception const & e )
339 : {
340 0 : throw daq::dbe::CouldNotCommitChanges ( ERS_HERE, dbe::config::errors::parse ( e ) );
341 0 : }
342 : }
343 :
344 : //------------------------------------------------------------------------------------------
345 :
346 : //------------------------------------------------------------------------------------------
347 0 : void dbe::confaccessor::init()
348 : {
349 0 : QString DUNEDAQ_DB_PATH = getenv ( "DUNEDAQ_DB_PATH" );
350 0 : QString GUI_DATA = getenv ( "OKS_GUI_INIT_DATA" );
351 :
352 0 : QStringList CONFIG_DATABASE = GUI_DATA.split ( ":", Qt::SkipEmptyParts );
353 0 : QStringList DUNEDAQ_DB_PATH_SPLIT = DUNEDAQ_DB_PATH.split ( ":", Qt::SkipEmptyParts );
354 :
355 : // We need to read the current configuration ( to retrieve parameters affecting dbe )
356 :
357 0 : std::vector<std::string> full_path_names;
358 :
359 0 : for ( QString & FileName : CONFIG_DATABASE )
360 : {
361 :
362 0 : for ( QString & PATH : DUNEDAQ_DB_PATH_SPLIT )
363 : {
364 0 : QFileInfo CheckFile ( PATH + "/" + FileName );
365 :
366 0 : if ( CheckFile.exists() and CheckFile.isFile() )
367 : {
368 0 : QString fullpathname = PATH + "/" + FileName;
369 0 : full_path_names.push_back ( fullpathname.toStdString() );
370 0 : }
371 0 : }
372 : }
373 :
374 0 : confaccessor::ref().coreconfig = new ui::config::info ( full_path_names );
375 :
376 0 : }
377 :
378 0 : QList<QStringList> dbe::confaccessor::GetIncludedFileCache() const
379 : {
380 0 : return IncludedFileCache;
381 : }
382 :
383 : //------------------------------------------------------------------------------------------
384 :
385 : //------------------------------------------------------------------------------------------
386 0 : void dbe::confaccessor::addfile ( std::string const & db, std::string const & fn )
387 : {
388 0 : if ( not enabled() )
389 : {
390 0 : throw daq::dbe::ChangeNotAllowed ( ERS_HERE );
391 : }
392 :
393 0 : dbaccessor::dbptr()->add_include ( db, fn );
394 0 : emit IncludeFileDone();
395 0 : }
396 :
397 0 : void dbe::confaccessor::removefile ( std::string const & db, std::string const & fn )
398 : {
399 0 : if ( not enabled() )
400 : {
401 0 : throw daq::dbe::ChangeNotAllowed ( ERS_HERE );
402 : }
403 :
404 0 : dbaccessor::dbptr()->remove_include ( db, fn );
405 0 : emit RemoveFileDone();
406 0 : }
407 :
408 : //------------------------------------------------------------------------------------------
409 :
410 : //------------------------------------------------------------------------------------------
411 0 : void dbe::confaccessor::CallbackFunction ( std::vector<ConfigurationChange *> const &
412 : changes,
413 : void * parameter )
414 : {
415 0 : dbe::confaccessor::ref().docallback ( changes, parameter );
416 0 : }
417 :
418 0 : void dbe::confaccessor::docallback ( std::vector<ConfigurationChange *> const & changes,
419 : void * parameter )
420 : {
421 0 : Q_UNUSED ( parameter );
422 :
423 0 : t_lock l ( mut_changes );
424 0 : external_change_stack.clear();
425 :
426 0 : for ( ConfigurationChange * Change : changes )
427 : {
428 0 : const auto& cl = Change->get_class_name();
429 0 : const auto& mod = Change->get_modified_objs();
430 0 : const auto& cre = Change->get_created_objs();
431 0 : const auto& rem = Change->get_removed_objs();
432 :
433 0 : external_change_stack.push_back ( { cl, mod, cre, rem } );
434 : }
435 :
436 0 : emit ExternalChangesAccepted();
437 0 : }
438 :
439 : //------------------------------------------------------------------------------------------
440 :
441 : //------------------------------------------------------------------------------------------
442 0 : void dbe::confaccessor::unsubscribe()
443 : {
444 0 : if ( dbaccessor::dbptr().get() && ref().CallId != nullptr )
445 : {
446 0 : dbaccessor::dbptr()->unsubscribe ( ref().CallId );
447 : }
448 0 : }
449 :
450 : dbe::confaccessor::t_internal_changes_stack_cptr
451 0 : dbe::confaccessor::get_internal_change_stack()
452 : {
453 0 : static t_internal_changes_stack_cptr rp ( ref().internal_change_stack.get() );
454 0 : return rp;
455 : }
456 :
457 : //------------------------------------------------------------------------------------------
458 :
|