API
 
Loading...
Searching...
No Matches
logMap.hpp
Go to the documentation of this file.
1/** \file logMap.hpp
2 * \brief Declares and defines the logMap class and related classes.
3 * \author Jared R. Males (jaredmales@gmail.com)
4 *
5 * \ingroup logger_files
6 *
7 * History:
8 * - 2020-01-02 created by JRM
9 */
10
11#ifndef logger_logMap_hpp
12#define logger_logMap_hpp
13
14#include <mx/sys/timeUtils.hpp>
15using namespace mx::sys::tscomp;
16
17#include <mx/ioutils/fileUtils.hpp>
18
19#include <vector>
20#include <map>
21
22#include <flatlogs/flatlogs.hpp>
23#include "../file/stdFileName.hpp"
24
25#ifndef DEBUG_CRUMB
26#define DEBUG_CRUMB(msg) {std::cerr << msg << '(' << __FILE__ << ' ' << __LINE__ << "\n";}
27#endif
28
29namespace MagAOX
30{
31namespace logger
32{
33
34#ifdef XWCTEST_NAMESPACE
35namespace XWCTEST_NAMESPACE
36{
37#endif
38
39/// Structure to hold a log file in memory, tracking when a new file needs to be opened.
41{
43
44 std::vector<char> m_memory; ///< The buffer holding the log data.
45
46 flatlogs::timespecX m_startTime{ 0, 0 };
47 flatlogs::timespecX m_endTime{ 0, 0 };
48
49 int loadFile( file::stdFileName<verboseT> const &lfn );
50};
51
52/// Map of log entries by application name, mapping both to files and to loaded buffers.
53template <class verboseT = XWC_DEFAULT_VERBOSITY>
54struct logMap
55{
56
59
60 /// The app-name to file-name map type, for sorting the input files by application
61 typedef std::map<std::string, std::set<stdFileNameT, file::compStdFileName<stdFileNameT>>> appToFileMapT;
62
63 /// The app-name to buffer map type, for looking up the currently loaded logs for a given app.
64 typedef std::map<std::string, logInMemory> appToBufferMapT;
65
66 int m_searchDaySpan {100}; ///< Maximum number of days to search for files in the past/future.
67
69
71
72 /// Add a list of files to the file map
73 /** This is a worker function for loadAppToFileMap
74 *
75 * \returns mx::error_t::noerror on success
76 * \returns mx::error_t::std_exception if a std::exception is thrown
77 */
78 mx::error_t addFileListToFileMap( const std::string &dev, /**< [in] the device name to add*/
79 const std::vector<std::string> &flist, /**< [in] the file list from which to
80 add files*/
81 size_t n0, /**< [in] the first entry in the file list
82 to add*/
83 size_t nf /**< [in] one past the last entry in the
84 file list to add, e.g. flist.size()*/
85 );
86
87 /// Get log file names in a directory and distribute them into the map by app-name
88 /** Finding no logs is not reported as an error (no exception is thrown). You must check
89 * the size of m_appToFileMap to check if any files were found.
90 *
91 */
92 mx::error_t loadAppToFileMap( const std::string &dir, /**< [in] the directory to search for files
93 (contains the dev/YYYY_MM_DD subdirs)*/
94 const std::string &dev, ///< [in] the device name to search for logs of
95 const std::string &ext, ///< [in] the extension to search for
96 const stdFileNameT &firstFile, ///< [in] the first file that needs coverage
97 const stdFileNameT &lastFile ///< [in] the last file that needs coverage
98 );
99
100 /// Get the log for an event code which is the first prior to the supplied time
101 int getPriorLog( char *&logBefore, ///< [out] pointer to the first byte of the prior log entry
102 const std::string &appName, ///< [in] the name of the app specifying which log to search
103 const flatlogs::eventCodeT &ev, ///< [in] the event code to search for
104 const flatlogs::timespecX &ts, ///< [in] the timestamp to be prior to
105 char *hint = 0 /**< [in] [optional] a hint specifying
106 where to start searching. If null
107 search starts at beginning.*/
108 );
109
110 /// Get the next log with the same event code which is after the supplied time
111 int getNextLog( char *&logAfter, ///< [out] pointer to the first byte of the prior log entry
112 char *logCurrent, ///< [in] The log to start from
113 const std::string &appName ///< [in] the name of the app specifying which log to search
114 );
115
116 int getNearestLogs( flatlogs::bufferPtrT &logBefore, flatlogs::bufferPtrT &logAfter, const std::string &appName );
117
118 int loadFiles( const std::string &appName, ///< MagAO-X app name for which to load files
119 const flatlogs::timespecX &startTime ///<
120 );
121};
122
123template <class verboseT>
124mx::error_t logMap<verboseT>::addFileListToFileMap( const std::string &dev,
125 const std::vector<std::string> &flist,
126 size_t n0,
127 size_t nf )
128{
129 try
130 {
131 // clang-format off
132 #ifdef XWCTEST_LOGMAP_AFLTFM_XWCE
133 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
134 #endif
135
136 #ifdef XWCTEST_LOGMAP_AFLTFM_BADALL
137 throw std::bad_alloc; // LCOV_EXCL_LINE
138 #endif
139
140 #ifdef XWCTEST_LOGMAP_AFLTFM_EXCEPTION
141 throw std::exception; // LCOV_EXCL_LINE
142 #endif
143 // clang-format on
144
145 for( size_t n = n0; n < nf; ++n )
146 {
147 file::stdFileName<verboseT> sfn( flist[n] );
148
149 if( !sfn.valid() ) // this is just not a standard file name.
150 {
151 continue;
152 }
153
154 if( sfn.appName() != dev ) // this is just a different app
155 {
156 continue;
157 }
158
159 m_appToFileMap[dev].insert( sfn );
160 }
161
162 return mx::error_t::noerror;
163 }
164 catch( const xwcException &e )
165 {
166 std::throw_with_nested( xwcException( "adding file to map" ) );
167 }
168 catch( const std::bad_alloc &e )
169 {
170 std::throw_with_nested( xwcException( "adding file to map" ) );
171 }
172 catch( const std::exception &e )
173 {
174 return mx::error_report<verboseT>( mx::error_t::std_exception,
175 std::string( "adding file to map:" ) + e.what() );
176 }
177}
178
179template <class verboseT>
180mx::error_t logMap<verboseT>::loadAppToFileMap( const std::string &dir,
181 const std::string &dev,
182 const std::string &ext,
183 const file::stdFileName<verboseT> &firstFile,
184 const file::stdFileName<verboseT> &lastFile )
185{
186 mx::error_t errc;
187
188 bool isdir = mx::ioutils::dir_exists_is( dir, errc );
189
190 mx_error_check_code( errc );
191
192 if( !isdir )
193 {
194 return mx::error_report<verboseT>( mx::error_t::dirnotfound, dir + " does not exist" );
195 }
196
197 // Timestamps for defining the previous log and the following log
198 flatlogs::timespecX prevts = firstFile.timestamp( &errc );
199 mx_error_check_code( errc );
200
201 prevts.time_s -= 60; // Move 60 seconds in future. This is a config setting
202
203 flatlogs::timespecX follts = lastFile.timestamp( &errc );
204 mx_error_check_code( errc );
205
206 follts.time_s += 3600; // Move 3600 seconds in future. This is a config setting
207
208 // Coordinates of the previous log, after it's found
209 bool prevLogFound = false;
210 file::stdSubDir prevLogSubDir;
211 size_t prevLogFile_n = 0;
212
213 // Coordinates of the following log, after it's found
214 bool follLogFound = false;
215 file::stdSubDir follLogSubDir;
216 size_t follLogFile_n;
217
218 std::string basedir = dir + '/' + dev + '/';
219
220 file::stdSubDir subdir = firstFile.subDir( &errc );
221 mx_error_check_code( errc );
222
223 int ndays = 0;
224
225 while( prevLogFound == false && ndays < m_searchDaySpan )
226 {
227 ++ndays;
228
229 std::vector<std::string> tmp_flist;
230
231 isdir = mx::ioutils::dir_exists_is( basedir + subdir.path(), errc );
232 mx_error_check_code( errc );
233
234 if( !isdir ) // this subdir doesn't exist so go around
235 {
236 mx_error_check( subdir.subDay() );
237 continue;
238 }
239
240 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
241
242 if( tmp_flist.size() == 0 ) // this subdir has no files in it so go around
243 {
244 mx_error_check( subdir.subDay() );
245 continue;
246 }
247
248 // Start from last file and move backwards
249 for( size_t n = tmp_flist.size() - 1; n != static_cast<size_t>( -1 ); --n )
250 {
252
253 try
254 {
255 // clang-format off
256 #ifdef XWCTEST_LOGMAP_LATFM_BADALL1
257 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
258 #endif
259 // clang-format on
260
261 sfn.fullName( tmp_flist[n] );
262 }
263 catch( ... )
264 {
265 std::throw_with_nested( xwcException( "parsing filename" ) );
266 }
267
268 if( !sfn.valid() ) // on any other errors we assume it's not a valid log file and just go around
269 {
270 continue;
271 }
272
273 if( sfn.timestamp() <= prevts )
274 {
275 prevLogFound = true;
276 prevLogSubDir = subdir;
277 prevLogFile_n = n;
278
279 std::cerr << "found previous log: " << tmp_flist[n] << '\n';
280 break;
281 }
282 } // iteration over tmp_flist
283
284 if( !prevLogFound )
285 {
286 mx_error_check( subdir.subDay() );
287 }
288 }
289
290 if( !prevLogFound )
291 {
292 return mx::error_t::noerror; // this is not an error...yet. one must check the map to see if 0 files found.
293 }
294
295 subdir = lastFile.subDir( &errc );
296 mx_error_check_code( errc );
297
298 ndays = 0;
299
300 while( follLogFound == false && ndays < m_searchDaySpan )
301 {
302 try
303 {
304 // clang-format off
305 #ifdef XWCTEST_LOGMAP_LATFM_BADALL2
306 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
307 #endif
308 // clang-format on
309
310 ++ndays;
311
312 std::vector<std::string> tmp_flist;
313
314 isdir = mx::ioutils::dir_exists_is( basedir + subdir.path(), errc );
315
316 if( errc != mx::error_t::noerror )
317 {
318 return mx::error_report<verboseT>( errc, "error from std::filesystem" );
319 }
320
321 if( !isdir ) // this subdir doesn't exist so go around
322 {
323 mx_error_check( subdir.addDay() );
324 continue;
325 }
326
327 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
328
329 if( tmp_flist.size() == 0 ) // this subdir has no files so go ahead
330 {
331 mx_error_check( subdir.addDay() );
332 continue;
333 }
334
335 // Start from first file and move forward
336 for( size_t n = 0; n < tmp_flist.size(); ++n )
337 {
339
340 sfn.fullName( tmp_flist[n] );
341
342 if( !sfn.valid() ) // any other errors just means it's not a standard file
343 {
344 continue;
345 }
346
347 if( sfn.timestamp() >= follts )
348 {
349 follLogFound = true;
350 follLogSubDir = subdir;
351 follLogFile_n = n;
352 break;
353 }
354
355 } // iteration over tmp_flist
356
357 if( !follLogFound )
358 {
359 mx_error_check( subdir.addDay() );
360 }
361 }
362 catch( ... )
363 {
364 std::throw_with_nested( xwcException( "parsing filename" ) );
365 }
366 }
367
368 // In this case we use the last log available and hope for the best
369 if( !follLogFound )
370 {
371 follLogSubDir = lastFile.subDir( &errc );
372 mx_error_check_code( errc );
373
374 DEBUG_CRUMB("checking for: " + basedir + follLogSubDir.path());
375
376 bool exists = mx::ioutils::dir_exists_is(basedir + follLogSubDir.path(), errc);
377
378 int n =0;
379 while(!exists && n < m_searchDaySpan)
380 {
381 follLogSubDir.subDay();
382
383 DEBUG_CRUMB("checking for: " + basedir + follLogSubDir.path());
384
385 exists = mx::ioutils::dir_exists_is(basedir + follLogSubDir.path(), errc);
386 ++n;
387 }
388
389 follLogFile_n = static_cast<size_t>( -1 );
390 }
391
392 if( prevLogSubDir == follLogSubDir ) // special case, probably most common
393 {
394 DEBUG_CRUMB("prevLogSubDir == follLogSubDir");
395
396 try
397 {
398 #ifdef XWCTEST_LOGMAP_LATFM_BADALL3
399 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
400 #endif
401 // clang-format on
402
403 subdir = prevLogSubDir;
404
405 std::vector<std::string> tmp_flist;
406
407 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
408
409 if( follLogFile_n == static_cast<size_t>( -1 ) )
410 {
411 follLogFile_n = tmp_flist.size();
412 }
413 else
414 {
415 ++follLogFile_n;
416 if( follLogFile_n > tmp_flist.size() )
417 {
418 return mx::error_report<verboseT>( mx::error_t::sizeerr,
419 "miscounted the number of files somewhere" );
420 }
421 }
422
423 mx_error_check( addFileListToFileMap( dev, tmp_flist, prevLogFile_n, follLogFile_n ) );
424 }
425 catch( ... )
426 {
427 std::throw_with_nested( xwcException( "adding file list to map" ) );
428 }
429 }
430 else
431 {
432 std::cerr << "prevLogSubDir != follLogSubDir\n";
433 try
434 {
435 // clang-format off
436 #ifdef XWCTEST_LOGMAP_LATFM_XWCE4
437 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
438 #endif
439
440 #ifdef XWCTEST_LOGMAP_LATFM_BADALL4
441 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
442 #endif
443 // clang-format on
444
445 subdir = prevLogSubDir;
446
447 std::vector<std::string> tmp_flist;
448
449 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
450
451 mx_error_check( addFileListToFileMap( dev, tmp_flist, prevLogFile_n, tmp_flist.size() ) );
452 }
453 catch( ... )
454 {
455 std::throw_with_nested( xwcException( "adding file list to map" ) );
456 }
457
458 mx_error_check( subdir.addDay() );
459
460 while( subdir < follLogSubDir )
461 {
462 try
463 {
464 // clang-format off
465 #ifdef XWCTEST_LOGMAP_LATFM_XWCE5
466 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
467 #endif
468
469 #ifdef XWCTEST_LOGMAP_LATFM_BADALL5
470 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
471 #endif
472 // clang-format on
473
474 if( !std::filesystem::exists( basedir + subdir.path() ) )
475 {
476 mx_error_check( subdir.addDay() );
477 continue;
478 }
479
480 std::vector<std::string> tmp_flist;
481
482 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
483
484 mx_error_check( addFileListToFileMap( dev, tmp_flist, 0, tmp_flist.size() ) );
485
486 mx_error_check( subdir.addDay() );
487 }
488 catch( ... )
489 {
490 std::throw_with_nested( xwcException( "adding file list to map" ) );
491 }
492 }
493
494 try
495 {
496 // clang-format off
497 #ifdef XWCTEST_LOGMAP_LATFM_XWCE6
498 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
499 #endif
500
501 #ifdef XWCTEST_LOGMAP_LATFM_BADALL6
502 throw xwcException("std::bad_alloc"); // LCOV_EXCL_LINE
503 #endif
504 // clang-format on
505
506 std::vector<std::string> tmp_flist;
507
508 /*mx::error_t errc = mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext );
509 if(errc != mx::error_t::dirnotfound)
510 {
511 return mx::error_report<verboseT>(errc);
512 }*/
513
514 mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
515
516
517 if(errc == mx::error_t::noerror)
518 {
519
520 if( follLogFile_n == static_cast<size_t>( -1 ) )
521 {
522 follLogFile_n = tmp_flist.size();
523 }
524 else
525 {
526 ++follLogFile_n;
527 if( follLogFile_n > tmp_flist.size() )
528 {
529 return mx::error_report<verboseT>( mx::error_t::sizeerr,
530 "miscounted the number of files somewhere" );
531 }
532 }
533
534 mx_error_check( addFileListToFileMap( dev, tmp_flist, 0, follLogFile_n ) );
535 }
536 }
537 catch( ... )
538 {
539 std::throw_with_nested( xwcException( "adding file list to map" ) );
540 }
541 }
542
543 return mx::error_t::noerror;
544}
545
546template <class verboseT>
547int logMap<verboseT>::getPriorLog( char *&logBefore,
548 const std::string &appName,
549 const flatlogs::eventCodeT &ev,
550 const flatlogs::timespecX &ts,
551 char *hint )
552{
554
555 DEBUG_CRUMB("");
556
557 if( m_appToFileMap[appName].size() == 0 )
558 {
559 std::cerr << __FILE__ << " " << __LINE__ << " getPriorLog empty map\n";
560 return -1;
561 }
562
563 DEBUG_CRUMB("");
564
565 logInMemory &lim = m_appToBufferMap[appName];
566
568 et.time_s += 30;
569 if( lim.m_startTime > ts || et < ts )
570 {
571 DEBUG_CRUMB("");
572
573 if( loadFiles( appName, ts ) < 0 )
574 {
575 std::cerr << __FILE__ << " " << __LINE__ << " error returned from loadfiles\n";
576 return -1;
577 }
578 }
579
580 char *buffer, *priorBuffer;
581
582 if( hint )
583 {
584 if( flatlogs::logHeader::timespec( hint ) <= ts )
585 {
586 buffer = hint;
587 }
588 else
589 {
590 buffer = lim.m_memory.data();
591 }
592 }
593 else
594 {
595 buffer = lim.m_memory.data();
596 }
597
598 priorBuffer = buffer;
599 evL = flatlogs::logHeader::eventCode( buffer );
600
601 while( evL != ev )
602 {
603 priorBuffer = buffer;
604 buffer += flatlogs::logHeader::totalSize( buffer );
605 if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
606 break;
607 evL = flatlogs::logHeader::eventCode( buffer );
608 }
609
610 if( evL != ev )
611 {
612 std::cerr << __FILE__ << " " << __LINE__ << " Event code not found.\n";
613 return -1;
614 }
615
616 if( flatlogs::logHeader::timespec( buffer ) < ts )
617 {
618 while( flatlogs::logHeader::timespec( buffer ) < ts ) // Loop until buffer is after the timestamp we want
619 {
620 if( buffer > lim.m_memory.data() + lim.m_memory.size() )
621 {
622 std::cerr << __FILE__ << " " << __LINE__
623 << " attempt to read too mach data, possible log corruption.\n";
624 return -1;
625 }
626
627 if( buffer == lim.m_memory.data() + lim.m_memory.size() )
628 {
629 std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName
630 << " -- need to load more data.\n";
631 // Proper action here is to load the next file if possible...
632 return 1;
633 }
634
635 priorBuffer = buffer;
636
637 buffer += flatlogs::logHeader::totalSize( buffer );
638
639 evL = flatlogs::logHeader::eventCode( buffer );
640
641 while( evL != ev ) // Find the next log with the event code we want.
642 {
643 if( buffer > lim.m_memory.data() + lim.m_memory.size() )
644 {
645 std::cerr << __FILE__ << " " << __LINE__
646 << " attempt to read too mach data, possible log corruption.\n";
647 return -1;
648 }
649
650 if( buffer == lim.m_memory.data() + lim.m_memory.size() )
651 {
652 std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName
653 << " -- need to load more data.\n";
654 // Proper action here is to load the next file if possible...
655 return 1;
656 }
657
658 buffer += flatlogs::logHeader::totalSize( buffer );
659 evL = flatlogs::logHeader::eventCode( buffer );
660 }
661 }
662 }
663
664 logBefore = priorBuffer;
665
666 return 0;
667} // getPriorLog
668
669template <class verboseT>
670int logMap<verboseT>::getNextLog( char *&logAfter, char *logCurrent, const std::string &appName )
671{
672 flatlogs::eventCodeT ev, evL;
673
674 logInMemory &lim = m_appToBufferMap[appName];
675
676 char *buffer;
677
678 ev = flatlogs::logHeader::eventCode( logCurrent );
679
680 buffer = logCurrent;
681
682 buffer += flatlogs::logHeader::totalSize( buffer );
683 if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
684 {
685 std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName
686 << " -- need to load more data\n";
687 // propoer action is to load the next file if possible.
688 return 1;
689 }
690
691 evL = flatlogs::logHeader::eventCode( buffer );
692
693 while( evL != ev )
694 {
695 buffer += flatlogs::logHeader::totalSize( buffer );
696 if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
697 {
698 std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName
699 << "-- need to load more data\n";
700 // propoer action is to load the next file if possible.
701 return 1;
702 }
703 evL = flatlogs::logHeader::eventCode( buffer );
704 }
705
706 if( evL != ev )
707 {
708 std::cerr << "Event code not found.\n";
709 return -1;
710 }
711
712 logAfter = buffer;
713
714 return 0;
715}
716
717template <class verboseT>
718int logMap<verboseT>::loadFiles( const std::string &appName, const flatlogs::timespecX &startTime )
719{
720 if( m_appToFileMap[appName].size() == 0 )
721 {
722 std::cerr << "*************************************\n\n";
723 std::cerr << "No files for " << appName << "\n";
724 std::cerr << "*************************************\n\n";
725 return -1;
726 }
727
728#ifdef DEBUG
729 std::cerr << __FILE__ << " " << __LINE__ << "\n";
730#endif
731
732 // First check if already loaded files cover this time
733 if( m_appToBufferMap[appName].m_memory.size() > 0 )
734 {
735 if( m_appToBufferMap[appName].m_startTime <= startTime && m_appToBufferMap[appName].m_endTime >= startTime )
736 {
737 std::cerr << "good!\n";
738 return 0;
739 }
740
741#ifdef DEBUG
742 std::cerr << __FILE__ << " " << __LINE__ << "\n";
743#endif
744
745 if( m_appToBufferMap[appName].m_startTime > startTime ) // Files don't go back far enough
746 {
747#ifdef DEBUG
748 std::cerr << __FILE__ << " " << __LINE__ << "\n";
749#endif
750
751 auto last = m_appToFileMap[appName].begin();
752 while( last->timestamp() < m_appToBufferMap[appName].m_startTime )
753 {
754 ++last;
755 if( last == m_appToFileMap[appName].end() )
756 break;
757 }
758 // Now last is the last file to open in the for loop sense.
759 auto first = last;
760
761 while( first->timestamp() > startTime )
762 {
763 --first;
764 if( first == m_appToFileMap[appName].begin() )
765 break;
766 }
767
768 // Now open each of these files, in reverse
769 std::cerr << "open earlier files!\n";
770 --last;
771 --first;
772 for( auto it = last; it != first; --it )
773 {
774 m_appToBufferMap[appName].loadFile( *it );
775 }
776
777 return 0;
778 }
779 else
780 {
781 auto first = m_appToFileMap[appName].end();
782 --first;
783
784 while( first->timestamp() > m_appToBufferMap[appName].m_endTime )
785 {
786 --first;
787 if( first == m_appToFileMap[appName].begin() )
788 break;
789 }
790 ++first;
791 auto last = first;
792 while( last->timestamp() < startTime )
793 {
794 ++last;
795 if( last == m_appToFileMap[appName].end() )
796 break;
797 }
798
799 // Now open each of these files
800 std::cerr << "open later file for " << appName << "!\n";
801 for( auto it = first; it != last; ++it )
802 {
803 m_appToBufferMap[appName].loadFile( *it );
804 }
805 return 0;
806 }
807 }
808
809#ifdef DEBUG
810 std::cerr << __FILE__ << " " << __LINE__ << "\n";
811#endif
812
813 auto before = m_appToFileMap[appName].begin();
814
815 for( ; before != m_appToFileMap[appName].end(); ++before )
816 {
817 if( !( before->timestamp() < startTime ) )
818 {
819 break;
820 }
821 }
822
823#ifdef debug
824 std::cerr << __FILE__ << " " << __LINE__ << "\n";
825#endif
826
827 if( before == m_appToFileMap[appName].begin() )
828 {
829 std::cerr << "No files in range for " << appName << "\n";
830 }
831 --before;
832
833#ifdef DEBUG
834 std::cerr << __FILE__ << " " << __LINE__ << "\n";
835#endif
836
837 m_appToBufferMap.emplace( std::pair<std::string, logInMemory>( appName, logInMemory() ) );
838
839#ifdef DEBUG
840 std::cerr << __FILE__ << " " << __LINE__ << "\n";
841#endif
842
843 m_appToBufferMap[appName].loadFile( *before );
844 if( ++before != m_appToFileMap[appName].end() )
845 {
846 m_appToBufferMap[appName].loadFile( *before );
847 }
848
849#ifdef DEBUG
850 std::cerr << __FILE__ << " " << __LINE__ << "\n";
851#endif
852
853 return 0;
854}
855
856#ifdef XWCTEST_NAMESPACE
857} // namespace XWCTEST_NAMESPACE
858#endif
859
860extern template class logMap<XWC_DEFAULT_VERBOSITY>;
861
862} // namespace logger
863} // namespace MagAOX
864
865#endif // logger_logMap_hpp
Organize and analyze the name of a standard file name.
const stdSubDir< verboseT > & subDir(mx::error_t *errc=nullptr) const
Get the current value of m_subDir.
const std::string & appName(mx::error_t *errc=nullptr) const
Get the current value of m_appName.
mx::error_t fullName(const std::string &fullName)
Sets the full name.
flatlogs::timespecX timestamp(mx::error_t *errc=nullptr) const
Get the current value of m_valid.
bool valid() const
Get the current value of.
Manage a standard subdirectory.
Definition stdSubDir.hpp:36
mx::error_t path(const std::string &subdir)
Set the subdirectory.
mx::error_t subDay()
Subtract a day from this subdirectory.
mx::error_t addDay()
Add a day to this subdirectory.
Augments an exception with the source file and line.
Flatlogs single include file.
#define XWC_DEFAULT_VERBOSITY
Definition defaults.hpp:53
virtual const char * what() const noexcept
Get the what string.
uint16_t eventCodeT
The type of an event code (16-bit unsigned int).
Definition logDefs.hpp:40
static int eventCode(bufferPtrT &logBuffer, const eventCodeT &ec)
Set the event code of a log entry.
static size_t totalSize(bufferPtrT &logBuffer)
Get the total size of the log entry, including the message buffer.
std::shared_ptr< char > bufferPtrT
The log entry buffer smart pointer.
Definition logHeader.hpp:58
static int timespec(bufferPtrT &logBuffer, const timespecX &ts)
Set the timespec of a log entry.
#define DEBUG_CRUMB(msg)
Definition logMap.hpp:26
Definition dm.hpp:19
Structure to hold a log file in memory, tracking when a new file needs to be opened.
Definition logMap.hpp:41
flatlogs::timespecX m_startTime
Definition logMap.hpp:46
XWC_DEFAULT_VERBOSITY verboseT
Definition logMap.hpp:42
std::vector< char > m_memory
The buffer holding the log data.
Definition logMap.hpp:44
flatlogs::timespecX m_endTime
Definition logMap.hpp:47
Map of log entries by application name, mapping both to files and to loaded buffers.
Definition logMap.hpp:55
file::stdSubDir< verboseT > stdSubDirT
Definition logMap.hpp:57
file::stdFileName< verboseT > stdFileNameT
Definition logMap.hpp:58
appToBufferMapT m_appToBufferMap
Definition logMap.hpp:70
appToFileMapT m_appToFileMap
Definition logMap.hpp:68
std::map< std::string, std::set< stdFileNameT, file::compStdFileName< stdFileNameT > > > appToFileMapT
The app-name to file-name map type, for sorting the input files by application.
Definition logMap.hpp:61
int getNearestLogs(flatlogs::bufferPtrT &logBefore, flatlogs::bufferPtrT &logAfter, const std::string &appName)
std::map< std::string, logInMemory > appToBufferMapT
The app-name to buffer map type, for looking up the currently loaded logs for a given app.
Definition logMap.hpp:64
A fixed-width timespec structure.
Definition timespecX.hpp:35
secT time_s
Time since the Unix epoch.
Definition timespecX.hpp:36
#define XWCTEST_NAMESPACE