Commit 68b77d7f authored by Nate Weibley's avatar Nate Weibley

Improve log gap handling algorithm efficiency

parent 51ddffa0
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <QUrl> #include <QUrl>
#define kTimeOutMilliseconds 500 #define kTimeOutMilliseconds 500
#define kGUIRateMilliseconds 17
QGC_LOGGING_CATEGORY(LogDownloadLog, "LogDownloadLog") QGC_LOGGING_CATEGORY(LogDownloadLog, "LogDownloadLog")
...@@ -275,33 +276,53 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui ...@@ -275,33 +276,53 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui
return; return;
} }
bool result = false; bool result = false;
//-- Find offset table entry
uint o_index = ofs / MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN; if(ofs <= _downloadData->entry->size()) {
if(o_index <= (uint)_downloadData->offsets.count()) { // Check for a gap
_downloadData->offsets[o_index] = count; qint64 pos = _downloadData->file.pos();
if (pos != ofs) {
// Check for a gap collision
if (_downloadData->gaps.contains(ofs)) {
// The gap is being filled. Shrink it
const int32_t gap = _downloadData->gaps.take(ofs) - count;
if (gap > 0) {
_downloadData->gaps[ofs+count] = qMax(static_cast<uint32_t>(gap), _downloadData->gaps.value(ofs+count, 0));
}
} else if (pos < ofs) {
// Mind the gap
uint32_t gap = ofs - pos;
_downloadData->gaps[pos] = gap;
}
// Seek to correct position
if (!_downloadData->file.seek(ofs)) {
qWarning() << "Error while seeking log file offset";
return;
}
}
//-- Write chunk to file //-- Write chunk to file
if(_downloadData->file.seek(ofs)) { if(_downloadData->file.write((const char*)data, count)) {
if(_downloadData->file.write((const char*)data, count)) { _downloadData->written += count;
_downloadData->written += count; if (_downloadData->elapsed.elapsed() >= kGUIRateMilliseconds) {
//-- Update status //-- Update status
QString comma_value = kLocale.toString(_downloadData->written); QString comma_value = kLocale.toString(_downloadData->written);
_downloadData->entry->setStatus(comma_value); _downloadData->entry->setStatus(comma_value);
result = true; _downloadData->elapsed.start();
//-- reset retries }
_retries = 0; result = true;
//-- Reset timer //-- reset retries
_timer.start(kTimeOutMilliseconds); _retries = 0;
//-- Do we have it all? //-- Reset timer
if(_logComplete()) { _timer.start(kTimeOutMilliseconds);
_downloadData->entry->setStatus(QString("Downloaded")); //-- Do we have it all?
//-- Check for more if(_logComplete()) {
_receivedAllData(); _downloadData->entry->setStatus(QString("Downloaded"));
} //-- Check for more
} else { _receivedAllData();
qWarning() << "Error while writing log file chunk";
} }
} else { } else {
qWarning() << "Error while seeking log file offset"; qWarning() << "Error while writing log file chunk";
} }
} else { } else {
qWarning() << "Received log offset greater than expected"; qWarning() << "Received log offset greater than expected";
...@@ -315,14 +336,8 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui ...@@ -315,14 +336,8 @@ LogDownloadController::_logData(UASInterface* uas, uint32_t ofs, uint16_t id, ui
bool bool
LogDownloadController::_logComplete() LogDownloadController::_logComplete()
{ {
//-- Iterate entries and look for a gap return _downloadData->file.pos() == _downloadData->entry->size() &&
int num_ofs = _downloadData->offsets.count(); _downloadData->gaps.count() == 0;
for(int i = 0; i < num_ofs; i++) {
if(_downloadData->offsets[i] == 0) {
return false;
}
}
return true;
} }
//---------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
...@@ -344,42 +359,32 @@ LogDownloadController::_receivedAllData() ...@@ -344,42 +359,32 @@ LogDownloadController::_receivedAllData()
void void
LogDownloadController::_findMissingData() LogDownloadController::_findMissingData()
{ {
int start = -1; if (_logComplete()) {
int end = -1; _receivedAllData();
int num_ofs = _downloadData->offsets.count(); return;
//-- Iterate offsets and look for a gap
for(int i = 0; i < num_ofs; i++) {
if(_downloadData->offsets[i] == 0) {
if(start < 0)
start = i;
else
end = i;
} else {
if(start >= 0) {
break;
}
}
} }
//-- Is there something missing?
if(start >= 0) { if(_retries++ > 2) {
//-- Have we tried too many times? _downloadData->entry->setStatus(QString("Timed Out"));
if(_retries++ > 2) { //-- Give up
_downloadData->entry->setStatus(QString("Timed Out")); qWarning() << "Too many errors retreiving log data. Giving up.";
//-- Give up _receivedAllData();
qWarning() << "Too many errors retreiving log data. Giving up."; return;
_receivedAllData(); }
return;
} const qint64 pos = _downloadData->file.pos(),
//-- Is it a sequence or just one entry? size = _downloadData->entry->size();
if(end < 0) { if (!_downloadData->gaps.isEmpty()) {
end = start; const uint32_t start = _downloadData->gaps.firstKey();
} const uint32_t count = _downloadData->gaps.value(start);
//-- Request these log chunks again //-- Request these log chunks again
_requestLogData( _requestLogData(_downloadData->ID, start, count);
_downloadData->ID, } else if (pos != size) {
(uint32_t)(start * MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN), // Request where we left off
(uint32_t)((end - start + 1) * MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN)); _requestLogData(_downloadData->ID, pos, size - pos);
} else { } else {
qWarning() << "Apparently we're missing data but can't figure out what. Giving up.";
_receivedAllData(); _receivedAllData();
} }
} }
...@@ -534,11 +539,7 @@ LogDownloadController::_prepareLogDownload() ...@@ -534,11 +539,7 @@ LogDownloadController::_prepareLogDownload()
if(!_downloadData->file.resize(entry->size())) { if(!_downloadData->file.resize(entry->size())) {
qWarning() << "Failed to allocate space for log file:" << _downloadData->filename; qWarning() << "Failed to allocate space for log file:" << _downloadData->filename;
} else { } else {
//-- Prepare Offset Table _downloadData->elapsed.start();
uint o_count = (uint)ceil(entry->size() / (double)MAVLINK_MSG_LOG_DATA_FIELD_DATA_LEN);
for(uint i = 0; i < o_count; i++) {
_downloadData->offsets.append(0);
}
result = true; result = true;
} }
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <QTimer> #include <QTimer>
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QLocale> #include <QLocale>
#include <QElapsedTimer>
#include <memory> #include <memory>
...@@ -39,7 +40,7 @@ class MultiVehicleManager; ...@@ -39,7 +40,7 @@ class MultiVehicleManager;
class UASInterface; class UASInterface;
class Vehicle; class Vehicle;
class QGCLogEntry; class QGCLogEntry;
class LogDownloadData; struct LogDownloadData;
Q_DECLARE_LOGGING_CATEGORY(LogDownloadLog) Q_DECLARE_LOGGING_CATEGORY(LogDownloadLog)
...@@ -122,16 +123,15 @@ private: ...@@ -122,16 +123,15 @@ private:
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class LogDownloadData { struct LogDownloadData {
public:
LogDownloadData(QGCLogEntry* entry); LogDownloadData(QGCLogEntry* entry);
QList<uint> offsets; QMap<uint32_t, uint32_t> gaps;
QFile file; QFile file;
QString filename; QString filename;
uint ID; uint ID;
QTimer processDataTimer; QGCLogEntry* entry;
QGCLogEntry* entry; uint written;
uint written; QElapsedTimer elapsed;
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment