From: Matt Schatz Date: Sun, 1 Jul 2018 05:16:03 +0000 (-0600) Subject: Attempt to improve the /LIST timeout for large lists X-Git-Tag: 0.13-rc1~14 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=fc26ee91d0e387007d656eb6e83a7a3a923f527a;hp=e9c0076ab1da4d613cf0ef97adbb1f45fed13d47 Attempt to improve the /LIST timeout for large lists Prior to this, the timer was simply running for 10 seconds from the start of the query; which could timeout even while data was being received. Large channel lists (i.e. Freenode) would over-run into the status buffer. Now we utilize QBasicTimer to create a timer that can be easily restarted everytime we receive a RPL_LIST. Inital timeout is 5 seconds and 5 seconds after each RPL_LIST. We also now remove the timer after receiving a RPL_LISTEND instead of letting it tick. --- diff --git a/src/core/coreirclisthelper.cpp b/src/core/coreirclisthelper.cpp index 9bdf4c48..1c4bfde5 100644 --- a/src/core/coreirclisthelper.cpp +++ b/src/core/coreirclisthelper.cpp @@ -23,6 +23,8 @@ #include "corenetwork.h" #include "coreuserinputhandler.h" +constexpr auto kTimeoutMs = 5000; + INIT_SYNCABLE_OBJECT(CoreIrcListHelper) QVariantList CoreIrcListHelper::requestChannelList(const NetworkId &netId, const QStringList &channelFilters) { @@ -45,6 +47,9 @@ bool CoreIrcListHelper::addChannel(const NetworkId &netId, const QString &channe return false; _channelLists[netId] << ChannelDescription(channelName, userCount, topic); + if (_queryTimeoutByNetId.contains(netId)) + _queryTimeoutByNetId[netId]->start(kTimeoutMs, this); + return true; } @@ -55,7 +60,12 @@ bool CoreIrcListHelper::dispatchQuery(const NetworkId &netId, const QString &que if (network) { _channelLists[netId] = QList(); network->userInputHandler()->handleList(BufferInfo(), query); - _queryTimeout[startTimer(10000)] = netId; + + auto timer = std::make_shared(); + timer->start(kTimeoutMs, this); + _queryTimeoutByNetId[netId] = timer; + _queryTimeoutByTimerId[timer->timerId()] = netId; + return true; } else { @@ -66,6 +76,12 @@ bool CoreIrcListHelper::dispatchQuery(const NetworkId &netId, const QString &que bool CoreIrcListHelper::endOfChannelList(const NetworkId &netId) { + if (_queryTimeoutByNetId.contains(netId)) { + // If we recieved an actual RPL_LISTEND, remove the timer + int timerId = _queryTimeoutByNetId.take(netId)->timerId(); + _queryTimeoutByTimerId.remove(timerId); + } + if (_queuedQuery.contains(netId)) { // we're no longer interessted in the current data. drop it and issue a new request. return dispatchQuery(netId, _queuedQuery.take(netId)); @@ -92,8 +108,14 @@ bool CoreIrcListHelper::endOfChannelList(const NetworkId &netId) void CoreIrcListHelper::timerEvent(QTimerEvent *event) { - int timerId = event->timerId(); - killTimer(timerId); - NetworkId netId = _queryTimeout.take(timerId); + if (!_queryTimeoutByTimerId.contains(event->timerId())) { + IrcListHelper::timerEvent(event); + return; + } + + NetworkId netId = _queryTimeoutByTimerId.take(event->timerId()); + _queryTimeoutByNetId.remove(netId); + + event->accept(); endOfChannelList(netId); } diff --git a/src/core/coreirclisthelper.h b/src/core/coreirclisthelper.h index 9247c8d6..8f1081cb 100644 --- a/src/core/coreirclisthelper.h +++ b/src/core/coreirclisthelper.h @@ -21,10 +21,13 @@ #ifndef COREIRCLISTHELPER_H #define COREIRCLISTHELPER_H +#include + #include "irclisthelper.h" #include "coresession.h" +class QBasicTimer; class QTimerEvent; class CoreIrcListHelper : public IrcListHelper @@ -58,7 +61,8 @@ private: QHash _queuedQuery; QHash > _channelLists; QHash _finishedChannelLists; - QHash _queryTimeout; + QHash _queryTimeoutByTimerId; + QHash> _queryTimeoutByNetId; };