API
 
Loading...
Searching...
No Matches
logMap.cpp
Go to the documentation of this file.
1/** \file logMap.cpp
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 */
8
9#include "logMap.hpp"
10
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <unistd.h>
14
15using namespace flatlogs;
16
17namespace MagAOX
18{
19namespace logger
20{
21
23{
24 int fd = open(lfn.fullName().c_str(), O_RDONLY );
25
26 off_t fsz = mx::ioutils::fileSize(fd);
27
28 std::vector<char> memory(fsz);
29
30 ssize_t nrd = read(fd, memory.data(), memory.size());
31
32 close(fd);
33
34 if(nrd != fsz)
35 {
36 std::cerr << __FILE__ << " " << __LINE__ << " logInMemory::loadFile(" << lfn.fullName() << ") did not read all bytes\n";
37 return -1;
38 }
39
40 flatlogs::timespecX startTime = logHeader::timespec(memory.data());
41
42 size_t st=0;
43 size_t ed = logHeader::totalSize(memory.data());
44 st = ed;
45
46 while(st < memory.size())
47 {
48 ed = logHeader::totalSize(memory.data()+st);
49 st = st + ed;
50 }
51
52 if(st != memory.size())
53 {
54 std::cerr << __FILE__ << " " << __LINE__ << " Possibly corrupt logfile.\n";
55 return -1;
56 }
57
58 st -= ed;
59
60 flatlogs::timespecX endTime = logHeader::timespec(memory.data()+st);
61
62 if(m_memory.size() == 0)
63 {
64 m_memory.swap(memory);
65 m_startTime = startTime;
66 m_endTime = endTime;
67
68 std::string timestamp;
69 timespec ts{ endTime.time_s, endTime.time_ns};
70 mx::sys::timeStamp(timestamp, ts);
71
72 #ifdef DEBUG
73 std::cerr << __FILE__ << " " << __LINE__ << " loading: " << lfn.fullName() << " " << timestamp << "\n";
74 #endif
75
76 return 0;
77 }
78
79 if(startTime < m_startTime)
80 {
81
82 if(endTime >= m_startTime)
83 {
84 std::cerr << __FILE__ << " " << __LINE__ << " overlapping log files!\n";
85 return -1;
86 }
87
88 m_memory.insert(m_memory.begin(), memory.begin(), memory.end());
89 m_startTime = startTime;
90 std::cerr << __FILE__ << " " << __LINE__ << " added before!\n";
91 return 0;
92 }
93
94 if(startTime > m_endTime)
95 {
96 #ifdef DEBUG
97 std::cerr << __FILE__ << " " << __LINE__ << " gonna append\n";
98 #endif
99
100 m_memory.insert(m_memory.end(), memory.begin(), memory.end());
101 m_endTime = endTime;
102
103 #ifdef DEBUG
104 std::cerr << __FILE__ << " " << __LINE__ << " added after!\n";
105 #endif
106
107 return 0;
108 }
109
110 std::cerr << __FILE__ << " " << __LINE__ << " Need to implement insert in the middle!\n";
111 std::cerr << m_startTime.time_s << " " << m_startTime.time_ns << "\n";
112 std::cerr << startTime.time_s << " " << startTime.time_ns << "\n";
113
114 return -1;
115}
116
117int logMap::loadAppToFileMap( const std::string & dir,
118 const std::string & ext
119 )
120{
121 std::vector<std::string> flist = mx::ioutils::getFileNames(dir, "", "", ext);
122
123 for(size_t n=0;n<flist.size(); ++n)
124 {
125 //std::cerr << "loading: " << flist[n] << "\n";
126
127 logFileName lfn(flist[n]);
128
129 m_appToFileMap[lfn.appName()].insert(lfn);
130 }
131
132 return 0;
133}
134
135int logMap::getPriorLog( char * &logBefore,
136 const std::string & appName,
137 const flatlogs::eventCodeT & ev,
138 const flatlogs::timespecX & ts,
139 char * hint
140 )
141{
143
144 #ifdef DEBUG
145 std::cerr << __FILE__ << " " << __LINE__ << "\n";
146 #endif
147
148 if(m_appToFileMap[appName].size() == 0)
149 {
150 std::cerr << __FILE__ << " " << __LINE__ << " getPriorLog empty map\n";
151 return -1;
152 }
153
154 #ifdef DEBUG
155 std::cerr << __FILE__ << " " << __LINE__ << "\n";
156 #endif
157
158 logInMemory & lim = m_appToBufferMap[appName];
159
161 et.time_s += 30;
162 if(lim.m_startTime > ts || et < ts)
163 {
164 #ifdef DEBUG
165 std::cerr << __FILE__ << " " << __LINE__ << "\n";
166 #endif
167
168 if(loadFiles(appName, ts) < 0)
169 {
170 std::cerr << __FILE__ << " " << __LINE__ << " error returned from loadfiles\n";
171 return -1;
172 }
173 }
174
175 char* buffer, *priorBuffer;
176
177 if(hint)
178 {
179 if(logHeader::timespec(hint) <= ts) buffer = hint;
180 else buffer = lim.m_memory.data();
181 }
182
183 else buffer = lim.m_memory.data();
184
185 priorBuffer = buffer;
186 evL = logHeader::eventCode(buffer);
187
188 while(evL != ev)
189 {
190 priorBuffer = buffer;
191 buffer += logHeader::totalSize(buffer);
192 if(buffer >=lim.m_memory.data() + lim.m_memory.size()) break;
193 evL = logHeader::eventCode(buffer);
194 }
195
196 if(evL != ev)
197 {
198 std::cerr << __FILE__ << " " << __LINE__ << " Event code not found.\n";
199 return -1;
200 }
201
202 if( logHeader::timespec(buffer) < ts )
203 {
204 while( logHeader::timespec(buffer) < ts ) //Loop until buffer is after the timestamp we want
205 {
206 if(buffer >lim.m_memory.data() +lim.m_memory.size())
207 {
208 std::cerr << __FILE__ << " " << __LINE__ << " attempt to read too mach data, possible log corruption.\n";
209 return -1;
210 }
211
212 if(buffer ==lim.m_memory.data() +lim.m_memory.size())
213 {
214 std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName << " -- need to load more data.\n";
215 //Proper action here is to load the next file if possible...
216 return 1;
217 }
218
219 priorBuffer = buffer;
220
221 buffer += logHeader::totalSize(buffer);
222
223 evL = logHeader::eventCode(buffer);
224
225 while(evL != ev) //Find the next log with the event code we want.
226 {
227 if(buffer >lim.m_memory.data() + lim.m_memory.size())
228 {
229 std::cerr << __FILE__ << " " << __LINE__ << " attempt to read too mach data, possible log corruption.\n";
230 return -1;
231 }
232
233 if(buffer ==lim.m_memory.data() + lim.m_memory.size())
234 {
235 std::cerr << __FILE__ << " " << __LINE__ << " did not find following log for " << appName << " -- need to load more data.\n";
236 //Proper action here is to load the next file if possible...
237 return 1;
238 }
239
240 buffer += logHeader::totalSize(buffer);
241 evL = logHeader::eventCode(buffer);
242 }
243 }
244
245 }
246
247 logBefore = priorBuffer;
248
249 return 0;
250}//getPriorLog
251
252int logMap::getNextLog( char * &logAfter,
253 char * logCurrent,
254 const std::string & appName
255 )
256{
257 flatlogs::eventCodeT ev, evL;
258
259 logInMemory & lim = m_appToBufferMap[appName];
260
261 char* buffer;
262
263 ev = logHeader::eventCode(logCurrent);
264
265 buffer = logCurrent;
266
267 buffer += logHeader::totalSize(buffer);
268 if(buffer >= lim.m_memory.data() + lim.m_memory.size())
269 {
270 std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName << " -- need to load more data\n";
271 //propoer action is to load the next file if possible.
272 return 1;
273 }
274
275 evL = logHeader::eventCode(buffer);
276
277 while(evL != ev)
278 {
279 buffer += logHeader::totalSize(buffer);
280 if(buffer >= lim.m_memory.data() + lim.m_memory.size())
281 {
282 std::cerr << __FILE__ << " " << __LINE__ << " Reached end of data for " << appName << "-- need to load more data\n";
283 //propoer action is to load the next file if possible.
284 return 1;
285 }
286 evL = logHeader::eventCode(buffer);
287 }
288
289 if(evL != ev)
290 {
291 std::cerr << "Event code not found.\n";
292 return -1;
293 }
294
295 logAfter = buffer;
296
297 return 0;
298}
299
300int logMap::loadFiles( const std::string & appName,
301 const flatlogs::timespecX & startTime
302 )
303{
304 if(m_appToFileMap[appName].size() == 0)
305 {
306 std::cerr << "*************************************\n\n";
307 std::cerr << "No files for " << appName << "\n";
308 std::cerr << "*************************************\n\n";
309 return -1;
310 }
311
312 #ifdef DEBUG
313 std::cerr << __FILE__ << " " << __LINE__ << "\n";
314 #endif
315
316 //First check if already loaded files cover this time
317 if(m_appToBufferMap[appName].m_memory.size() > 0)
318 {
319 if( m_appToBufferMap[appName].m_startTime <= startTime && m_appToBufferMap[appName].m_endTime >= startTime)
320 {
321 std::cerr << "good!\n";
322 return 0;
323 }
324
325 #ifdef DEBUG
326 std::cerr << __FILE__ << " " << __LINE__ << "\n";
327 #endif
328
329 if( m_appToBufferMap[appName].m_startTime > startTime ) // Files don't go back far enough
330 {
331 #ifdef DEBUG
332 std::cerr << __FILE__ << " " << __LINE__ << "\n";
333 #endif
334
335 auto last = m_appToFileMap[appName].begin();
336 while( last->timestamp() < m_appToBufferMap[appName].m_startTime)
337 {
338 ++last;
339 if(last == m_appToFileMap[appName].end()) break;
340 }
341 //Now last is the last file to open in the for loop sense.
342 auto first = last;
343
344 while( first->timestamp() > startTime)
345 {
346 --first;
347 if(first == m_appToFileMap[appName].begin()) break;
348 }
349
350 //Now open each of these files, in reverse
351 std::cerr << "open earlier files!\n";
352 --last;
353 --first;
354 for(auto it=last; it != first; --it)
355 {
356 m_appToBufferMap[appName].loadFile(*it);
357 }
358
359 return 0;
360 }
361 else
362 {
363 auto first = m_appToFileMap[appName].end();
364 --first;
365
366 while( first->timestamp() > m_appToBufferMap[appName].m_endTime)
367 {
368 --first;
369 if(first == m_appToFileMap[appName].begin()) break;
370 }
371 ++first;
372 auto last = first;
373 while( last->timestamp() < startTime)
374 {
375 ++last;
376 if(last == m_appToFileMap[appName].end()) break;
377 }
378
379 //Now open each of these files
380 std::cerr << "open later file for " << appName << "!\n";
381 for(auto it=first; it != last; ++it)
382 {
383 m_appToBufferMap[appName].loadFile(*it);
384 }
385 return 0;
386 }
387
388 }
389
390 #ifdef DEBUG
391 std::cerr << __FILE__ << " " << __LINE__ << "\n";
392 #endif
393
394 auto before = m_appToFileMap[appName].begin();
395
396 for(; before != m_appToFileMap[appName].end(); ++before)
397 {
398 if( !(before->timestamp() < startTime) )
399 {
400 break;
401 }
402 }
403
404 #ifdef debug
405 std::cerr << __FILE__ << " " << __LINE__ << "\n";
406 #endif
407
408 if(before == m_appToFileMap[appName].begin())
409 {
410 std::cerr << "No files in range for " << appName << "\n";
411 }
412 --before;
413
414 #ifdef DEBUG
415 std::cerr << __FILE__ << " " << __LINE__ << "\n";
416 #endif
417
418 m_appToBufferMap.emplace(std::pair<std::string, logInMemory>(appName, logInMemory()));
419
420 #ifdef DEBUG
421 std::cerr << __FILE__ << " " << __LINE__ << "\n";
422 #endif
423
424 m_appToBufferMap[appName].loadFile(*before);
425 if(++before != m_appToFileMap[appName].end())
426 {
427 m_appToBufferMap[appName].loadFile(*before);
428 }
429
430 #ifdef DEBUG
431 std::cerr << __FILE__ << " " << __LINE__ << "\n";
432 #endif
433
434 return 0;
435}
436
437} //namespace logger
438} //namespace MagAOX
Organize and analyze the name of a log or telemetry file.
int fullName(const std::string &fullName)
Sets the full name.
std::string appName() const
Get the current value of m_appName.
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.
static int timespec(bufferPtrT &logBuffer, const timespecX &ts)
Set the timespec of a log entry.
Declares and defines the logMap class and related classes.
Definition dm.hpp:24
Structure to hold a log file in memory, tracking when a new file needs to be opened.
Definition logMap.hpp:32
flatlogs::timespecX m_startTime
Definition logMap.hpp:35
int loadFile(logFileName const &lfn)
Definition logMap.cpp:22
std::vector< char > m_memory
The buffer holding the log.
Definition logMap.hpp:33
flatlogs::timespecX m_endTime
Definition logMap.hpp:36
int getPriorLog(char *&logBefore, const std::string &appName, const flatlogs::eventCodeT &ev, const flatlogs::timespecX &ts, char *hint=0)
Get the log for an event code which is the first prior to the supplied time.
Definition logMap.cpp:135
appToBufferMapT m_appToBufferMap
Definition logMap.hpp:53
int getNextLog(char *&logAfter, char *logCurrent, const std::string &appName)
Get the next log with the same event code which is after the supplied time.
Definition logMap.cpp:252
int loadFiles(const std::string &appName, const flatlogs::timespecX &startTime)
Definition logMap.cpp:300
int loadAppToFileMap(const std::string &dir, const std::string &ext)
Get log file names in a directory and distribute them into the map by app-name.
Definition logMap.cpp:117
appToFileMapT m_appToFileMap
Definition logMap.hpp:51
A fixed-width timespec structure.
Definition timespecX.hpp:35
nanosecT time_ns
Nanoseconds.
Definition timespecX.hpp:37
secT time_s
Time since the Unix epoch.
Definition timespecX.hpp:36