Make event handling of `syncthingctl wait-for-idle` more efficient
Don't go though the list of dirs/devs for every dir/dev change event. Just go though the list once after receiving new events. This makes also the code a little bit easier to follow.
This commit is contained in:
parent
230532d15e
commit
aa524aa8b7
|
@ -943,23 +943,20 @@ void Application::waitForIdle(const ArgumentOccurrence &)
|
||||||
{
|
{
|
||||||
m_preventDisconnect = true;
|
m_preventDisconnect = true;
|
||||||
|
|
||||||
// setup timer
|
// setup timer for handling minimum idle duration
|
||||||
QTimer idleTime;
|
auto idleTime = QTimer();
|
||||||
idleTime.setSingleShot(true);
|
idleTime.setSingleShot(true);
|
||||||
idleTime.setInterval(m_idleDuration);
|
idleTime.setInterval(m_idleDuration);
|
||||||
|
|
||||||
// define variable which is set to true if handleTimeout to indicate the idle state has persisted long enough
|
// define event handlers
|
||||||
bool isLongEnoughIdle = false;
|
auto isLongEnoughIdle = false, dirsOrDevsChanged = true, newDirsOrDevs = true;
|
||||||
|
const auto handleStatusChange = [&dirsOrDevsChanged] { dirsOrDevsChanged = true; };
|
||||||
// define handler for timer timeout
|
const auto handleNewDirsOrDevs = [&newDirsOrDevs] { newDirsOrDevs = true; };
|
||||||
function<void(void)> handleTimeout([this, &isLongEnoughIdle] {
|
const auto handleAllEventsProcessed = [this, &newDirsOrDevs, &dirsOrDevsChanged, &idleTime] {
|
||||||
if (checkWhetherIdle()) {
|
if (newDirsOrDevs) {
|
||||||
isLongEnoughIdle = true;
|
findRelevantDirsAndDevs(OperationType::WaitForIdle);
|
||||||
}
|
}
|
||||||
});
|
if (newDirsOrDevs || dirsOrDevsChanged) {
|
||||||
|
|
||||||
// define handler for dirStatusChanged/devStatusChanged
|
|
||||||
function<void(void)> handleStatusChange([this, &idleTime] {
|
|
||||||
if (!checkWhetherIdle()) {
|
if (!checkWhetherIdle()) {
|
||||||
idleTime.stop();
|
idleTime.stop();
|
||||||
return;
|
return;
|
||||||
|
@ -967,22 +964,24 @@ void Application::waitForIdle(const ArgumentOccurrence &)
|
||||||
if (!idleTime.isActive()) {
|
if (!idleTime.isActive()) {
|
||||||
idleTime.start();
|
idleTime.start();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
newDirsOrDevs = dirsOrDevsChanged = false;
|
||||||
// define handler for newDirs/newDevices to call findRelevantDirsAndDevs() in that case
|
};
|
||||||
function<void(void)> handleNewDirsOrDevs([this, &handleStatusChange] {
|
const auto handleIdleTimer = [this, &isLongEnoughIdle] {
|
||||||
findRelevantDirsAndDevs(OperationType::WaitForIdle);
|
if (checkWhetherIdle()) {
|
||||||
handleStatusChange();
|
isLongEnoughIdle = true;
|
||||||
});
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// invoke handler manually because Syncthing could already be idling
|
// invoke handler manually because Syncthing could already be idling
|
||||||
handleNewDirsOrDevs();
|
handleAllEventsProcessed();
|
||||||
|
|
||||||
waitForSignals(&noop, m_idleTimeout, signalInfo(&m_connection, &SyncthingConnection::dirStatusChanged, handleStatusChange, &isLongEnoughIdle),
|
waitForSignals(&noop, m_idleTimeout, signalInfo(&m_connection, &SyncthingConnection::dirStatusChanged, handleStatusChange, &isLongEnoughIdle),
|
||||||
signalInfo(&m_connection, &SyncthingConnection::devStatusChanged, handleStatusChange, &isLongEnoughIdle),
|
signalInfo(&m_connection, &SyncthingConnection::devStatusChanged, handleStatusChange, &isLongEnoughIdle),
|
||||||
signalInfo(&m_connection, &SyncthingConnection::newDirs, handleNewDirsOrDevs, &isLongEnoughIdle),
|
signalInfo(&m_connection, &SyncthingConnection::newDirs, handleNewDirsOrDevs, &isLongEnoughIdle),
|
||||||
signalInfo(&m_connection, &SyncthingConnection::newDevices, handleNewDirsOrDevs, &isLongEnoughIdle),
|
signalInfo(&m_connection, &SyncthingConnection::newDevices, handleNewDirsOrDevs, &isLongEnoughIdle),
|
||||||
signalInfo(&idleTime, &QTimer::timeout, handleTimeout, &isLongEnoughIdle));
|
signalInfo(&m_connection, &SyncthingConnection::allEventsProcessed, handleAllEventsProcessed, &isLongEnoughIdle),
|
||||||
|
signalInfo(&idleTime, &QTimer::timeout, handleIdleTimer, &isLongEnoughIdle));
|
||||||
|
|
||||||
if (!isLongEnoughIdle) {
|
if (!isLongEnoughIdle) {
|
||||||
cerr << Phrases::Warning << "Exiting after timeout" << Phrases::End << flush;
|
cerr << Phrases::Warning << "Exiting after timeout" << Phrases::End << flush;
|
||||||
|
|
|
@ -1113,6 +1113,16 @@ void SyncthingConnection::recalculateStatus()
|
||||||
* \remarks New events are automatically polled when connected.
|
* \remarks New events are automatically polled when connected.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \fn SyncthingConnection::allEventsProcesses()
|
||||||
|
* \brief Indicates all new events have been processed.
|
||||||
|
* \remarks
|
||||||
|
* This event is emitted after newEvents() and dirStatusChanged(), devStatusChanged() and other specific events.
|
||||||
|
* If you would go through the list of all directories on every dirStatusChanged() event using instead might
|
||||||
|
* be a more efficient alternative allEventsProcesses(). Just set a flag on dirStatusChanged() and go though the
|
||||||
|
* list of directories only once on the allEventsProcesses() event when the flag has been set.
|
||||||
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \fn SyncthingConnection::dirStatusChanged()
|
* \fn SyncthingConnection::dirStatusChanged()
|
||||||
* \brief Indicates the status of the specified \a dir changed.
|
* \brief Indicates the status of the specified \a dir changed.
|
||||||
|
|
|
@ -233,6 +233,7 @@ Q_SIGNALS:
|
||||||
void newDevices(const std::vector<SyncthingDev> &devs);
|
void newDevices(const std::vector<SyncthingDev> &devs);
|
||||||
void newConfigApplied();
|
void newConfigApplied();
|
||||||
void newEvents(const QJsonArray &events);
|
void newEvents(const QJsonArray &events);
|
||||||
|
void allEventsProcessed();
|
||||||
void dirStatusChanged(const Data::SyncthingDir &dir, int index);
|
void dirStatusChanged(const Data::SyncthingDir &dir, int index);
|
||||||
void devStatusChanged(const Data::SyncthingDev &dev, int index);
|
void devStatusChanged(const Data::SyncthingDev &dev, int index);
|
||||||
void fileChanged(const Data::SyncthingDir &dir, int index, const Data::SyncthingFileChange &fileChange);
|
void fileChanged(const Data::SyncthingDir &dir, int index, const Data::SyncthingFileChange &fileChange);
|
||||||
|
|
|
@ -1737,7 +1737,9 @@ void SyncthingConnection::readEvents()
|
||||||
m_hasEvents = true;
|
m_hasEvents = true;
|
||||||
const auto replyArray = replyDoc.array();
|
const auto replyArray = replyDoc.array();
|
||||||
emit newEvents(replyArray);
|
emit newEvents(replyArray);
|
||||||
if (!readEventsFromJsonArray(replyArray, m_lastEventId)) {
|
const auto res = readEventsFromJsonArray(replyArray, m_lastEventId);
|
||||||
|
emit allEventsProcessed();
|
||||||
|
if (!res) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue