refs #687, use hash to avoid unnecessary operations

* for bookings
* VATSIM file (plus check if cache really changed before writing)
* METARs
This commit is contained in:
Klaus Basan
2016-06-25 02:31:28 +02:00
parent 0253da8bf9
commit 0fca9c1f18
5 changed files with 73 additions and 22 deletions

View File

@@ -85,17 +85,33 @@ namespace BlackCore
void CThreadedReader::setInterval(int updatePeriodMs) void CThreadedReader::setInterval(int updatePeriodMs)
{ {
Q_ASSERT(this->m_updateTimer); Q_ASSERT(this->m_updateTimer);
bool s; QTimer::singleShot(0, this, [this, updatePeriodMs]
{
QWriteLocker wl(&this->m_lock);
if (updatePeriodMs < 1) if (updatePeriodMs < 1)
{ {
s = QMetaObject::invokeMethod(m_updateTimer, "stop"); this->m_updateTimer->stop();
} }
else else {
this->m_updateTimer->start(updatePeriodMs);
}
});
}
bool CThreadedReader::didContentChange(const QString &content, int startPosition)
{ {
s = QMetaObject::invokeMethod(m_updateTimer, "start", Q_ARG(int, updatePeriodMs)); uint oldHash = 0;
{
QReadLocker rl(&this->m_lock);
oldHash = this->m_contentHash;
} }
Q_ASSERT_X(s, Q_FUNC_INFO, "Failed invoke"); uint newHash = qHash(startPosition < 0 ? content : content.mid(startPosition));
Q_UNUSED(s); if (oldHash == newHash) { return false; }
{
QWriteLocker wl(&this->m_lock);
this->m_contentHash = newHash;
}
return true;
} }
void CThreadedReader::ps_toggleInterval() void CThreadedReader::ps_toggleInterval()

View File

@@ -94,8 +94,13 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
void setInterval(int updatePeriodMs); void setInterval(int updatePeriodMs);
//! Stores new content hash and returns if content changed (based on hash value
//! \threadsafe
bool didContentChange(const QString &content, int startPosition = -1);
private: private:
QDateTime m_updateTimestamp; //!< when file/resource was read QDateTime m_updateTimestamp; //!< when file/resource was read
uint m_contentHash = 0; //!< has of the content given
QMetaObject::Connection m_toggleConnection; //!< connection to switch interval from initial to periodic QMetaObject::Connection m_toggleConnection; //!< connection to switch interval from initial to periodic
private slots: private slots:

View File

@@ -83,22 +83,22 @@ namespace BlackCore
this->threadAssertCheck(); this->threadAssertCheck();
// Worker thread, make sure to write no members here! // Worker thread, make sure to write no members here od do it threadsafe
if (this->isAbandoned()) if (this->isAbandoned())
{ {
CLogMessage(this).debug() << Q_FUNC_INFO; CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("terminated booking parsing process"); // for users CLogMessage(this).info("Terminated booking parsing process");
return; // stop, terminate straight away, ending thread return; // stop, terminate straight away, ending thread
} }
if (nwReply->error() == QNetworkReply::NoError) if (nwReply->error() == QNetworkReply::NoError)
{ {
static const QString timestampFormat("yyyy-MM-dd HH:mm:ss"); static const QString timestampFormat("yyyy-MM-dd HH:mm:ss");
QString xmlData = nwReply->readAll(); const QString xmlData = nwReply->readAll();
nwReply->close(); // close asap nwReply->close(); // close asap
QDomDocument doc;
QDateTime updateTimestamp = QDateTime::currentDateTimeUtc();
QDomDocument doc;
QDateTime updateTimestamp = QDateTime::currentDateTimeUtc(); // default
if (doc.setContent(xmlData)) if (doc.setContent(xmlData))
{ {
QDomNode timestamp = doc.elementsByTagName("timestamp").at(0); QDomNode timestamp = doc.elementsByTagName("timestamp").at(0);
@@ -112,6 +112,14 @@ namespace BlackCore
updateTimestamp = QDateTime::fromString(ts, timestampFormat); updateTimestamp = QDateTime::fromString(ts, timestampFormat);
updateTimestamp.setTimeSpec(Qt::UTC); updateTimestamp.setTimeSpec(Qt::UTC);
if (this->getUpdateTimestamp() == updateTimestamp) return; // nothing to do if (this->getUpdateTimestamp() == updateTimestamp) return; // nothing to do
// save parsing and all follow up actions if nothing changed
bool changed = this->didContentChange(xmlData, xmlData.indexOf("</timestamp>"));
if (!changed)
{
CLogMessage(this).info("Bookings unchanged, skipped");
return; // stop, terminate straight away, ending thread
}
} }
QDomNode atc = doc.elementsByTagName("atcs").at(0); QDomNode atc = doc.elementsByTagName("atcs").at(0);

View File

@@ -211,7 +211,7 @@ namespace BlackCore
if (this->isAbandoned()) if (this->isAbandoned())
{ {
CLogMessage(this).debug() << Q_FUNC_INFO; CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated VATSIM file parsing process"); // for users CLogMessage(this).info("Terminated VATSIM file parsing process");
return; // stop, terminate straight away, ending thread return; // stop, terminate straight away, ending thread
} }
@@ -221,7 +221,13 @@ namespace BlackCore
const QString dataFileData = nwReply->readAll(); const QString dataFileData = nwReply->readAll();
nwReply->close(); // close asap nwReply->close(); // close asap
if (dataFileData.isEmpty()) return; if (dataFileData.isEmpty()) { return; }
// Quick check by hash
if (!this->didContentChange(dataFileData))
{
CLogMessage(this).info("VATSIM file has same content, skipped");
return;
}
const QStringList lines = dataFileData.split(QRegExp("[\r\n]"), QString::SkipEmptyParts); const QStringList lines = dataFileData.split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
if (lines.isEmpty()) { return; } if (lines.isEmpty()) { return; }
@@ -240,7 +246,7 @@ namespace BlackCore
if (this->isAbandoned()) if (this->isAbandoned())
{ {
CLogMessage(this).debug() << Q_FUNC_INFO; CLogMessage(this).debug() << Q_FUNC_INFO;
CLogMessage(this).info("Terminated booking parsing process"); // for users CLogMessage(this).info("Terminated VATSIM file parsing process"); // for users
return; // stop, terminate straight away, ending thread return; // stop, terminate straight away, ending thread
} }
@@ -347,7 +353,11 @@ namespace BlackCore
updateTimestampFromFile = QDateTime::fromString(dts, "yyyyMMddHHmmss"); updateTimestampFromFile = QDateTime::fromString(dts, "yyyyMMddHHmmss");
updateTimestampFromFile.setOffsetFromUtc(0); updateTimestampFromFile.setOffsetFromUtc(0);
bool alreadyRead = (updateTimestampFromFile == this->getUpdateTimestamp()); bool alreadyRead = (updateTimestampFromFile == this->getUpdateTimestamp());
if (alreadyRead) { return; }// still same data, terminate if (alreadyRead)
{
CLogMessage(this).info("VATSIM file has same timestamp, skipped");
return;
}
} }
} }
break; break;
@@ -388,11 +398,16 @@ namespace BlackCore
this->m_atcStations = atcStations; this->m_atcStations = atcStations;
this->m_voiceCapabilities = voiceCapabilities; this->m_voiceCapabilities = voiceCapabilities;
CVatsimSetup vs(this->m_lastGoodSetup.getThreadLocal()); CVatsimSetup vs(this->m_lastGoodSetup.getThreadLocal());
// check if we need to save in cache
if (vs.getVoiceServers() != voiceServers || vs.getFsdServers() != fsdServers)
{
vs.setVoiceServers(voiceServers); vs.setVoiceServers(voiceServers);
vs.setFsdServers(fsdServers); vs.setFsdServers(fsdServers);
vs.setUtcTimestamp(updateTimestampFromFile); vs.setUtcTimestamp(updateTimestampFromFile);
this->m_lastGoodSetup.set(vs); this->m_lastGoodSetup.set(vs);
} }
}
// warnings, if required // warnings, if required
if (!illegalIcaoCodes.isEmpty()) if (!illegalIcaoCodes.isEmpty())

View File

@@ -109,8 +109,15 @@ namespace BlackCore
{ {
QString metarData = nwReply->readAll(); QString metarData = nwReply->readAll();
nwReply->close(); // close asap nwReply->close(); // close asap
CMetarSet metars;
// Quick check by hash
if (!this->didContentChange(metarData))
{
CLogMessage(this).info("METAR file has same content, skipped");
return;
}
CMetarSet metars;
QString invalidMetars; QString invalidMetars;
int invalidLineCount = 0; int invalidLineCount = 0;
QTextStream lineReader(&metarData); QTextStream lineReader(&metarData);