DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
file.cpp
Go to the documentation of this file.
1// DUNE DAQ modification notice:
2// This file has been modified from the original ATLAS oks source for the DUNE DAQ project.
3// Fork baseline commit: oks-08-03-04 (2022-04-14).
4// Renamed since fork: no.
5
6#define _OksBuildDll_
7
8#include "oks/file.hpp"
9#include "oks/kernel.hpp"
10#include "oks/xml.hpp"
11#include "oks/cstring.hpp"
12
13#include "oks_utils.hpp"
14
15#include <errno.h>
16#include <stdlib.h>
17#include <unistd.h>
18#include <string.h>
19#include <sys/stat.h>
20
21#include <fstream>
22#include <sstream>
23#include <stdexcept>
24
25#include <boost/date_time/posix_time/posix_time_types.hpp>
26#include <boost/date_time/posix_time/time_formatters.hpp>
27#include <boost/date_time/posix_time/time_parsers.hpp>
28#include <boost/interprocess/sync/file_lock.hpp>
29
30#include "ers/ers.hpp"
31#include "logging/Logging.hpp"
32
33namespace dunedaq {
34namespace oks {
35 // Nasty hack to allow code generation on the fly without locking
36 // file. Off by default
37 bool OksFile::p_nolock_mode = false;
38 //
39 // Define XML formats used to store OKS schema and data files
40 //
41
42const char OksFile::xml_info_tag[] = "info";
43const char OksFile::xml_include_tag[] = "include";
44const char OksFile::xml_file_tag[] = "file";
45const char OksFile::xml_comments_tag[] = "comments";
46const char OksFile::xml_comment_tag[] = "comment";
47
48const char OksFile::xml_file_header[] = "<?xml version=\"1.0\" encoding=\"ASCII\"?>";
49
51 "<!DOCTYPE oks-schema [\n"
52
53 " <!ELEMENT oks-schema (info, (include)?, (comments)?, (class)+)>\n"
54
55 " <!ELEMENT info EMPTY>\n"
56 " <!ATTLIST info\n"
57 " name CDATA #IMPLIED\n"
58 " type CDATA #IMPLIED\n"
59 " num-of-items CDATA #REQUIRED\n"
60 " oks-format CDATA #FIXED \"schema\"\n"
61 " oks-version CDATA #REQUIRED\n"
62 " created-by CDATA #IMPLIED\n"
63 " created-on CDATA #IMPLIED\n"
64 " creation-time CDATA #IMPLIED\n"
65 " last-modified-by CDATA #IMPLIED\n"
66 " last-modified-on CDATA #IMPLIED\n"
67 " last-modification-time CDATA #IMPLIED\n"
68 " >\n"
69
70 " <!ELEMENT include (file)+>\n"
71 " <!ELEMENT file EMPTY>\n"
72 " <!ATTLIST file\n"
73 " path CDATA #REQUIRED\n"
74 " >\n"
75
76 " <!ELEMENT comments (comment)+>\n"
77 " <!ELEMENT comment EMPTY>\n"
78 " <!ATTLIST comment\n"
79 " creation-time CDATA #REQUIRED\n"
80 " created-by CDATA #REQUIRED\n"
81 " created-on CDATA #REQUIRED\n"
82 " author CDATA #REQUIRED\n"
83 " text CDATA #REQUIRED\n"
84 " >\n"
85
86 " <!ELEMENT class (superclass | attribute | relationship | method)*>\n"
87 " <!ATTLIST class\n"
88 " name CDATA #REQUIRED\n"
89 " description CDATA \"\"\n"
90 " is-abstract (yes|no) \"no\"\n"
91 " >\n"
92
93 " <!ELEMENT superclass EMPTY>\n"
94 " <!ATTLIST superclass name CDATA #REQUIRED>\n"
95
96 " <!ELEMENT attribute EMPTY>\n"
97 " <!ATTLIST attribute\n"
98 " name CDATA #REQUIRED\n"
99 " description CDATA \"\"\n"
100 " type (bool|s8|u8|s16|u16|s32|u32|s64|u64|float|double|date|time|string|uid|enum|class) #REQUIRED\n"
101 " range CDATA \"\"\n"
102 " format (dec|hex|oct) \"dec\"\n"
103 " is-multi-value (yes|no) \"no\"\n"
104 " init-value CDATA \"\"\n"
105 " is-not-null (yes|no) \"no\"\n"
106 " ordered (yes|no) \"no\"\n"
107 " >\n"
108
109 " <!ELEMENT relationship EMPTY>\n"
110 " <!ATTLIST relationship\n"
111 " name CDATA #REQUIRED\n"
112 " description CDATA \"\"\n"
113 " class-type CDATA #REQUIRED\n"
114 " low-cc (zero|one) #REQUIRED\n"
115 " high-cc (one|many) #REQUIRED\n"
116 " is-composite (yes|no) #REQUIRED\n"
117 " is-exclusive (yes|no) #REQUIRED\n"
118 " is-dependent (yes|no) #REQUIRED\n"
119 " ordered (yes|no) \"no\"\n"
120 " >\n"
121
122 " <!ELEMENT method (method-implementation*)>\n"
123 " <!ATTLIST method\n"
124 " name CDATA #REQUIRED\n"
125 " description CDATA \"\"\n"
126 " >\n"
127
128 " <!ELEMENT method-implementation EMPTY>\n"
129 " <!ATTLIST method-implementation\n"
130 " language CDATA #REQUIRED\n"
131 " prototype CDATA #REQUIRED\n"
132 " body CDATA \"\"\n"
133 " >\n"
134
135 "]>";
136
137const char OksFile::xml_data_file_dtd[] =
138 "<!DOCTYPE oks-data [\n"
139
140 " <!ELEMENT oks-data (info, (include)?, (comments)?, (obj)+)>\n"
141
142 " <!ELEMENT info EMPTY>\n"
143 " <!ATTLIST info\n"
144 " name CDATA #IMPLIED\n"
145 " type CDATA #IMPLIED\n"
146 " num-of-items CDATA #REQUIRED\n"
147 " oks-format CDATA #FIXED \"data\"\n"
148 " oks-version CDATA #REQUIRED\n"
149 " created-by CDATA #IMPLIED\n"
150 " created-on CDATA #IMPLIED\n"
151 " creation-time CDATA #IMPLIED\n"
152 " last-modified-by CDATA #IMPLIED\n"
153 " last-modified-on CDATA #IMPLIED\n"
154 " last-modification-time CDATA #IMPLIED\n"
155 " >\n"
156
157 " <!ELEMENT include (file)*>\n"
158 " <!ELEMENT file EMPTY>\n"
159 " <!ATTLIST file\n"
160 " path CDATA #REQUIRED\n"
161 " >\n"
162
163 " <!ELEMENT comments (comment)*>\n"
164 " <!ELEMENT comment EMPTY>\n"
165 " <!ATTLIST comment\n"
166 " creation-time CDATA #REQUIRED\n"
167 " created-by CDATA #REQUIRED\n"
168 " created-on CDATA #REQUIRED\n"
169 " author CDATA #REQUIRED\n"
170 " text CDATA #REQUIRED\n"
171 " >\n"
172
173 " <!ELEMENT obj (attr | rel)*>\n"
174 " <!ATTLIST obj\n"
175 " class CDATA #REQUIRED\n"
176 " id CDATA #REQUIRED\n"
177 " >\n"
178 " <!ELEMENT attr (data)*>\n"
179 " <!ATTLIST attr\n"
180 " name CDATA #REQUIRED\n"
181 " type (bool|s8|u8|s16|u16|s32|u32|s64|u64|float|double|date|time|string|uid|enum|class|-) \"-\"\n"
182 " val CDATA \"\"\n"
183 " >\n"
184 " <!ELEMENT data EMPTY>\n"
185 " <!ATTLIST data\n"
186 " val CDATA #REQUIRED\n"
187 " >\n"
188 " <!ELEMENT rel (ref)*>\n"
189 " <!ATTLIST rel\n"
190 " name CDATA #REQUIRED\n"
191 " class CDATA \"\"\n"
192 " id CDATA \"\"\n"
193 " >\n"
194 " <!ELEMENT ref EMPTY>\n"
195 " <!ATTLIST ref\n"
196 " class CDATA #REQUIRED\n"
197 " id CDATA #REQUIRED\n"
198 " >\n"
199 "]>";
200
201
202 std::string
203 FailedAddInclude::fill(const OksFile& file, const std::string& include_name, const std::string& reason) noexcept
204 {
205 return ( std::string("Failed to add include \'") + include_name + "\' to file \'" + file.get_full_file_name() + "\' because:\n" + reason);
206 }
207
208 std::string
209 FailedRemoveInclude::fill(const OksFile& file, const std::string& include_name, const std::string& reason) noexcept
210 {
211 return ( std::string("Failed to remove include \'") + include_name + "\' from file \'" + file.get_full_file_name() + "\' because:\n" + reason);
212 }
213
214 std::string
215 FailedRenameInclude::fill(const OksFile& file, const std::string& from, const std::string& to, const std::string& reason) noexcept
216 {
217 return ( std::string("Failed to rename include of \'") + file.get_full_file_name() + "\' from \'" + from + "\' to \'" + to + "\' because:\n" + reason);
218 }
219
220 std::string
221 FailedAddComment::fill(const OksFile& file, const std::string& reason) noexcept
222 {
223 return ( std::string("Failed to add new comment to file \'") + file.get_full_file_name() + "\' because:\n" + reason);
224 }
225
226 std::string
227 FailedRemoveComment::fill(const OksFile& file, const std::string& creation_time, const std::string& reason) noexcept
228 {
229 return ( std::string("Failed to remove comment created at \'") + creation_time + "\' from file \'" + file.get_full_file_name() + "\' because:\n" + reason);
230 }
231
232 std::string
233 FailedChangeComment::fill(const OksFile& file, const std::string& creation_time, const std::string& reason) noexcept
234 {
235 return ( std::string("Failed to change comment created at \'") + creation_time + "\' from file \'" + file.get_full_file_name() + "\' because:\n" + reason);
236 }
237
238 std::string
239 FileLockError::fill(const OksFile& file, bool lock_action, const std::string& reason) noexcept
240 {
241 return ( std::string("Failed to ") + (lock_action ? "" : "un") + "lock file \'" + file.get_full_file_name() + "\' because:\n" + reason);
242 }
243
244 std::string
245 FileChangeError::fill(const OksFile& file, const std::string& action, const std::string& reason) noexcept
246 {
247 return ( std::string("Failed to ") + action + " of file \'" + file.get_full_file_name() + "\' because:\n" + reason);
248 }
249
250 std::string
251 FileCompareError::fill(const std::string& src, const std::string& dest, const std::string& reason) noexcept
252 {
253 return ( std::string("Failed to compare file \'") + src + "\' with \'" + dest + "\' because:\n" + reason);
254 }
255
256
257OksFile::OksFile(const std::string& s, const std::string& ln, const std::string& ft, const std::string& ff, OksKernel * k) :
258 p_short_name (s),
259 p_full_name (s),
260 p_logical_name (ln),
261 p_type (ft),
262 p_oks_format (ff),
264 p_size (0),
265 p_created_by (OksKernel::get_user_name()),
266 p_creation_time (boost::posix_time::second_clock::universal_time()),
267 p_created_on (OksKernel::get_host_name()),
269 p_lock (),
270 p_is_updated (false),
271 p_is_read_only (true),
272 p_last_modified (0),
274 p_is_on_disk (false),
275 p_included_by (0),
276 p_kernel (k)
277{
282}
283
284void
286{
287 for(std::map<std::string, oks::Comment *>::iterator i = p_comments.begin(); i != p_comments.end(); ++i) {
288 delete i->second;
289 }
290
291 p_comments.clear();
292}
293
294
296{
298}
299
300OksFile&
302{
303 if (&f != this)
304 {
307
308 p_short_name = f.p_short_name;
309 p_full_name = f.p_full_name;
310// p_repository = f.p_repository;
311 p_repository_name = f.p_repository_name;
312 p_logical_name = f.p_logical_name;
313 p_type = f.p_type;
314 p_oks_format = f.p_oks_format;
315 p_number_of_items = f.p_number_of_items;
316 p_size = f.p_size;
317 p_created_by = f.p_created_by;
318 p_creation_time = f.p_creation_time;
319 p_created_on = f.p_created_on;
320 p_last_modified_by = f.p_last_modified_by;
321 p_last_modification_time = f.p_last_modification_time;
322 p_last_modified_on = f.p_last_modified_on;
323 p_open_mode = f.p_open_mode;
324 p_is_updated = f.p_is_updated;
325 p_lock = f.p_lock;
326 p_is_read_only = f.p_is_read_only;
327 p_lock_file_name = f.p_lock_file_name;
328 p_list_of_include_files = f.p_list_of_include_files;
329 p_last_modified = f.p_last_modified;
330 p_repository_last_modified = f.p_repository_last_modified;
331 p_is_on_disk = f.p_is_on_disk;
332 p_included_by = f.p_included_by;
333 p_kernel = f.p_kernel;
334
335 for (const auto& i : f.p_comments)
336 {
337 p_comments[i.first] = new oks::Comment(*i.second);
338 }
339 }
340
341 return *this;
342}
343
344
345 // read xml-file header from file
346
347const char _empty_str[] = "empty";
348
349OksFile::OksFile(std::shared_ptr<OksXmlInputStream> xmls, const std::string& sp, const std::string& fp, OksKernel * k) :
350 p_short_name (sp),
351 p_full_name (fp),
353 p_creation_time (boost::posix_time::not_a_date_time),
354 p_last_modification_time (boost::posix_time::not_a_date_time),
355 p_lock (),
356 p_is_updated (false),
357 p_is_read_only (true),
358 p_last_modified (0),
360 p_is_on_disk (true),
361 p_included_by (0),
362 p_kernel (k)
363{
364 const char * fname = "OksFile::OksFile()";
365
366// create_lock_name();
368
369
370 // check file header
371
372 try {
373
374 // skip an xml file header
375
376 {
377 const char * tag_start = xmls->get_tag_start();
378
379 if(!oks::cmp_str4(tag_start, "?xml")) {
380 xmls->throw_unexpected_tag(tag_start, "?xml");
381 }
382 }
383
384 // skip possible tag attributes
385
386 while(true) {
387 OksXmlAttribute attr(*xmls);
388
389 // check for close of tag
390
391 if(
392 oks::cmp_str1(attr.name(), ">") ||
393 oks::cmp_str1(attr.name(), "/") ||
394 oks::cmp_str1(attr.name(), "?")
395 ) { break; }
396
397 // check for start of info tag
398
399 if(!oks::cmp_str7(attr.name(), "version") && !oks::cmp_str8(attr.name(), "encoding")) {
400 if(!p_kernel->get_silence_mode()) {
401 Oks::warning_msg(fname) << " Unexpected attribute \'" << attr.name() << "\' in the xml file header. Either \'version\' or \'encoding\' is expected.\n";
402 }
403 }
404 }
405
406 }
407 catch (oks::exception & e) {
408 throw oks::FailedRead("an xml file header", e);
409 }
410 catch (std::exception & e) {
411 throw oks::FailedRead("an xml file header", e.what());
412 }
413
414
415 // skip document type declaration and comments
416
417 {
418 while(true) {
419 try {
420 const char * dtd = xmls->get_tag();
421 const char dtd_start[] = "<!DOCTYPE ";
422 if(!strncmp(dtd_start, dtd, sizeof(dtd_start) - 1)) {
423 break;
424 }
425 }
426 catch (oks::exception & e) {
427 throw oks::FailedRead("DTD section", e);
428 }
429 catch (std::exception & e) {
430 throw oks::FailedRead("DTD section", e.what());
431 }
432 }
433 }
434
435
436 // skip
437
438 try {
439 xmls->store_position();
440
441 const char * a_tag = xmls->get_tag();
442
443 const char xml_stylesheet_start[] = "<?xml-stylesheet";
444 if(strncmp(xml_stylesheet_start, a_tag, sizeof(xml_stylesheet_start) - 1)) {
445 xmls->restore_position();
446 }
447 }
448 catch (oks::exception & e) {
449 throw oks::FailedRead("an xml-stylesheet tag or an oks tag", e);
450 }
451 catch (std::exception & e) {
452 throw oks::FailedRead("an xml-stylesheet tag or an oks tag", e.what());
453 }
454
455 // read start-of-tag
456
457 try {
458 xmls->get_tag_start();
459 }
460 catch (oks::exception & e) {
461 throw oks::FailedRead("tag", e);
462 }
463 catch (std::exception & e) {
464 throw oks::FailedRead("tag", e.what());
465 }
466
467
468 // read info tag
469
470 try {
471 const char * tag_start = xmls->get_tag_start();
472
473 if(!oks::cmp_str4(tag_start, xml_info_tag)) {
474 xmls->throw_unexpected_tag(tag_start, xml_info_tag);
475 }
476 }
477 catch (oks::exception & e) {
478 throw oks::FailedRead("<info> tag", e);
479 }
480 catch (std::exception & e) {
481 throw oks::FailedRead("<info> tag", e.what());
482 }
483
484
485 std::string oks_version;
486
487
488 // read class attributes
489
490 try {
491 while(true) {
492 OksXmlAttribute attr(*xmls);
493
494 // check for close of tag
495
496 if(oks::cmp_str1(attr.name(), ">") || oks::cmp_str1(attr.name(), "/")) { break; }
497
498 // check for known info' attributes
499
500 else if(oks::cmp_str4 (attr.name(), "name")) p_logical_name.assign(attr.value(), attr.value_len());
501 else if(oks::cmp_str4 (attr.name(), "type")) p_type.assign(attr.value(), attr.value_len());
502 else if(oks::cmp_str10(attr.name(), "oks-format")) p_oks_format.assign(attr.value(), attr.value_len());
503 else if(oks::cmp_str10(attr.name(), "created-by")) p_created_by.assign(attr.value(), attr.value_len());
504 else if(oks::cmp_str10(attr.name(), "created-on")) p_created_on.assign(attr.value(), attr.value_len());
505 else if(oks::cmp_str11(attr.name(), "oks-version")) oks_version.assign(attr.value(), attr.value_len());
506 else if(oks::cmp_str12(attr.name(), "num-of-items")) p_number_of_items = atol(attr.value());
507 else if(oks::cmp_str13(attr.name(), "creation-time")) p_creation_time = oks::str2time(attr.value(), attr.value_len(), p_full_name.c_str());
508 else if(oks::cmp_str15(attr.name(), "num-of-includes")) continue; // ignore this value
509 else if(oks::cmp_str16(attr.name(), "last-modified-by")) p_last_modified_by.assign(attr.value(), attr.value_len());
510 else if(oks::cmp_str16(attr.name(), "last-modified-on")) p_last_modified_on.assign(attr.value(), attr.value_len());
511 else if(!strcmp(attr.name(), "last-modification-time")) p_last_modification_time = oks::str2time(attr.value(), attr.value_len(), p_full_name.c_str());
512 else {
513 p_oks_format.clear();
514 xmls->throw_unexpected_tag(attr.name(), "info\'s tags");
515 }
516 }
517 }
518 catch(oks::exception & e) {
519 throw oks::FailedRead("<info> tag attribute", e);
520 }
521 catch (std::exception & e) {
522 throw oks::FailedRead("<info> tag attribute", e.what());
523 }
524
525 // read include and comments sections
526 while(true) {
527 xmls->store_position();
528
529 bool read_include = false;
530
531 try {
532 const char * tag_start = xmls->get_tag_start();
533 if(oks::cmp_str7(tag_start, xml_include_tag)) { read_include = true; }
534 else if(oks::cmp_str8(tag_start, xml_comments_tag)) { read_include = false; }
535 else { xmls->restore_position(); return; }
536 }
537 catch (oks::exception & e) {
538 throw oks::FailedRead("a tag", e);
539 }
540 catch (std::exception & e) {
541 throw oks::FailedRead("a tag", e.what());
542 }
543
544 if(read_include) {
545 while(true) {
546 try {
547
548 {
549 const char * tag_start = xmls->get_tag_start();
550 if(!oks::cmp_str4(tag_start, xml_file_tag)) {
551 if(!oks::cmp_str8(tag_start, "/include")) { xmls->throw_unexpected_tag(tag_start + 1, xml_file_tag); }
552 break;
553 }
554 }
555
556 while(true) {
557 OksXmlAttribute attr(*xmls);
558
559 // check for close of tag
560 if(oks::cmp_str1(attr.name(), ">") || oks::cmp_str1(attr.name(), "/")) { break; }
561
562 // check for known info' attributes
563 else if(oks::cmp_str4(attr.name(), "path")) p_list_of_include_files.push_back(std::string(attr.value(),attr.value_len()));
564 else {
565 p_oks_format.clear();
566 xmls->throw_unexpected_tag(attr.name(), "path");
567 }
568 }
569
570 }
571 catch (oks::exception & e) {
572 throw oks::FailedRead("<file> tag", e);
573 }
574 catch (std::exception & e) {
575 throw oks::FailedRead("<file> tag", e.what());
576 }
577 }
578 }
579 else {
580 while(true) {
581 try {
582
583 {
584 const char * tag_start = xmls->get_tag_start();
585 if(!oks::cmp_str7(tag_start, xml_comment_tag)) {
586 if(!oks::cmp_str9(tag_start, "/comments")) { xmls->throw_unexpected_tag(tag_start, xml_comment_tag); }
587 return;
588 }
589 }
590
591 std::unique_ptr<oks::Comment> comment( new oks::Comment() );
592 std::string creation_time;
593
594 while(true) {
595 OksXmlAttribute attr(*xmls);
596
597 // check for close of tag
598 if(oks::cmp_str1(attr.name(), ">") || oks::cmp_str1(attr.name(), "/")) { break; }
599
600 // check for known info' attributes
601 else if(oks::cmp_str4 (attr.name(), "text")) comment->p_text.assign(attr.value(), attr.value_len());
602 else if(oks::cmp_str6 (attr.name(), "author")) comment->p_author.assign(attr.value(), attr.value_len());
603 else if(oks::cmp_str10(attr.name(), "created-by")) comment->p_created_by.assign(attr.value(), attr.value_len());
604 else if(oks::cmp_str10(attr.name(), "created-on")) comment->p_created_on.assign(attr.value(), attr.value_len());
605 else if(oks::cmp_str13(attr.name(), "creation-time")) creation_time.assign(attr.value(), attr.value_len());
606 else {
607 p_oks_format.clear();
608 xmls->throw_unexpected_tag(attr.name(), "comment\'s tags");
609 }
610 }
611
612 comment->validate(creation_time);
613
614 if(p_comments.find(creation_time) != p_comments.end()) {
615 std::ostringstream text;
616 text << "The comment created at \'" << creation_time << "\' was already defined in this file";
617 throw std::runtime_error(text.str().c_str());
618 }
619
620 p_comments[creation_time] = comment.release();
621
622 }
623 catch (oks::exception & e) {
624 throw oks::FailedRead("<comment>", e);
625 }
626 catch (std::exception & e) {
627 throw oks::FailedRead("<comment>", e.what());
628 }
629 }
630 }
631 }
632}
633
634
635void
636oks::Comment::validate(const std::string& creation_time)
637{
638 // YYYYMMDDThhmmss
639 if( creation_time.size() != 15 || creation_time[8] != 'T' ) {
640 std::ostringstream msg;
641 msg << "the creation time \'" << creation_time << "\' is not an ISO-8601 date-time";
642 throw std::runtime_error(msg.str().c_str());
643 }
644
645 validate();
646}
647
648void
650{
651 if(p_text.empty()) {
652 throw std::runtime_error("text is empty");
653 }
654}
655
656oks::Comment::Comment(const std::string& text, const std::string& author) :
657 p_created_by (OksKernel::get_user_name()),
658 p_author (author),
659 p_created_on (OksKernel::get_host_name()),
660 p_text (text)
661{
662 validate();
663}
664
666 p_created_by (src.p_created_by),
667 p_author (src.p_author),
668 p_created_on (src.p_created_on),
669 p_text (src.p_text)
670{
671}
672
673void
674OksFile::add_comment(const std::string& text, const std::string& author)
675{
676 try {
677 lock();
678 }
679 catch(oks::exception& ex) {
680 throw oks::FailedAddComment(*this, ex);
681 }
682
683 boost::posix_time::ptime now = boost::posix_time::second_clock::universal_time();
684 std::string creation_time = boost::posix_time::to_iso_string(now);
685
686 try {
687 std::unique_ptr<oks::Comment> comment( new oks::Comment(text, author) );
688 comment->validate();
689
690 oks::Comment *& x(p_comments[creation_time]);
691
692 if(x == 0)
693 {
694 x = comment.release();
695 }
696 else
697 {
698 x->p_text += "\n-----\n";
699 x->p_text.append(text);
700 }
701 }
702 catch(std::exception & ex) {
703 throw oks::FailedAddComment(*this, ex.what());
704 }
705
706 p_is_updated = true;
707}
708
710OksFile::get_comment(const std::string& creation_time) noexcept
711{
712 std::map<std::string, oks::Comment *>::const_iterator i = p_comments.find(creation_time);
713 return (i == p_comments.end()) ? 0: i->second;
714}
715
716void
717OksFile::modify_comment(const std::string& creation_time, const std::string& text, const std::string& author)
718{
719 if(oks::Comment * comment = get_comment(creation_time)) {
720 try {
721 lock();
722 }
723 catch(oks::exception& ex) {
724 throw oks::FailedChangeComment(*this, creation_time, ex);
725 }
726
727 std::string saved_author(comment->p_author);
728 std::string saved_text(comment->p_text);
729
730 comment->p_author = author;
731 comment->p_text = text;
732
733 try {
734 comment->validate();
735 }
736 catch(std::exception& ex) {
737 comment->p_author = saved_author;
738 comment->p_text = saved_text;
739 throw oks::FailedChangeComment(*this, creation_time, ex.what());
740 }
741
742 p_is_updated = true;
743 }
744 else {
745 throw oks::FailedChangeComment(*this, creation_time, "cannot find comment");
746 }
747}
748
749
750void
751OksFile::remove_comment(const std::string& creation_time)
752{
753 if(oks::Comment * comment = get_comment(creation_time)) {
754 try {
755 lock();
756 }
757 catch(oks::exception& ex) {
758 throw oks::FailedRemoveComment(*this, creation_time, ex);
759 }
760
761 delete comment;
762 p_comments.erase(creation_time);
763 p_is_updated = true;
764 }
765 else {
766 throw oks::FailedRemoveComment(*this, creation_time, "cannot find comment");
767 }
768}
769
770
771void
773{
774 const static std::string __data("data");
775 const static std::string __schema("schema");
776
777 try
778 {
779 const char __oks_data[] = "oks-data";
780 const char __oks_schema[] = "oks-schema";
781
782 const char * id(__oks_data);
783 long id_len(sizeof(__oks_data) - 1);
784 const char * dtd(xml_data_file_dtd);
785 long dtd_len(sizeof(xml_data_file_dtd) - 1);
786
787 if (p_oks_format != __data)
788 {
789 if (p_oks_format == __schema)
790 {
791 id = __oks_schema;
792 id_len = sizeof(__oks_schema) - 1;
794 dtd_len = sizeof(xml_schema_file_dtd) - 1;
795 }
796 else
797 {
798 throw std::runtime_error("bad oks format");
799 }
800 }
801
802 {
803 const char __hdr_start[] = "\n\n<!-- ";
804 const char __hdr_end[] = " version 2.2 -->\n\n\n";
805
806 std::string header(xml_file_header, sizeof(xml_file_header) - 1);
807 header.append(__hdr_start, sizeof(__hdr_start) - 1);
808 header.append(id, id_len);
809 header.append(__hdr_end, sizeof(__hdr_end) - 1);
810 header.append(dtd, dtd_len);
811
812 xmls.put_raw(header.c_str(), header.size());
813 xmls.put_raw('\n');
814 xmls.put_raw('\n');
815 }
816
817 xmls.put_start_tag(id, id_len);
818
819 xmls.put_raw('>');
820 xmls.put_raw('\n');
821 xmls.put_raw('\n');
822
823 // "creation-time" may not be filled
824
825 std::string created_c_str;
826 if (!p_creation_time.is_not_a_date_time())
827 {
828 created_c_str = boost::posix_time::to_iso_string(p_creation_time);
829 }
830
831 // get last-modified information
832
833 if (p_repository_name.empty())
834 {
835 p_last_modification_time = boost::posix_time::second_clock::universal_time();
838 }
839
840 std::string last_modified_c_str = boost::posix_time::to_iso_string(p_last_modification_time);
841
842 xmls.put_start_tag(xml_info_tag, sizeof(xml_info_tag) - 1);
843 xmls.put_attribute("name", sizeof("name") - 1, p_logical_name.c_str());
844 xmls.put_attribute("type", sizeof("type") - 1, p_type.c_str());
845 xmls.put_attribute("num-of-items", sizeof("num-of-items") - 1, p_number_of_items);
846 xmls.put_attribute("oks-format", sizeof("oks-format") - 1, p_oks_format.c_str());
847 xmls.put_attribute("oks-version", sizeof("oks-version") - 1, OksKernel::GetVersion());
848 xmls.put_attribute("created-by", sizeof("created-by") - 1, p_created_by.c_str());
849 xmls.put_attribute("created-on", sizeof("created-on") - 1, p_created_on.c_str());
850 if (!created_c_str.empty())
851 xmls.put_attribute("creation-time", sizeof("creation-time") - 1, created_c_str.c_str());
852 if (p_repository_name.empty())
853 {
854 xmls.put_attribute("last-modified-by", sizeof("last-modified-by") - 1, p_last_modified_by.c_str());
855 xmls.put_attribute("last-modified-on", sizeof("last-modified-on") - 1, p_last_modified_on.c_str());
856 xmls.put_attribute("last-modification-time", sizeof("last-modification-time") - 1, last_modified_c_str.c_str());
857 }
858 xmls.put_end_tag();
859
860 if (!p_list_of_include_files.empty())
861 {
862 xmls.put_raw('\n');
864
865 xmls.put_raw('>');
866 xmls.put_raw('\n');
867
868 for (const auto& i : p_list_of_include_files)
869 {
870 xmls.put_raw(' ');
871 xmls.put_start_tag(xml_file_tag, sizeof(xml_file_tag) - 1);
872 xmls.put_attribute("path", sizeof("path") - 1, i.c_str());
873 xmls.put_end_tag();
874 }
875
877 xmls.put_raw('\n');
878 }
879
880 if (!p_comments.empty())
881 {
883
884 xmls.put_raw('>');
885 xmls.put_raw('\n');
886
887 for (const auto& i : p_comments)
888 {
889 xmls.put_raw(' ');
891 xmls.put_attribute("creation-time", sizeof("creation-time") - 1, i.first.c_str());
892 xmls.put_attribute("created-by", sizeof("created-by") - 1, i.second->p_created_by.c_str());
893 xmls.put_attribute("created-on", sizeof("created-on") - 1, i.second->p_created_on.c_str());
894 xmls.put_attribute("author", sizeof("author") - 1, i.second->p_author.c_str());
895 xmls.put_attribute("text", sizeof("text") - 1, i.second->p_text.c_str());
896 xmls.put_end_tag();
897 }
898
900 xmls.put_raw('\n');
901 }
902
903 xmls.put_raw('\n');
904 }
905 catch (std::exception& ex)
906 {
907 throw oks::FailedSave("oks-file", p_full_name, ex.what());
908 }
909
910 p_is_on_disk = true;
911}
912
913bool
915{
916 return (!p_kernel->get_user_repository_root().empty());
917}
918
919void
921{
922// if(size_t len = OksKernel::get_repository_root().size()) {
923// if(p_full_name.size() > len && p_full_name.substr(0, len) == OksKernel::get_repository_root()) {
924// p_repository = GlobalRepository;
925// p_repository_name = p_full_name.substr(len + 1);
926// TLOG_DEBUG( 3 ) << "file \'" << p_full_name << "\' comes from user repository [\'" << p_repository_name << "\']";
927// return;
928// }
929// }
930
931 const std::string& s(p_kernel->get_user_repository_root());
932 if(size_t len = s.size()) {
933 if(p_full_name.size() > len && p_full_name.substr(0, len) == s) {
934// p_repository = UserRepository;
935 p_repository_name = p_full_name.substr(len + 1);
936
937 TLOG_DEBUG( 3 ) << "file \'" << p_full_name << "\' comes from user repository [\'" << p_repository_name << "\']" ;
938 return;
939
940// std::string repository_file = OksKernel::get_repository_root() + '/' + p_repository_name;
941//
942// struct stat buf;
943// if(stat(repository_file.c_str(), &buf) == 0) {
944// TLOG_DEBUG( 3 ) << "file \'" << p_full_name << "\' comes from user repository [\'" << p_repository_name << "\']" ;
945// return;
946// }
947// else {
948// TLOG_DEBUG( 3 ) << "file \'" << p_full_name << "\' is found in user repository [\'" << p_repository_name << "\'] but does not exist in global one [\'" << OksKernel::get_repository_root() << "\']" ;
949// }
950 }
951 }
952
953 TLOG_DEBUG( 3 ) << "file \'" << p_full_name << "\' is not in a repository" ;
954// p_repository = NoneRepository;
955 p_repository_name.clear();
956}
957
958void
960{
962
963 std::string::size_type idx = p_lock_file_name.find_last_of('/');
964 if(idx == std::string::npos) p_lock_file_name = "./";
965 else p_lock_file_name.erase(idx+1);
966
967 const char _prefix_str[] = ".oks-lock-";
968 p_lock_file_name.append(_prefix_str, sizeof(_prefix_str)-1);
969
970 idx = p_full_name.find_last_of('/');
971 std::string::size_type len(p_full_name.size());
972 if(idx == std::string::npos) {
973 idx = 0;
974 }
975 else {
976 idx++;
977 len -= idx;
978 }
979
980 p_lock_file_name.append(p_full_name, idx, len);
981 p_lock_file_name.append(".txt");
982}
983
984
985 // return true if lock exists and false if does not exist
986 // the string is non-empty, if the lock file was read
987
988bool
989OksFile::get_lock_string(std::string& lock_file_contents) const
990{
992
993 lock_file_contents.clear();
994
995 const char * lock_name = p_lock_file_name.c_str();
996 struct stat buf;
997
998 if(stat(lock_name, &buf) == 0) {
999 std::ifstream f(lock_name);
1000
1001 if(f.good()) {
1002 std::getline(f, lock_file_contents);
1003 return true;
1004 }
1005 else {
1006 lock_file_contents = "unknown [cannot read lock file \'";
1007 lock_file_contents += p_lock_file_name;
1008 lock_file_contents += "\']";
1009 return true;
1010 }
1011 }
1012
1013 return false;
1014}
1015
1016void
1018{
1019 if (p_nolock_mode) {
1020 // Nasty hack to allow code generation on the fly without locking
1021 // file. Just return without locking!
1022 return;
1023 }
1024
1026
1027 if (p_lock != nullptr)
1028 {
1029 return;
1030 }
1031
1032
1033 // check that the file is not read-only
1034
1035 {
1036 struct stat buf;
1037
1038 if (stat(p_full_name.c_str(), &buf) == 0)
1039 {
1040 if (OksKernel::check_read_only(this) == true)
1041 {
1042 throw oks::FileLockError(*this, true, "file is read-only");
1043 }
1044 }
1045 }
1046
1047
1048 // check lock and report problem if it exists and cannot be reset
1049
1050 {
1051 std::string lock_file_contents;
1052
1053 if (get_lock_string(lock_file_contents))
1054 {
1055 try
1056 {
1057 boost::interprocess::file_lock lock(p_lock_file_name.c_str());
1058
1059 if (lock.try_lock() == false)
1060 {
1061 std::ostringstream text;
1062 text << "file is already locked by \"" << lock_file_contents << '\"';
1063 throw oks::FileLockError(*this, true, text.str());
1064 }
1065 else
1066 {
1067 try
1068 {
1069 lock.unlock();
1070 }
1071 catch (const boost::interprocess::interprocess_exception& ex)
1072 {
1073 std::ostringstream text;
1074 text << "boost::interprocess::unlock() failed: \"" << ex.what() << '\"';
1075 throw oks::FileLockError(*this, false, text.str());
1076 }
1077
1078 if (!p_kernel->get_silence_mode())
1079 {
1080 Oks::warning_msg("OksFile::lock()") << "Remove obsolete lock of file \'" << p_full_name << "\' created by \n\"" << lock_file_contents << "\"\n";
1081 }
1082
1083 if (unlink(p_lock_file_name.c_str()) != 0)
1084 {
1085 std::ostringstream text;
1086 text << "failed to remove lock file \'" << p_lock_file_name << "\':\n" << oks::strerror(errno);
1087 throw oks::FileLockError(*this, false, text.str());
1088 }
1089 }
1090 }
1091 catch (const boost::interprocess::interprocess_exception& ex)
1092 {
1093 std::ostringstream text;
1094 text << "boost::interprocess::try_lock() failed: \"" << ex.what() << '\"';
1095 throw oks::FileLockError(*this, false, text.str());
1096 }
1097 }
1098 }
1099
1100
1101 // write lock file
1102
1103 {
1104 std::ofstream f(p_lock_file_name.c_str());
1105
1106 if (!f.good())
1107 {
1108 std::ostringstream text;
1109 text << "failed to create lock file \'" << p_lock_file_name << '\'';
1110 throw oks::FileLockError(*this, true, text.str());
1111 }
1112
1113 try
1114 {
1115 boost::posix_time::ptime now(boost::posix_time::second_clock::universal_time());
1116 f << "process " << getpid() << " on " << OksKernel::get_host_name() << " started by " << OksKernel::get_user_name() << " at " << boost::posix_time::to_simple_string(now) << " (UTC)" << std::endl;
1117 f.flush();
1118 f.close();
1119 }
1120 catch (std::exception& ex)
1121 {
1122 std::ostringstream text;
1123 text << "failed to write lock file \'" << p_lock_file_name << "\': " << ex.what();
1124 throw oks::FileLockError(*this, true, text.str());
1125 }
1126 }
1127
1128
1129 try
1130 {
1131 p_lock.reset(new boost::interprocess::file_lock(p_lock_file_name.c_str()));
1132
1133 if (p_lock->try_lock() == false)
1134 {
1135 throw std::runtime_error("file is locked by another process");
1136 }
1137 }
1138 catch (const std::exception& ex)
1139 {
1140 std::ostringstream text;
1141 text << "boost::interprocess::try_lock() failed: \"" << ex.what() << '\"';
1142 p_lock.reset();
1143 throw oks::FileLockError(*this, false, text.str());
1144 }
1145}
1146
1147void
1149{
1150 if (p_lock == nullptr)
1151 return;
1152
1153 try
1154 {
1155 p_lock->unlock();
1156 }
1157 catch (const boost::interprocess::interprocess_exception& ex)
1158 {
1159 std::ostringstream text;
1160 text << "boost::interprocess::unlock() failed: \"" << ex.what() << '\"';
1161 p_lock.reset();
1162 throw oks::FileLockError(*this, false, text.str());
1163 }
1164
1165 p_lock.reset();
1166
1167 if (unlink(p_lock_file_name.c_str()) != 0 && errno != ENOENT)
1168 {
1169 std::ostringstream text;
1170 text << "failed to remove lock file \'" << p_lock_file_name << "\':\n" << oks::strerror(errno);
1171 throw oks::FileLockError(*this, false, text.str());
1172 }
1173}
1174
1175
1176std::list<std::string>::iterator
1177OksFile::find_include_file(const std::string& s)
1178{
1179 std::list<std::string>::iterator i = p_list_of_include_files.begin();
1180
1181 for(;i != p_list_of_include_files.end(); ++i) {if(*i == s) break;}
1182
1183 return i;
1184}
1185
1186
1187OksFile *
1189{
1190 if(p_included_by == 0 && parent_h != 0) {
1191 p_included_by = parent_h;
1192 }
1193
1194 return this;
1195}
1196
1197
1198void
1199OksFile::add_include_file(const std::string& s)
1200{
1201 // check if the file was already included
1202 if(find_include_file(s) != p_list_of_include_files.end()) { return; }
1203
1204 // lock file
1205 try {
1206 lock();
1207 }
1208 catch(oks::exception& ex) {
1209 throw oks::FailedAddInclude(*this, s, ex);
1210 }
1211
1212 // try to find path to include and load it
1213 try {
1214 std::string path = p_kernel->get_file_path(s, this);
1215 p_kernel->k_load_file(path, true, this, 0);
1216 }
1217 catch(std::exception& ex) {
1218 throw oks::FailedAddInclude(*this, s, ex.what());
1219 }
1220
1221 // add include and mark file as updated
1222 p_list_of_include_files.push_back(s);
1223 p_is_updated = true;
1224}
1225
1226
1227void
1228OksFile::remove_include_file(const std::string& s)
1229{
1230 // search included file
1231 std::list<std::string>::iterator i = find_include_file(s);
1232
1233 // check if the file was included
1234 if(i == p_list_of_include_files.end()) {
1235 throw oks::FailedRemoveInclude(*this, s, "there is no such include file");
1236 }
1237
1238 // lock file
1239 try {
1240 lock();
1241 }
1242 catch(oks::exception& ex) {
1243 throw oks::FailedRemoveInclude(*this, s, ex);
1244 }
1245
1246 // remove include and mark file as updated
1247 p_list_of_include_files.erase(i);
1248 p_is_updated = true;
1249
1250 // close file, if it is not referenced by others
1251 p_kernel->k_close_dangling_includes();
1252}
1253
1254
1255void
1256OksFile::rename_include_file(const std::string& old_s, const std::string& new_s)
1257{
1258 if(old_s == new_s) return;
1259
1260 std::list<std::string>::iterator i1 = find_include_file(old_s);
1261 std::list<std::string>::iterator i2 = find_include_file(new_s);
1262
1263 if(i1 == p_list_of_include_files.end()) {
1264 throw oks::FailedRenameInclude(*this, old_s, new_s, "there is no such include file");
1265 }
1266
1267 if(i2 != p_list_of_include_files.end()) {
1268 throw oks::FailedRenameInclude(*this, old_s, new_s, "file with new name is already included");
1269 }
1270
1271 try {
1272 lock();
1273 }
1274 catch(oks::exception& ex) {
1275 throw oks::FailedRenameInclude(*this, old_s, new_s, ex);
1276 }
1277
1278 (*i1) = new_s;
1279 p_is_updated = true;
1280}
1281
1282
1283void
1284OksFile::set_logical_name(const std::string& s)
1285{
1286 if(s == p_logical_name) return;
1287
1288 try {
1289 lock();
1290 }
1291 catch(oks::exception& ex) {
1292 throw oks::FileChangeError(*this, "set logical name", ex);
1293 }
1294
1295 p_logical_name = s;
1296 p_is_updated = true;
1297}
1298
1299
1300void
1301OksFile::set_type(const std::string& s)
1302{
1303 if(s == p_type) return;
1304
1305 try {
1306 lock();
1307 }
1308 catch(oks::exception& ex) {
1309 throw oks::FileChangeError(*this, "set type", ex);
1310 }
1311
1312 p_type = s;
1313 p_is_updated = true;
1314}
1315
1316std::ostream& operator<<(std::ostream& s, const oks::Comment& c)
1317{
1318 s << "user \"" << c.get_created_by() << "\" (" << c.get_author() << ")"
1319 << " on \"" << c.get_created_on() << "\" wrote: \"" << c.get_text() << "\"";
1320
1321 return s;
1322}
1323
1324
1325std::ostream&
1326operator<<(std::ostream& s, const OksFile& f)
1327{
1328 s << "OKS file\n"
1329 " short file name: \'" << f.get_short_file_name() << "\'\n"
1330 " full file name: \'" << f.get_full_file_name() << "\'\n"
1331 " lock file name: \'" << f.get_lock_file() << "\'\n"
1332 " logical name: \'" << f.get_logical_name() << "\'\n"
1333 " type: \'" << f.get_type() << "\'\n"
1334 " oks format: \'" << f.get_oks_format() << "\'\n"
1335 " number of items: " << f.get_number_of_items() << "\n"
1336 " created by: " << f.get_created_by() << "\n"
1337 " creation time: " << boost::posix_time::to_simple_string(f.get_creation_time()) << "\n"
1338 " created on: " << f.get_created_on() << "\n"
1339 " last modified by: \'" << f.get_last_modified_by() << "\'\n"
1340 " last modification time: " << boost::posix_time::to_simple_string(f.get_last_modification_time()) << "\'\n"
1341 " last modified on: " << f.get_last_modified_on() << "\'\n"
1342 " is " << (f.is_read_only() ? "read-only" : "read-write") << "\n"
1343 " is " << (f.is_locked() ? "" : "not ") << "locked\n"
1344 " is " << (f.is_updated() ? "" : "not ") << "updated\n";
1345
1346 {
1347 size_t num_of_includes = f.get_include_files().size();
1348
1349 if (num_of_includes)
1350 {
1351 s << " contains " << num_of_includes << " include file(s)";
1352 for (const auto& i : f.get_include_files())
1353 s << " - \'" << i << "\'\n";
1354 }
1355 else
1356 {
1357 s << " contains no include files\n";
1358 }
1359 }
1360
1361 {
1362 size_t num_of_comments = f.get_comments().size();
1363
1364 if (num_of_comments)
1365 {
1366 s << " contains " << num_of_comments << " comment(s)";
1367 for (const auto& i : f.get_comments())
1368 s << " - " << boost::posix_time::to_simple_string(boost::posix_time::from_iso_string(i.first)) << ": \'" << *i.second << "\'\n";
1369 }
1370 else
1371 {
1372 s << " contains no comments\n";
1373 }
1374 }
1375
1376 s << "END of oks file\n";
1377
1378 return s;
1379}
1380
1381
1382std::string
1384{
1385 std::string name;
1386
1387 if(!OksKernel::get_repository_root().empty()) {
1389 }
1390
1391 return name;
1392}
1393
1394
1395void
1396OksFile::update_status_of_file(bool update_local, bool update_repository)
1397{
1398 struct stat buf;
1399
1400 if(update_local == true && p_is_on_disk == true) {
1401
1402 if(stat(p_full_name.c_str(), &buf) == 0) {
1403 p_last_modified = buf.st_mtime;
1404 }
1405 }
1406
1407 if(update_repository == true /*&& get_repository() == UserRepository*/) {
1408 std::string full_repository_name = make_repository_name();
1409
1410 if(!full_repository_name.empty() && stat(full_repository_name.c_str(), &buf) == 0) {
1411 p_repository_last_modified = buf.st_mtime;
1412 }
1413 }
1414}
1415
1416
1419{
1420 if(p_is_on_disk == false) {
1421 return FileWasNotSaved;
1422 }
1423 else {
1424 struct stat buf;
1425
1426 if(stat(p_full_name.c_str(), &buf) != 0) {
1427 return FileRemoved;
1428 }
1429
1430 if(buf.st_mtime != p_last_modified) {
1431 return FileModified;
1432 }
1433
1434// if(get_repository() == UserRepository) {
1435// std::string full_repository_name = make_repository_name();
1436//
1437// if(!full_repository_name.empty()) {
1438// if(stat(full_repository_name.c_str(), &buf) != 0) {
1439// return FileRepositoryRemoved;
1440// }
1441//
1442// if(buf.st_mtime != p_repository_last_modified) {
1443// return FileRepositoryModified;
1444// }
1445// }
1446// }
1447 }
1448
1449 return FileNotModified;
1450}
1451
1452
1453void
1454OksFile::rename(const std::string& short_name, const std::string& full_name)
1455{
1456 p_short_name = short_name;
1457 p_full_name = full_name;
1460}
1461
1462void
1463OksFile::rename(const std::string& full_name)
1464{
1465 p_full_name = full_name;
1468}
1469
1470void
1471OksFile::get_all_include_files(const OksKernel * kernel, std::set<OksFile *>& out)
1472{
1473 const OksFile::Map & schema_files = kernel->schema_files();
1474 const OksFile::Map & data_files = kernel->data_files();
1475
1476 for(std::list<std::string>::iterator i = p_list_of_include_files.begin(); i != p_list_of_include_files.end(); ++i) {
1477 std::string s = kernel->get_file_path(*i, this);
1478 if(s.size()) {
1479 OksFile::Map::const_iterator j = data_files.find(&s);
1480 if(j != data_files.end()) {
1481 if(out.find(j->second) != out.end()) { continue; }
1482 out.insert(j->second);
1483 }
1484 else {
1485 j = schema_files.find(&s);
1486 if(j != schema_files.end()) {
1487 if(out.find(j->second) != out.end()) { continue; }
1488 out.insert(j->second);
1489 }
1490 else {
1491 continue;
1492 }
1493 }
1494
1495 j->second->get_all_include_files(kernel, out);
1496 }
1497 }
1498}
1499
1500// return true if the string is not info line:
1501// <info ... last-modification-time="nnnnnnnnTnnnnnn"/>
1502
1503static bool
1504is_not_info(const std::string& line)
1505{
1506 static const char start_tag[] = "<info ";
1507 static const char last_tag[] = "last-modification-time=\"yyyymmddThhmmss\"/>"; // 24 - is a position of first double quote
1508
1509 const std::string::size_type len = line.length();
1510
1511 return(
1512 ( len < (sizeof(start_tag) + sizeof(last_tag)) ) ||
1513 ( line.compare(0, sizeof(start_tag)-1, start_tag, sizeof(start_tag)-1) != 0 ) ||
1514 ( line.compare(len - sizeof(last_tag) + 1, 24, last_tag, 24) != 0 )
1515 );
1516}
1517
1518bool
1519OksFile::compare(const char * file1_name, const char * file2_name)
1520{
1521 std::ifstream f1(file1_name);
1522 std::ifstream f2(file2_name);
1523
1524 if (!f1)
1525 {
1526 throw oks::FileCompareError(file1_name, file2_name, "cannot open file");
1527 }
1528
1529 if (!f2)
1530 {
1531 throw oks::FileCompareError(file2_name, file1_name, "cannot open file");
1532 }
1533
1534 std::string line1;
1535 std::string line2;
1536
1537 while (true)
1538 {
1539 if (f1.eof() && f2.eof())
1540 {
1541 return true;
1542 }
1543
1544 std::getline(f1, line1);
1545 std::getline(f2, line2);
1546
1547 if ((line1 != line2) && (is_not_info(line1) || is_not_info(line2)))
1548 {
1549 return false;
1550 }
1551 }
1552
1553 return true;
1554}
1555
1556} // namespace oks
1557} // namespace dunedaq
The comment about file modification. A comment can be added when user saves file using OKS tools.
Definition file.hpp:275
std::string p_created_by
Definition file.hpp:314
Comment() noexcept
Definition file.hpp:282
std::string p_created_on
Definition file.hpp:316
std::string p_text
Definition file.hpp:317
std::string p_author
Definition file.hpp:315
Cannot add comment. Such exception is thrown when OKS cannot add new comment.
Definition file.hpp:200
static std::string fill(const OksFile &file, const std::string &reason) noexcept
Definition file.cpp:221
Cannot add include file. Such exception is thrown when OKS cannot add include file.
Definition file.hpp:125
static std::string fill(const OksFile &file, const std::string &include_name, const std::string &reason) noexcept
Definition file.cpp:203
Cannot change comment. Such exception is thrown when OKS cannot change comment.
Definition file.hpp:250
static std::string fill(const OksFile &file, const std::string &creation_time, const std::string &reason) noexcept
Definition file.cpp:233
Cannot remove comment. Such exception is thrown when OKS cannot remove comment.
Definition file.hpp:225
static std::string fill(const OksFile &file, const std::string &creation_time, const std::string &reason) noexcept
Definition file.cpp:227
Cannot remove include file. Such exception is thrown when OKS cannot remove include file.
Definition file.hpp:150
static std::string fill(const OksFile &file, const std::string &include_name, const std::string &reason) noexcept
Definition file.cpp:209
Cannot rename include file. Such exception is thrown when OKS cannot rename include file.
Definition file.hpp:175
static std::string fill(const OksFile &file, const std::string &from, const std::string &to, const std::string &reason) noexcept
Definition file.cpp:215
static std::string fill(const OksFile &file, const std::string &action, const std::string &reason) noexcept
Definition file.cpp:245
static std::string fill(const std::string &src, const std::string &dest, const std::string &reason) noexcept
Definition file.cpp:251
Cannot add include file. Such exception is thrown when OKS cannot add include file.
Definition file.hpp:53
static std::string fill(const OksFile &file, bool lock_action, const std::string &reason) noexcept
Definition file.cpp:239
Provides interface to the OKS XML schema and data files.
Definition file.hpp:345
static bool compare(const char *file1_name, const char *file2_name)
Compare two files.
Definition file.cpp:1519
static const char xml_schema_file_dtd[]
Definition file.hpp:772
std::shared_ptr< boost::interprocess::file_lock > p_lock
Definition file.hpp:759
std::string p_lock_file_name
Definition file.hpp:760
std::list< std::string >::iterator find_include_file(const std::string &)
Definition file.cpp:1177
std::string p_oks_format
Definition file.hpp:749
static const char xml_comments_tag[]
Definition file.hpp:777
void unlock()
Unlock OKS file.
Definition file.cpp:1148
void add_include_file(const std::string &name)
Add include file.
Definition file.cpp:1199
time_t p_repository_last_modified
Definition file.hpp:765
OksFile(const std::string &, const std::string &, const std::string &, const std::string &, OksKernel *)
Definition file.cpp:257
oks::Comment * get_comment(const std::string &creation_time) noexcept
Definition file.cpp:710
void get_all_include_files(const OksKernel *kernel, std::set< OksFile * > &out)
Get all include files.
Definition file.cpp:1471
void lock()
Lock OKS file.
Definition file.cpp:1017
void write(OksXmlOutputStream &)
Definition file.cpp:772
std::string p_created_by
Definition file.hpp:752
void set_type(const std::string &type)
Set file type.
Definition file.cpp:1301
void init_lock_name() const
Definition file.hpp:803
bool get_lock_string(std::string &info) const
Return lock status of OKS file and if the file is locked, get information string about process which ...
Definition file.cpp:989
static const char xml_data_file_dtd[]
Definition file.hpp:773
std::string make_repository_name() const
Definition file.cpp:1383
std::string p_short_name
Definition file.hpp:744
static bool p_nolock_mode
Definition file.hpp:742
std::map< std::string, oks::Comment * > p_comments
Definition file.hpp:766
boost::posix_time::ptime p_last_modification_time
Definition file.hpp:756
std::list< std::string > p_list_of_include_files
Definition file.hpp:763
boost::posix_time::ptime p_creation_time
Definition file.hpp:753
std::string p_logical_name
Definition file.hpp:747
const std::string & get_repository_name() const
Get name of file inside repository.
Definition file.hpp:555
void remove_comment(const std::string &creation_time)
Modify existing comment.
Definition file.cpp:751
void set_logical_name(const std::string &name)
Set logical name of file.
Definition file.cpp:1284
std::string p_repository_name
Definition file.hpp:746
std::string p_last_modified_by
Definition file.hpp:755
friend class OksKernel
Definition file.hpp:347
OksKernel * p_kernel
Definition file.hpp:769
void add_comment(const std::string &text, const std::string &author)
Add new comment to file.
Definition file.cpp:674
void update_status_of_file(bool update_local=true, bool update_repository=true)
Update status of file.
Definition file.cpp:1396
std::map< const std::string *, OksFile *, SortByName > Map
Definition file.hpp:372
std::string p_full_name
Definition file.hpp:745
std::string p_type
Definition file.hpp:748
bool is_repository_file() const
Get information about repository, the file belongs to.
Definition file.cpp:914
~OksFile() noexcept
Definition file.cpp:295
void create_lock_name()
Definition file.cpp:959
void check_repository()
Definition file.cpp:920
void clear_comments() noexcept
Definition file.cpp:285
static const char xml_file_tag[]
Definition file.hpp:776
OksFile * check_parent(const OksFile *parent_h)
Set given parent, if this file is not yet included.
Definition file.cpp:1188
const OksFile * p_included_by
Definition file.hpp:768
static const char xml_comment_tag[]
Definition file.hpp:778
std::string p_last_modified_on
Definition file.hpp:757
OksFile & operator=(const OksFile &)
Definition file.cpp:301
void modify_comment(const std::string &creation_time, const std::string &text, const std::string &author)
Definition file.cpp:717
void rename_include_file(const std::string &from, const std::string &to)
Rename include file.
Definition file.cpp:1256
static const char xml_file_header[]
Definition file.hpp:771
std::string p_created_on
Definition file.hpp:754
FileStatus get_status_of_file() const
Return update status of file.
Definition file.cpp:1418
static const char xml_include_tag[]
Definition file.hpp:775
void rename(const std::string &short_name, const std::string &full_name)
Definition file.cpp:1454
void remove_include_file(const std::string &name)
Remove include file.
Definition file.cpp:1228
static const char xml_info_tag[]
Definition file.hpp:774
Provides interface to the OKS kernel.
Definition kernel.hpp:582
static std::string & get_host_name()
Get hostname of given process.
Definition kernel.cpp:434
static std::string & get_user_name()
Get username of given process.
Definition kernel.cpp:473
static bool check_read_only(OksFile *f)
Check if the OKS file is read-only.
Definition kernel.cpp:1537
const OksFile::Map & data_files() const
Get all data files.
Definition kernel.hpp:1498
std::string get_file_path(const std::string &path, const OksFile *parent_file=0, bool strict_paths=true) const
Calculates full path to file.
Definition kernel.cpp:1665
static const std::string & get_repository_root()
Get OKS repository root.
Definition kernel.cpp:309
static const char * GetVersion()
Get OKS version. The method returns string containing CVS tag and date of OKS build.
Definition kernel.cpp:302
const OksFile::Map & schema_files() const
Get all schema files.
Definition kernel.hpp:1228
void put_last_tag(const char *, size_t len)
Definition xml.cpp:209
void put_attribute(const char *, size_t len, const char *)
Definition xml.cpp:225
void put_start_tag(const char *, size_t len)
Definition xml.cpp:176
static std::ostream & warning_msg(const char *)
Definition kernel.cpp:568
virtual const char * what() const noexcept
static int64_t now()
#define TLOG_DEBUG(lvl,...)
Definition Logging.hpp:112
bool cmp_str8(const char *s1, const char s2[9])
Definition cstring.hpp:66
const std::string strerror(int error)
Convert C error number to string.
Definition kernel.cpp:119
bool cmp_str1(const char *s1, const char s2[2])
Definition cstring.hpp:14
bool cmp_str4(const char *s1, const char s2[5])
Definition cstring.hpp:34
bool cmp_str6(const char *s1, const char s2[7])
Definition cstring.hpp:50
bool cmp_str10(const char *s1, const char s2[11])
Definition cstring.hpp:78
static bool is_not_info(const std::string &line)
Definition file.cpp:1504
bool cmp_str9(const char *s1, const char s2[10])
Definition cstring.hpp:74
boost::posix_time::ptime str2time(const char *value, size_t len, const char *file_name=nullptr)
const char _empty_str[]
Definition file.cpp:347
std::ostream & operator<<(std::ostream &s, const oks::exception &ex)
bool cmp_str13(const char *s1, const char s2[14])
Definition cstring.hpp:90
bool cmp_str16(const char *s1, const char s2[17])
Definition cstring.hpp:102
bool cmp_str15(const char *s1, const char s2[16])
Definition cstring.hpp:98
bool cmp_str11(const char *s1, const char s2[12])
Definition cstring.hpp:82
bool cmp_str12(const char *s1, const char s2[13])
Definition cstring.hpp:86
bool cmp_str7(const char *s1, const char s2[8])
Definition cstring.hpp:58
Including Qt Headers.
Definition module.cpp:16
FELIX Initialization std::string initerror FELIX queue timed out
Both frame_count_limit and tp_count_limit were set to(disabled) in the TPCRawDataProcessor config. TPs will not send."
Definition ral.hpp:35
size_t value_len() const
Definition xml.hpp:309