5 LogFile::LogFile(QObject
*parent
) :
12 m_useProvidedTimeStamp(false)
14 connect(&m_timer
, SIGNAL(timeout()), this, SLOT(timerFired()));
18 * Opens the logfile QIODevice and the underlying logfile. In case
19 * we want to save the logfile, we open in WriteOnly. In case we
20 * want to read the logfile, we open in ReadOnly.
22 bool LogFile::open(OpenMode mode
)
24 // start a timer for playback
26 if (m_file
.isOpen()) {
27 // We end up here when doing a replay, because the connection
28 // manager will also try to open the QIODevice, even though we just
29 // opened it after selecting the file, which happens before the
30 // connection manager call...
34 if (m_file
.open(mode
) == false) {
35 qDebug() << "Unable to open " << m_file
.fileName() << " for logging";
39 // TODO: Write a header at the beginng describing objects so that in future
40 // they can be read back if ID's change
42 // Must call parent function for QIODevice to pass calls to writeData
43 // We always open ReadWrite, because otherwise we will get tons of warnings
44 // during a logfile replay. Read nature is checked upon write ops below.
45 QIODevice::open(QIODevice::ReadWrite
);
54 if (m_timer
.isActive()) {
61 qint64
LogFile::writeData(const char *data
, qint64 dataSize
)
63 if (!m_file
.isWritable()) {
67 // If m_nextTimeStamp != -1 then use this timestamp instead of the timer
68 // This is used when saving logs from on-board logging
69 quint32 timeStamp
= m_useProvidedTimeStamp
? m_nextTimeStamp
: m_myTime
.elapsed();
71 m_file
.write((char *)&timeStamp
, sizeof(timeStamp
));
72 m_file
.write((char *)&dataSize
, sizeof(dataSize
));
74 qint64 written
= m_file
.write(data
, dataSize
);
76 emit
bytesWritten(written
);
82 qint64
LogFile::readData(char *data
, qint64 maxSize
)
84 QMutexLocker
locker(&m_mutex
);
85 qint64 toRead
= qMin(maxSize
, (qint64
)m_dataBuffer
.size());
87 memcpy(data
, m_dataBuffer
.data(), toRead
);
88 m_dataBuffer
.remove(0, toRead
);
92 qint64
LogFile::bytesAvailable() const
94 return m_dataBuffer
.size();
97 void LogFile::timerFired()
101 if (m_file
.bytesAvailable() > 4) {
103 time
= m_myTime
.elapsed();
105 // TODO: going back in time will be a problem
106 while ((m_lastPlayed
+ ((time
- m_timeOffset
) * m_playbackSpeed
) > m_lastTimeStamp
)) {
107 m_lastPlayed
+= ((time
- m_timeOffset
) * m_playbackSpeed
);
108 if (m_file
.bytesAvailable() < (qint64
)sizeof(dataSize
)) {
113 m_file
.read((char *)&dataSize
, sizeof(dataSize
));
115 if (dataSize
< 1 || dataSize
> (1024 * 1024)) {
116 qDebug() << "Error: Logfile corrupted! Unlikely packet size: " << dataSize
<< "\n";
121 if (m_file
.bytesAvailable() < dataSize
) {
127 m_dataBuffer
.append(m_file
.read(dataSize
));
132 if (m_file
.bytesAvailable() < (qint64
)sizeof(m_lastTimeStamp
)) {
137 int save
= m_lastTimeStamp
;
138 m_file
.read((char *)&m_lastTimeStamp
, sizeof(m_lastTimeStamp
));
139 // some validity checks
140 if (m_lastTimeStamp
< save
// logfile goes back in time
141 || (m_lastTimeStamp
- save
) > (60 * 60 * 1000)) { // gap of more than 60 minutes)
142 qDebug() << "Error: Logfile corrupted! Unlikely timestamp " << m_lastTimeStamp
<< " after " << save
<< "\n";
148 time
= m_myTime
.elapsed();
155 bool LogFile::startReplay()
157 m_dataBuffer
.clear();
161 m_file
.read((char *)&m_lastTimeStamp
, sizeof(m_lastTimeStamp
));
162 m_timer
.setInterval(10);
164 emit
replayStarted();
168 bool LogFile::stopReplay()
171 emit
replayFinished();
175 void LogFile::pauseReplay()
180 void LogFile::resumeReplay()
182 m_timeOffset
= m_myTime
.elapsed();