Line data Source code
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>
15 : using 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 :
29 : namespace MagAOX
30 : {
31 : namespace logger
32 : {
33 :
34 : #ifdef XWCTEST_NAMESPACE
35 : namespace XWCTEST_NAMESPACE
36 : {
37 : #endif
38 :
39 : /// Structure to hold a log file in memory, tracking when a new file needs to be opened.
40 : struct logInMemory
41 : {
42 : typedef XWC_DEFAULT_VERBOSITY verboseT;
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.
53 : template <class verboseT = XWC_DEFAULT_VERBOSITY>
54 : struct logMap
55 : {
56 :
57 : typedef file::stdSubDir<verboseT> stdSubDirT;
58 : typedef file::stdFileName<verboseT> stdFileNameT;
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 :
68 : appToFileMapT m_appToFileMap;
69 :
70 : appToBufferMapT m_appToBufferMap;
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 :
123 : template <class verboseT>
124 9 : mx::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 51 : for( size_t n = n0; n < nf; ++n )
146 : {
147 21 : file::stdFileName<verboseT> sfn( flist[n] );
148 :
149 21 : if( !sfn.valid() ) // this is just not a standard file name.
150 : {
151 0 : continue;
152 : }
153 :
154 21 : if( sfn.appName() != dev ) // this is just a different app
155 : {
156 0 : continue;
157 : }
158 :
159 21 : m_appToFileMap[dev].insert( sfn );
160 : }
161 :
162 9 : return mx::error_t::noerror;
163 : }
164 0 : catch( const xwcException &e )
165 : {
166 0 : std::throw_with_nested( xwcException( "adding file to map" ) );
167 : }
168 0 : catch( const std::bad_alloc &e )
169 : {
170 0 : std::throw_with_nested( xwcException( "adding file to map" ) );
171 : }
172 0 : catch( const std::exception &e )
173 : {
174 0 : return mx::error_report<verboseT>( mx::error_t::std_exception,
175 0 : std::string( "adding file to map:" ) + e.what() );
176 : }
177 : }
178 :
179 : template <class verboseT>
180 12 : mx::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 12 : bool isdir = mx::ioutils::dir_exists_is( dir, errc );
189 :
190 12 : mx_error_check_code( errc );
191 :
192 11 : if( !isdir )
193 : {
194 1 : 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 10 : flatlogs::timespecX prevts = firstFile.timestamp( &errc );
199 10 : mx_error_check_code( errc );
200 :
201 9 : prevts.time_s -= 60; // Move 60 seconds in future. This is a config setting
202 :
203 9 : flatlogs::timespecX follts = lastFile.timestamp( &errc );
204 9 : mx_error_check_code( errc );
205 :
206 8 : 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 8 : bool prevLogFound = false;
210 8 : file::stdSubDir prevLogSubDir;
211 8 : size_t prevLogFile_n = 0;
212 :
213 : // Coordinates of the following log, after it's found
214 8 : bool follLogFound = false;
215 8 : file::stdSubDir follLogSubDir;
216 : size_t follLogFile_n;
217 :
218 8 : std::string basedir = dir + '/' + dev + '/';
219 :
220 8 : file::stdSubDir subdir = firstFile.subDir( &errc );
221 8 : mx_error_check_code( errc );
222 :
223 8 : int ndays = 0;
224 :
225 622 : while( prevLogFound == false && ndays < m_searchDaySpan )
226 : {
227 307 : ++ndays;
228 :
229 307 : std::vector<std::string> tmp_flist;
230 :
231 307 : isdir = mx::ioutils::dir_exists_is( basedir + subdir.path(), errc );
232 307 : mx_error_check_code( errc );
233 :
234 307 : if( !isdir ) // this subdir doesn't exist so go around
235 : {
236 301 : mx_error_check( subdir.subDay() );
237 301 : continue;
238 301 : }
239 :
240 12 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
241 :
242 6 : if( tmp_flist.size() == 0 ) // this subdir has no files in it so go around
243 : {
244 0 : mx_error_check( subdir.subDay() );
245 0 : continue;
246 0 : }
247 :
248 : // Start from last file and move backwards
249 35 : for( size_t n = tmp_flist.size() - 1; n != static_cast<size_t>( -1 ); --n )
250 : {
251 17 : file::stdFileName<verboseT> sfn;
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 17 : sfn.fullName( tmp_flist[n] );
262 : }
263 0 : catch( ... )
264 : {
265 0 : std::throw_with_nested( xwcException( "parsing filename" ) );
266 : }
267 :
268 17 : if( !sfn.valid() ) // on any other errors we assume it's not a valid log file and just go around
269 : {
270 0 : continue;
271 : }
272 :
273 17 : if( sfn.timestamp() <= prevts )
274 : {
275 5 : prevLogFound = true;
276 5 : prevLogSubDir = subdir;
277 5 : prevLogFile_n = n;
278 :
279 5 : std::cerr << "found previous log: " << tmp_flist[n] << '\n';
280 5 : break;
281 : }
282 : } // iteration over tmp_flist
283 :
284 6 : if( !prevLogFound )
285 : {
286 1 : mx_error_check( subdir.subDay() );
287 : }
288 : }
289 :
290 8 : if( !prevLogFound )
291 : {
292 3 : 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 5 : subdir = lastFile.subDir( &errc );
296 5 : mx_error_check_code( errc );
297 :
298 5 : ndays = 0;
299 :
300 111 : 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 106 : ++ndays;
311 :
312 106 : std::vector<std::string> tmp_flist;
313 :
314 106 : isdir = mx::ioutils::dir_exists_is( basedir + subdir.path(), errc );
315 :
316 106 : if( errc != mx::error_t::noerror )
317 : {
318 0 : return mx::error_report<verboseT>( errc, "error from std::filesystem" );
319 : }
320 :
321 106 : if( !isdir ) // this subdir doesn't exist so go around
322 : {
323 100 : mx_error_check( subdir.addDay() );
324 100 : continue;
325 100 : }
326 :
327 12 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
328 :
329 6 : if( tmp_flist.size() == 0 ) // this subdir has no files so go ahead
330 : {
331 0 : mx_error_check( subdir.addDay() );
332 0 : continue;
333 0 : }
334 :
335 : // Start from first file and move forward
336 34 : for( size_t n = 0; n < tmp_flist.size(); ++n )
337 : {
338 16 : file::stdFileName<verboseT> sfn;
339 :
340 16 : sfn.fullName( tmp_flist[n] );
341 :
342 16 : if( !sfn.valid() ) // any other errors just means it's not a standard file
343 : {
344 0 : continue;
345 : }
346 :
347 16 : if( sfn.timestamp() >= follts )
348 : {
349 4 : follLogFound = true;
350 4 : follLogSubDir = subdir;
351 4 : follLogFile_n = n;
352 4 : break;
353 : }
354 :
355 : } // iteration over tmp_flist
356 :
357 6 : if( !follLogFound )
358 : {
359 2 : mx_error_check( subdir.addDay() );
360 : }
361 106 : }
362 0 : catch( ... )
363 : {
364 0 : 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 5 : if( !follLogFound )
370 : {
371 1 : follLogSubDir = lastFile.subDir( &errc );
372 1 : mx_error_check_code( errc );
373 :
374 1 : DEBUG_CRUMB("checking for: " + basedir + follLogSubDir.path());
375 :
376 1 : bool exists = mx::ioutils::dir_exists_is(basedir + follLogSubDir.path(), errc);
377 :
378 1 : int n =0;
379 1 : while(!exists && n < m_searchDaySpan)
380 : {
381 0 : follLogSubDir.subDay();
382 :
383 0 : DEBUG_CRUMB("checking for: " + basedir + follLogSubDir.path());
384 :
385 0 : exists = mx::ioutils::dir_exists_is(basedir + follLogSubDir.path(), errc);
386 0 : ++n;
387 : }
388 :
389 1 : follLogFile_n = static_cast<size_t>( -1 );
390 : }
391 :
392 5 : if( prevLogSubDir == follLogSubDir ) // special case, probably most common
393 : {
394 2 : 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 2 : subdir = prevLogSubDir;
404 :
405 2 : std::vector<std::string> tmp_flist;
406 :
407 4 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
408 :
409 2 : if( follLogFile_n == static_cast<size_t>( -1 ) )
410 : {
411 0 : follLogFile_n = tmp_flist.size();
412 : }
413 : else
414 : {
415 2 : ++follLogFile_n;
416 2 : if( follLogFile_n > tmp_flist.size() )
417 : {
418 0 : return mx::error_report<verboseT>( mx::error_t::sizeerr,
419 0 : "miscounted the number of files somewhere" );
420 : }
421 : }
422 :
423 2 : mx_error_check( addFileListToFileMap( dev, tmp_flist, prevLogFile_n, follLogFile_n ) );
424 2 : }
425 0 : catch( ... )
426 : {
427 0 : std::throw_with_nested( xwcException( "adding file list to map" ) );
428 : }
429 : }
430 : else
431 : {
432 3 : 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 3 : subdir = prevLogSubDir;
446 :
447 3 : std::vector<std::string> tmp_flist;
448 :
449 6 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
450 :
451 3 : mx_error_check( addFileListToFileMap( dev, tmp_flist, prevLogFile_n, tmp_flist.size() ) );
452 3 : }
453 0 : catch( ... )
454 : {
455 0 : std::throw_with_nested( xwcException( "adding file list to map" ) );
456 : }
457 :
458 3 : mx_error_check( subdir.addDay() );
459 :
460 8 : 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 5 : if( !std::filesystem::exists( basedir + subdir.path() ) )
475 : {
476 4 : mx_error_check( subdir.addDay() );
477 4 : continue;
478 4 : }
479 :
480 1 : std::vector<std::string> tmp_flist;
481 :
482 2 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
483 :
484 1 : mx_error_check( addFileListToFileMap( dev, tmp_flist, 0, tmp_flist.size() ) );
485 :
486 1 : mx_error_check( subdir.addDay() );
487 1 : }
488 0 : catch( ... )
489 : {
490 0 : 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 3 : 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 6 : mx_error_check( mx::ioutils::getFileNames( tmp_flist, basedir + subdir.path(), dev, "", ext ) );
515 :
516 :
517 3 : if(errc == mx::error_t::noerror)
518 : {
519 :
520 3 : if( follLogFile_n == static_cast<size_t>( -1 ) )
521 : {
522 1 : follLogFile_n = tmp_flist.size();
523 : }
524 : else
525 : {
526 2 : ++follLogFile_n;
527 2 : if( follLogFile_n > tmp_flist.size() )
528 : {
529 0 : return mx::error_report<verboseT>( mx::error_t::sizeerr,
530 0 : "miscounted the number of files somewhere" );
531 : }
532 : }
533 :
534 3 : mx_error_check( addFileListToFileMap( dev, tmp_flist, 0, follLogFile_n ) );
535 : }
536 3 : }
537 0 : catch( ... )
538 : {
539 0 : std::throw_with_nested( xwcException( "adding file list to map" ) );
540 : }
541 : }
542 :
543 5 : return mx::error_t::noerror;
544 8 : }
545 :
546 : template <class verboseT>
547 0 : int logMap<verboseT>::getPriorLog( char *&logBefore,
548 : const std::string &appName,
549 : const flatlogs::eventCodeT &ev,
550 : const flatlogs::timespecX &ts,
551 : char *hint )
552 : {
553 : flatlogs::eventCodeT evL;
554 :
555 0 : DEBUG_CRUMB("");
556 :
557 0 : if( m_appToFileMap[appName].size() == 0 )
558 : {
559 0 : std::cerr << __FILE__ << " " << __LINE__ << " getPriorLog empty map\n";
560 0 : return -1;
561 : }
562 :
563 0 : DEBUG_CRUMB("");
564 :
565 0 : logInMemory &lim = m_appToBufferMap[appName];
566 :
567 0 : flatlogs::timespecX et = lim.m_endTime;
568 0 : et.time_s += 30;
569 0 : if( lim.m_startTime > ts || et < ts )
570 : {
571 0 : DEBUG_CRUMB("");
572 :
573 0 : if( loadFiles( appName, ts ) < 0 )
574 : {
575 0 : std::cerr << __FILE__ << " " << __LINE__ << " error returned from loadfiles\n";
576 0 : return -1;
577 : }
578 : }
579 :
580 : char *buffer, *priorBuffer;
581 :
582 0 : if( hint )
583 : {
584 0 : if( flatlogs::logHeader::timespec( hint ) <= ts )
585 : {
586 0 : buffer = hint;
587 : }
588 : else
589 : {
590 0 : buffer = lim.m_memory.data();
591 : }
592 : }
593 : else
594 : {
595 0 : buffer = lim.m_memory.data();
596 : }
597 :
598 0 : priorBuffer = buffer;
599 0 : evL = flatlogs::logHeader::eventCode( buffer );
600 :
601 0 : while( evL != ev )
602 : {
603 0 : priorBuffer = buffer;
604 0 : buffer += flatlogs::logHeader::totalSize( buffer );
605 0 : if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
606 0 : break;
607 0 : evL = flatlogs::logHeader::eventCode( buffer );
608 : }
609 :
610 0 : if( evL != ev )
611 : {
612 0 : std::cerr << __FILE__ << " " << __LINE__ << " Event code not found.\n";
613 0 : return -1;
614 : }
615 :
616 0 : if( flatlogs::logHeader::timespec( buffer ) < ts )
617 : {
618 0 : while( flatlogs::logHeader::timespec( buffer ) < ts ) // Loop until buffer is after the timestamp we want
619 : {
620 0 : if( buffer > lim.m_memory.data() + lim.m_memory.size() )
621 : {
622 0 : std::cerr << __FILE__ << " " << __LINE__
623 0 : << " attempt to read too mach data, possible log corruption.\n";
624 0 : return -1;
625 : }
626 :
627 0 : if( buffer == lim.m_memory.data() + lim.m_memory.size() )
628 : {
629 0 : std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName
630 0 : << " -- need to load more data.\n";
631 : // Proper action here is to load the next file if possible...
632 0 : return 1;
633 : }
634 :
635 0 : priorBuffer = buffer;
636 :
637 0 : buffer += flatlogs::logHeader::totalSize( buffer );
638 :
639 0 : evL = flatlogs::logHeader::eventCode( buffer );
640 :
641 0 : while( evL != ev ) // Find the next log with the event code we want.
642 : {
643 0 : if( buffer > lim.m_memory.data() + lim.m_memory.size() )
644 : {
645 0 : std::cerr << __FILE__ << " " << __LINE__
646 0 : << " attempt to read too mach data, possible log corruption.\n";
647 0 : return -1;
648 : }
649 :
650 0 : if( buffer == lim.m_memory.data() + lim.m_memory.size() )
651 : {
652 0 : std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName
653 0 : << " -- need to load more data.\n";
654 : // Proper action here is to load the next file if possible...
655 0 : return 1;
656 : }
657 :
658 0 : buffer += flatlogs::logHeader::totalSize( buffer );
659 0 : evL = flatlogs::logHeader::eventCode( buffer );
660 : }
661 : }
662 : }
663 :
664 0 : logBefore = priorBuffer;
665 :
666 0 : return 0;
667 : } // getPriorLog
668 :
669 : template <class verboseT>
670 0 : int logMap<verboseT>::getNextLog( char *&logAfter, char *logCurrent, const std::string &appName )
671 : {
672 : flatlogs::eventCodeT ev, evL;
673 :
674 0 : logInMemory &lim = m_appToBufferMap[appName];
675 :
676 : char *buffer;
677 :
678 0 : ev = flatlogs::logHeader::eventCode( logCurrent );
679 :
680 0 : buffer = logCurrent;
681 :
682 0 : buffer += flatlogs::logHeader::totalSize( buffer );
683 0 : if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
684 : {
685 0 : std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName
686 0 : << " -- need to load more data\n";
687 : // propoer action is to load the next file if possible.
688 0 : return 1;
689 : }
690 :
691 0 : evL = flatlogs::logHeader::eventCode( buffer );
692 :
693 0 : while( evL != ev )
694 : {
695 0 : buffer += flatlogs::logHeader::totalSize( buffer );
696 0 : if( buffer >= lim.m_memory.data() + lim.m_memory.size() )
697 : {
698 0 : std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName
699 0 : << "-- need to load more data\n";
700 : // propoer action is to load the next file if possible.
701 0 : return 1;
702 : }
703 0 : evL = flatlogs::logHeader::eventCode( buffer );
704 : }
705 :
706 0 : if( evL != ev )
707 : {
708 0 : std::cerr << "Event code not found.\n";
709 0 : return -1;
710 : }
711 :
712 0 : logAfter = buffer;
713 :
714 0 : return 0;
715 : }
716 :
717 : template <class verboseT>
718 0 : int logMap<verboseT>::loadFiles( const std::string &appName, const flatlogs::timespecX &startTime )
719 : {
720 0 : if( m_appToFileMap[appName].size() == 0 )
721 : {
722 0 : std::cerr << "*************************************\n\n";
723 0 : std::cerr << "No files for " << appName << "\n";
724 0 : std::cerr << "*************************************\n\n";
725 0 : 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 0 : if( m_appToBufferMap[appName].m_memory.size() > 0 )
734 : {
735 0 : if( m_appToBufferMap[appName].m_startTime <= startTime && m_appToBufferMap[appName].m_endTime >= startTime )
736 : {
737 0 : std::cerr << "good!\n";
738 0 : return 0;
739 : }
740 :
741 : #ifdef DEBUG
742 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
743 : #endif
744 :
745 0 : 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 0 : auto last = m_appToFileMap[appName].begin();
752 0 : while( last->timestamp() < m_appToBufferMap[appName].m_startTime )
753 : {
754 0 : ++last;
755 0 : if( last == m_appToFileMap[appName].end() )
756 0 : break;
757 : }
758 : // Now last is the last file to open in the for loop sense.
759 0 : auto first = last;
760 :
761 0 : while( first->timestamp() > startTime )
762 : {
763 0 : --first;
764 0 : if( first == m_appToFileMap[appName].begin() )
765 0 : break;
766 : }
767 :
768 : // Now open each of these files, in reverse
769 0 : std::cerr << "open earlier files!\n";
770 0 : --last;
771 0 : --first;
772 0 : for( auto it = last; it != first; --it )
773 : {
774 0 : m_appToBufferMap[appName].loadFile( *it );
775 : }
776 :
777 0 : return 0;
778 : }
779 : else
780 : {
781 0 : auto first = m_appToFileMap[appName].end();
782 0 : --first;
783 :
784 0 : while( first->timestamp() > m_appToBufferMap[appName].m_endTime )
785 : {
786 0 : --first;
787 0 : if( first == m_appToFileMap[appName].begin() )
788 0 : break;
789 : }
790 0 : ++first;
791 0 : auto last = first;
792 0 : while( last->timestamp() < startTime )
793 : {
794 0 : ++last;
795 0 : if( last == m_appToFileMap[appName].end() )
796 0 : break;
797 : }
798 :
799 : // Now open each of these files
800 0 : std::cerr << "open later file for " << appName << "!\n";
801 0 : for( auto it = first; it != last; ++it )
802 : {
803 0 : m_appToBufferMap[appName].loadFile( *it );
804 : }
805 0 : return 0;
806 : }
807 : }
808 :
809 : #ifdef DEBUG
810 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
811 : #endif
812 :
813 0 : auto before = m_appToFileMap[appName].begin();
814 :
815 0 : for( ; before != m_appToFileMap[appName].end(); ++before )
816 : {
817 0 : if( !( before->timestamp() < startTime ) )
818 : {
819 0 : break;
820 : }
821 : }
822 :
823 : #ifdef debug
824 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
825 : #endif
826 :
827 0 : if( before == m_appToFileMap[appName].begin() )
828 : {
829 0 : std::cerr << "No files in range for " << appName << "\n";
830 : }
831 0 : --before;
832 :
833 : #ifdef DEBUG
834 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
835 : #endif
836 :
837 0 : m_appToBufferMap.emplace( std::pair<std::string, logInMemory>( appName, logInMemory() ) );
838 :
839 : #ifdef DEBUG
840 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
841 : #endif
842 :
843 0 : m_appToBufferMap[appName].loadFile( *before );
844 0 : if( ++before != m_appToFileMap[appName].end() )
845 : {
846 0 : m_appToBufferMap[appName].loadFile( *before );
847 : }
848 :
849 : #ifdef DEBUG
850 : std::cerr << __FILE__ << " " << __LINE__ << "\n";
851 : #endif
852 :
853 0 : return 0;
854 : }
855 :
856 : #ifdef XWCTEST_NAMESPACE
857 : } // namespace XWCTEST_NAMESPACE
858 : #endif
859 :
860 : extern template class logMap<XWC_DEFAULT_VERBOSITY>;
861 :
862 : } // namespace logger
863 : } // namespace MagAOX
864 :
865 : #endif // logger_logMap_hpp
|