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