app/core/DavSyncScheduler.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "DavSyncScheduler.h" | ||
| 2 | |||
| 3 | #include "data/DavPushModels.h" | ||
| 4 | |||
| 5 | #include <QElapsedTimer> | ||
| 6 | #include <QLoggingCategory> | ||
| 7 | #include <QRandomGenerator> | ||
| 8 | #include <climits> | ||
| 9 | |||
| 10 |
4/7✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 8 taken 169 times.
✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
175 | Q_LOGGING_CATEGORY(lcDavScheduler, "mailjd.calendarsync.scheduler") |
| 11 | |||
| 12 | namespace { | ||
| 13 | constexpr unsigned kImmediate = DavSyncReasonManual | DavSyncReasonInitial | DavSyncReasonRecovery | DavSyncReasonPoll; | ||
| 14 | constexpr unsigned kUnlocking = DavSyncReasonManual | DavSyncReasonInitial | DavSyncReasonPoll; | ||
| 15 | |||
| 16 | 130 | bool lockingFailure(const QString &kind) { | |
| 17 |
4/4✓ Branch 7 → 8 taken 126 times.
✓ Branch 7 → 14 taken 1 time.
✓ Branch 10 → 11 taken 125 times.
✓ Branch 10 → 14 taken 1 time.
|
383 | return kind == QLatin1String("authentication") || kind == QLatin1String("password") || |
| 18 |
3/4✓ Branch 4 → 5 taken 127 times.
✓ Branch 4 → 14 taken 3 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 125 times.
|
383 | kind == QLatin1String("authorization") || kind == QLatin1String("tls"); |
| 19 | } | ||
| 20 | } // namespace | ||
| 21 | |||
| 22 | 957 | DavSyncScheduler::DavSyncScheduler(Executor executor, QObject *parent) | |
| 23 |
2/2✓ Branch 18 → 19 taken 957 times.
✓ Branch 19 → 20 taken 957 times.
|
957 | : QObject(parent), m_executor(std::move(executor)) { |
| 24 |
1/1✓ Branch 20 → 21 taken 957 times.
|
957 | m_wake.setSingleShot(true); |
| 25 |
1/1✓ Branch 21 → 22 taken 957 times.
|
957 | m_pollTimer.setSingleShot(true); |
| 26 |
1/1✓ Branch 22 → 23 taken 957 times.
|
957 | connect(&m_wake, &QTimer::timeout, this, &DavSyncScheduler::evaluate); |
| 27 |
1/1✓ Branch 24 → 25 taken 957 times.
|
957 | connect(&m_pollTimer, &QTimer::timeout, this, &DavSyncScheduler::onPollTimer); |
| 28 | 1787 | m_jitter = [] { return QRandomGenerator::global()->generateDouble(); }; | |
| 29 | 957 | } | |
| 30 | |||
| 31 | 1568 | qint64 DavSyncScheduler::now() const { | |
| 32 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 1568 times.
|
1568 | if (m_clock) return m_clock(); |
| 33 | static QElapsedTimer monotonic; | ||
| 34 |
2/2✓ Branch 7 → 8 taken 34 times.
✓ Branch 7 → 9 taken 1534 times.
|
1568 | if (!monotonic.isValid()) monotonic.start(); |
| 35 | 1568 | return monotonic.elapsed(); | |
| 36 | } | ||
| 37 | |||
| 38 | 833 | void DavSyncScheduler::setPollIntervalMs(qint64 intervalMs) { | |
| 39 | 833 | m_stopped = false; | |
| 40 | 833 | m_pollIntervalMs = qMax<qint64>(0, intervalMs); | |
| 41 |
1/1✓ Branch 3 → 4 taken 833 times.
|
833 | m_pollTimer.stop(); |
| 42 | 833 | m_nextPollAt = 0; | |
| 43 |
2/2✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 832 times.
|
833 | if (m_pollIntervalMs <= 0) return; |
| 44 | // Earlier-only jitter: the configured maximum interval never grows. | ||
| 45 |
2/2✓ Branch 6 → 7 taken 832 times.
✓ Branch 7 → 8 taken 832 times.
|
832 | const qint64 delay = m_pollIntervalMs - qint64(m_pollIntervalMs * 0.1 * qBound(0.0, m_jitter(), 0.999)); |
| 46 |
1/1✓ Branch 8 → 9 taken 832 times.
|
832 | m_nextPollAt = now() + delay; |
| 47 |
1/1✓ Branch 10 → 11 taken 832 times.
|
832 | m_pollTimer.start(int(qMin<qint64>(delay, INT_MAX))); |
| 48 | } | ||
| 49 | |||
| 50 | 1 | void DavSyncScheduler::onPollTimer() { | |
| 51 | 1 | requestAll(DavSyncReasonPoll); | |
| 52 | 1 | setPollIntervalMs(m_pollIntervalMs); | |
| 53 | 1 | } | |
| 54 | |||
| 55 | 89 | void DavSyncScheduler::requestAll(unsigned reasons) { | |
| 56 |
3/4✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 5 taken 88 times.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 5 not taken.
|
89 | if (m_stopped && !(reasons & DavSyncReasonManual)) return; |
| 57 |
6/7✓ Branch 6 → 7 taken 88 times.
✗ Branch 6 → 9 not taken.
✓ Branch 7 → 8 taken 87 times.
✓ Branch 7 → 9 taken 1 time.
✓ Branch 10 → 11 taken 87 times.
✓ Branch 10 → 12 taken 1 time.
✓ Branch 11 → 12 taken 87 times.
|
88 | if (m_roundHook && (reasons & kUnlocking)) m_roundHook(reasons); |
| 58 |
2/3✓ Branch 13 → 14 taken 88 times.
✗ Branch 13 → 15 not taken.
✓ Branch 14 → 16 taken 88 times.
|
88 | const QStringList accounts = m_accounts ? m_accounts() : QStringList(); |
| 59 |
3/3✓ Branch 20 → 21 taken 93 times.
✓ Branch 24 → 18 taken 93 times.
✓ Branch 24 → 25 taken 88 times.
|
181 | for (const QString &accountId : accounts) mark(accountId, true, {}, reasons); |
| 60 |
1/1✓ Branch 25 → 26 taken 88 times.
|
88 | evaluate(); |
| 61 | 88 | } | |
| 62 | |||
| 63 | 13 | void DavSyncScheduler::requestAccount(const QString &accountId, unsigned reasons) { | |
| 64 |
3/4✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 5 taken 12 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
13 | if (m_stopped && !(reasons & DavSyncReasonManual)) return; |
| 65 |
1/1✓ Branch 6 → 7 taken 13 times.
|
13 | mark(accountId, true, {}, reasons); |
| 66 | 13 | evaluate(); | |
| 67 | } | ||
| 68 | |||
| 69 | 181 | void DavSyncScheduler::requestCollections(const QString &accountId, const QStringList &paths, unsigned reasons) { | |
| 70 |
6/8✓ Branch 3 → 4 taken 181 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 7 taken 180 times.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 180 times.
|
181 | if (paths.isEmpty() || (m_stopped && !(reasons & DavSyncReasonManual))) return; |
| 71 | 180 | mark(accountId, false, paths, reasons); | |
| 72 | 180 | evaluate(); | |
| 73 | } | ||
| 74 | |||
| 75 | 296 | void DavSyncScheduler::mark(const QString &accountId, bool full, const QStringList &paths, unsigned reasons) { | |
| 76 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 296 times.
|
296 | if (accountId.isEmpty()) return; |
| 77 |
2/2✓ Branch 5 → 6 taken 91 times.
✓ Branch 5 → 8 taken 205 times.
|
296 | if (reasons & DavSyncReasonManual) { |
| 78 |
1/1✓ Branch 6 → 7 taken 91 times.
|
91 | m_locked.remove(accountId); |
| 79 |
1/1✓ Branch 7 → 8 taken 91 times.
|
91 | m_holdUntil.remove(accountId); |
| 80 | } | ||
| 81 |
1/1✓ Branch 8 → 9 taken 296 times.
|
296 | Pending &pending = m_pending[accountId]; |
| 82 | 296 | const bool fresh = pending.reasons == 0; | |
| 83 |
4/4✓ Branch 9 → 10 taken 293 times.
✓ Branch 9 → 11 taken 3 times.
✓ Branch 10 → 11 taken 113 times.
✓ Branch 10 → 12 taken 180 times.
|
296 | pending.full = pending.full || full; |
| 84 | 296 | pending.reasons |= reasons; | |
| 85 |
2/2✓ Branch 21 → 15 taken 181 times.
✓ Branch 21 → 22 taken 296 times.
|
477 | for (const QString &path : paths) |
| 86 |
3/3✓ Branch 17 → 18 taken 74 times.
✓ Branch 17 → 19 taken 107 times.
✓ Branch 18 → 19 taken 74 times.
|
181 | if (!pending.paths.contains(path)) pending.paths.append(path); |
| 87 |
1/1✓ Branch 22 → 23 taken 296 times.
|
296 | const qint64 t = now(); |
| 88 |
2/2✓ Branch 23 → 24 taken 172 times.
✓ Branch 23 → 29 taken 124 times.
|
296 | if (reasons & kImmediate) { |
| 89 |
2/2✓ Branch 24 → 25 taken 159 times.
✓ Branch 24 → 26 taken 13 times.
|
172 | pending.dueAt = fresh ? t : qMin(pending.dueAt, t); |
| 90 | } else { | ||
| 91 |
2/2✓ Branch 29 → 30 taken 42 times.
✓ Branch 29 → 31 taken 82 times.
|
124 | if (pending.firstPushAt == 0) pending.firstPushAt = t; |
| 92 | 124 | const qint64 pushDue = qMin(t + m_timing.pushDebounceMs, pending.firstPushAt + m_timing.pushMaxDelayMs); | |
| 93 | // Only push so far: the latest notice moves the start (coalescing). | ||
| 94 |
1/2✗ Branch 32 → 33 not taken.
✓ Branch 32 → 35 taken 124 times.
|
124 | pending.dueAt = (pending.reasons & kImmediate) ? qMin(pending.dueAt, pushDue) : pushDue; |
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | 288 | qint64 DavSyncScheduler::earliestStart(const QString &accountId, const Pending &pending) const { | |
| 99 | 288 | qint64 start = pending.dueAt; | |
| 100 |
2/2✓ Branch 2 → 3 taken 195 times.
✓ Branch 2 → 6 taken 93 times.
|
288 | if (!(pending.reasons & DavSyncReasonManual)) start = qMax(start, m_holdUntil.value(accountId, 0)); |
| 101 |
2/2✓ Branch 6 → 7 taken 130 times.
✓ Branch 6 → 10 taken 158 times.
|
288 | if (pending.reasons == DavSyncReasonPush) |
| 102 | 130 | start = qMax(start, m_lastStart.value(accountId, LLONG_MIN / 2) + m_timing.minBatchSpacingMs); | |
| 103 | 288 | return start; | |
| 104 | } | ||
| 105 | |||
| 106 | 433 | void DavSyncScheduler::evaluate() { | |
| 107 |
1/1✓ Branch 2 → 3 taken 433 times.
|
433 | const qint64 t = now(); |
| 108 | // Fallback window after a push failure: regular short polls. | ||
| 109 |
7/7✓ Branch 3 → 4 taken 433 times.
✓ Branch 35 → 36 taken 446 times.
✓ Branch 35 → 40 taken 1 time.
✓ Branch 38 → 39 taken 14 times.
✓ Branch 38 → 40 taken 432 times.
✓ Branch 41 → 5 taken 14 times.
✓ Branch 41 → 42 taken 433 times.
|
447 | for (auto it = m_fallbackUntil.begin(); !m_stopped && it != m_fallbackUntil.end();) { |
| 110 |
2/2✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 24 taken 13 times.
|
14 | if (t >= it.value()) { |
| 111 |
6/6✓ Branch 7 → 8 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 18 → 9 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
|
2 | qCInfo(lcDavScheduler) << "Fallback window ended for" << it.key(); |
| 112 |
1/1✓ Branch 20 → 21 taken 1 time.
|
1 | m_nextFallbackPoll.remove(it.key()); |
| 113 |
1/1✓ Branch 22 → 23 taken 1 time.
|
1 | it = m_fallbackUntil.erase(it); |
| 114 | 1 | continue; | |
| 115 | 1 | } | |
| 116 |
2/2✓ Branch 26 → 27 taken 10 times.
✓ Branch 26 → 34 taken 3 times.
|
13 | if (t >= m_nextFallbackPoll.value(it.key(), 0)) { |
| 117 |
1/1✓ Branch 28 → 29 taken 10 times.
|
10 | m_nextFallbackPoll[it.key()] = t + m_timing.fallbackPollMs; |
| 118 |
1/1✓ Branch 31 → 32 taken 10 times.
|
10 | mark(it.key(), true, {}, DavSyncReasonRecovery); |
| 119 | } | ||
| 120 | 13 | ++it; | |
| 121 | } | ||
| 122 | 433 | qint64 wakeAt = LLONG_MAX; | |
| 123 |
2/2✓ Branch 49 → 45 taken 13 times.
✓ Branch 49 → 50 taken 433 times.
|
446 | for (qint64 next : std::as_const(m_nextFallbackPoll)) wakeAt = qMin(wakeAt, next); |
| 124 |
4/5✓ Branch 51 → 52 taken 433 times.
✗ Branch 51 → 54 not taken.
✓ Branch 52 → 53 taken 433 times.
✓ Branch 53 → 54 taken 431 times.
✓ Branch 53 → 55 taken 2 times.
|
433 | const bool online = !m_networkGate || m_networkGate(); |
| 125 |
1/1✓ Branch 56 → 57 taken 433 times.
|
433 | const QStringList accounts = m_pending.keys(); |
| 126 |
2/2✓ Branch 146 → 59 taken 343 times.
✓ Branch 146 → 147 taken 433 times.
|
776 | for (const QString &accountId : accounts) { |
| 127 |
6/6✓ Branch 61 → 62 taken 293 times.
✓ Branch 61 → 63 taken 50 times.
✓ Branch 62 → 63 taken 3 times.
✓ Branch 62 → 64 taken 290 times.
✓ Branch 65 → 66 taken 53 times.
✓ Branch 65 → 67 taken 290 times.
|
468 | if (m_busy.contains(accountId) || !online) continue; |
| 128 | 290 | Pending pending = m_pending.value(accountId); | |
| 129 |
3/4✓ Branch 68 → 69 taken 1 time.
✓ Branch 68 → 72 taken 289 times.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 72 taken 1 time.
|
290 | if (m_stopped && !(pending.reasons & DavSyncReasonManual)) { |
| 130 | ✗ | m_pending.remove(accountId); // background sync stopped: manual only | |
| 131 | ✗ | continue; | |
| 132 | } | ||
| 133 |
5/6✓ Branch 73 → 74 taken 2 times.
✓ Branch 73 → 76 taken 288 times.
✓ Branch 74 → 75 taken 2 times.
✗ Branch 74 → 76 not taken.
✓ Branch 77 → 78 taken 2 times.
✓ Branch 77 → 91 taken 288 times.
|
290 | if (m_locked.contains(accountId) && !(pending.reasons & kUnlocking)) { |
| 134 | // Broken credentials/TLS: no automatic retries until the next poll, | ||
| 135 | // a manual request or a configuration change. | ||
| 136 |
6/6✓ Branch 78 → 79 taken 2 times.
✓ Branch 82 → 83 taken 2 times.
✓ Branch 83 → 84 taken 2 times.
✓ Branch 84 → 85 taken 2 times.
✓ Branch 88 → 80 taken 2 times.
✓ Branch 88 → 89 taken 2 times.
|
4 | qCInfo(lcDavScheduler) << "Account locked, dropping automatic request" << accountId; |
| 137 |
1/1✓ Branch 89 → 90 taken 2 times.
|
2 | m_pending.remove(accountId); |
| 138 | 2 | continue; | |
| 139 | 2 | } | |
| 140 |
1/1✓ Branch 91 → 92 taken 288 times.
|
288 | const qint64 start = earliestStart(accountId, pending); |
| 141 |
2/2✓ Branch 92 → 93 taken 120 times.
✓ Branch 92 → 95 taken 168 times.
|
288 | if (start > t) { |
| 142 | 120 | wakeAt = qMin(wakeAt, start); | |
| 143 | 120 | continue; | |
| 144 | } | ||
| 145 |
2/2✓ Branch 96 → 97 taken 3 times.
✓ Branch 96 → 98 taken 165 times.
|
168 | if (m_busy.size() >= m_timing.maxParallelAccounts) continue; // re-evaluated on finish |
| 146 |
1/1✓ Branch 98 → 99 taken 165 times.
|
165 | m_pending.remove(accountId); |
| 147 | 165 | CalendarSyncRequest request; | |
| 148 | 165 | request.accountId = accountId; | |
| 149 | 165 | request.discover = pending.full; | |
| 150 | 165 | request.forcedPaths = pending.paths; | |
| 151 | 165 | request.reasons = pending.reasons; | |
| 152 |
1/1✓ Branch 101 → 102 taken 165 times.
|
165 | m_busy.insert(accountId); |
| 153 |
1/1✓ Branch 102 → 103 taken 165 times.
|
165 | m_lastStart[accountId] = t; |
| 154 |
9/9✓ Branch 103 → 104 taken 165 times.
✓ Branch 107 → 108 taken 165 times.
✓ Branch 108 → 109 taken 165 times.
✓ Branch 109 → 110 taken 165 times.
✓ Branch 110 → 111 taken 165 times.
✓ Branch 111 → 112 taken 165 times.
✓ Branch 112 → 113 taken 165 times.
✓ Branch 120 → 105 taken 165 times.
✓ Branch 120 → 121 taken 165 times.
|
330 | qCInfo(lcDavScheduler) << "Batch" << accountId << "full" << request.discover << "forced" |
| 155 |
3/3✓ Branch 114 → 115 taken 165 times.
✓ Branch 115 → 116 taken 165 times.
✓ Branch 116 → 117 taken 165 times.
|
165 | << request.forcedPaths.size() << "reasons" << request.reasons; |
| 156 |
1/1✓ Branch 121 → 122 taken 165 times.
|
165 | emit batchStarted(request); |
| 157 |
3/3✓ Branch 122 → 123 taken 165 times.
✓ Branch 123 → 124 taken 1 time.
✓ Branch 123 → 137 taken 164 times.
|
165 | if (!m_executor(request)) { |
| 158 |
1/1✓ Branch 124 → 125 taken 1 time.
|
1 | m_busy.remove(accountId); |
| 159 |
6/6✓ Branch 125 → 126 taken 1 time.
✓ Branch 129 → 130 taken 1 time.
✓ Branch 130 → 131 taken 1 time.
✓ Branch 131 → 132 taken 1 time.
✓ Branch 135 → 127 taken 1 time.
✓ Branch 135 → 136 taken 1 time.
|
2 | qCInfo(lcDavScheduler) << "Batch not started for" << accountId; |
| 160 | } | ||
| 161 | 290 | } | |
| 162 |
3/3✓ Branch 147 → 148 taken 133 times.
✓ Branch 147 → 151 taken 300 times.
✓ Branch 149 → 150 taken 133 times.
|
433 | if (wakeAt != LLONG_MAX) m_wake.start(int(qBound(qint64(0), wakeAt - t, qint64(INT_MAX)))); |
| 163 | 433 | } | |
| 164 | |||
| 165 | 130 | void DavSyncScheduler::batchFinished(const CalendarSyncResult &result) { | |
| 166 | 130 | m_busy.remove(result.accountId); | |
| 167 |
3/3✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 7 taken 125 times.
✓ Branch 5 → 6 taken 5 times.
|
130 | if (lockingFailure(result.errorKind)) m_locked.insert(result.accountId); |
| 168 |
6/6✓ Branch 7 → 8 taken 122 times.
✓ Branch 7 → 11 taken 3 times.
✓ Branch 9 → 10 taken 115 times.
✓ Branch 9 → 11 taken 7 times.
✓ Branch 12 → 13 taken 115 times.
✓ Branch 12 → 14 taken 10 times.
|
125 | else if (result.completed && result.errorKind.isEmpty()) m_locked.remove(result.accountId); |
| 169 |
2/2✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 17 taken 129 times.
|
130 | if (result.retryAfterSeconds > 0) holdUntil(result.accountId, now() + qint64(result.retryAfterSeconds) * 1000); |
| 170 | 130 | evaluate(); | |
| 171 | 130 | } | |
| 172 | |||
| 173 | 9 | void DavSyncScheduler::enterFallback(const QString &accountId) { | |
| 174 |
2/2✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 6 times.
|
9 | if (m_fallbackUntil.contains(accountId)) return; |
| 175 |
6/6✓ Branch 5 → 6 taken 6 times.
✓ Branch 9 → 10 taken 6 times.
✓ Branch 10 → 11 taken 6 times.
✓ Branch 11 → 12 taken 6 times.
✓ Branch 15 → 7 taken 6 times.
✓ Branch 15 → 16 taken 6 times.
|
12 | qCInfo(lcDavScheduler) << "Fallback polling for" << accountId; |
| 176 | 6 | m_fallbackUntil[accountId] = now() + m_timing.fallbackWindowMs; | |
| 177 | 6 | m_nextFallbackPoll[accountId] = 0; // one immediate catch-up | |
| 178 | 6 | evaluate(); | |
| 179 | } | ||
| 180 | |||
| 181 | 2 | void DavSyncScheduler::leaveFallback(const QString &accountId) { | |
| 182 | 2 | m_fallbackUntil.remove(accountId); | |
| 183 | 2 | m_nextFallbackPoll.remove(accountId); | |
| 184 | 2 | } | |
| 185 | |||
| 186 | 474 | bool DavSyncScheduler::inFallback(const QString &accountId) const { | |
| 187 | 474 | return m_fallbackUntil.contains(accountId); | |
| 188 | } | ||
| 189 | |||
| 190 | 1 | void DavSyncScheduler::holdUntil(const QString &accountId, qint64 at) { | |
| 191 |
1/1✓ Branch 4 → 5 taken 1 time.
|
1 | m_holdUntil[accountId] = qMax(m_holdUntil.value(accountId, 0), at); |
| 192 | 1 | } | |
| 193 | |||
| 194 | ✗ | void DavSyncScheduler::lockAccount(const QString &accountId) { | |
| 195 | ✗ | m_locked.insert(accountId); | |
| 196 | ✗ | } | |
| 197 | |||
| 198 | 1 | void DavSyncScheduler::kick() { | |
| 199 | 1 | evaluate(); | |
| 200 | 1 | } | |
| 201 | |||
| 202 | 12 | void DavSyncScheduler::stop() { | |
| 203 | 12 | m_stopped = true; | |
| 204 | 12 | m_wake.stop(); | |
| 205 | 12 | m_pollTimer.stop(); | |
| 206 | 12 | m_nextPollAt = 0; | |
| 207 | 12 | m_pending.clear(); | |
| 208 | 12 | m_busy.clear(); | |
| 209 | 12 | m_fallbackUntil.clear(); | |
| 210 | 12 | m_nextFallbackPoll.clear(); | |
| 211 | 12 | } | |
| 212 |