void ConnectionManager::on(TimerManagerListener::Second, uint32_t aTick) throw() { User::List passiveUsers; ConnectionQueueItem::List removed; User::List idlers; { Lock l(cs); bool attemptDone = false; idlers = checkIdle; checkIdle.clear(); for(ConnectionQueueItem::Iter i = downloads.begin(); i != downloads.end(); ++i) { ConnectionQueueItem* cqi = *i; if(cqi->getState() != ConnectionQueueItem::ACTIVE) { if(!cqi->getUser()->isOnline()) { // Not online anymore...remove it from the pending... removed.push_back(cqi); continue; } if(cqi->getUser()->isSet(User::PASSIVE) && !ClientManager::getInstance()->isActive()) { passiveUsers.push_back(cqi->getUser()); removed.push_back(cqi); continue; } if( ((cqi->getLastAttempt() + 60*1000) < aTick) && !attemptDone ) { cqi->setLastAttempt(aTick); QueueItem::Priority prio = QueueManager::getInstance()->hasDownload(cqi->getUser()); if(prio == QueueItem::PAUSED) { removed.push_back(cqi); continue; } bool startDown = DownloadManager::getInstance()->startDownload(prio); if(cqi->getState() == ConnectionQueueItem::WAITING) { if(startDown) { cqi->setState(ConnectionQueueItem::CONNECTING); ClientManager::getInstance()->connect(cqi->getUser()); fire(ConnectionManagerListener::StatusChanged(), cqi); attemptDone = true; } else { cqi->setState(ConnectionQueueItem::NO_DOWNLOAD_SLOTS); fire(ConnectionManagerListener::Failed(), cqi, STRING(ALL_DOWNLOAD_SLOTS_TAKEN)); } } else if(cqi->getState() == ConnectionQueueItem::NO_DOWNLOAD_SLOTS && startDown) { cqi->setState(ConnectionQueueItem::WAITING); } } else if(((cqi->getLastAttempt() + 50*1000) < aTick) && (cqi->getState() == ConnectionQueueItem::CONNECTING)) { fire(ConnectionManagerListener::Failed(), cqi, STRING(CONNECTION_TIMEOUT)); cqi->setState(ConnectionQueueItem::WAITING); } } } for(ConnectionQueueItem::Iter m = removed.begin(); m != removed.end(); ++m) { putCQI(*m); } } for(User::Iter i = idlers.begin(); i != idlers.end(); ++i) { DownloadManager::getInstance()->checkIdle(*i); } for(User::Iter ui = passiveUsers.begin(); ui != passiveUsers.end(); ++ui) { QueueManager::getInstance()->removeSource(*ui, QueueItem::Source::FLAG_PASSIVE); } }
void ConnectionManager::on(TimerManagerListener::Second, u_int32_t aTick) throw() { ConnectionQueueItem::List failPassive; ConnectionQueueItem::List connecting; ConnectionQueueItem::List removed; User::List getDown; { Lock l(cs); { for(User::Iter k = pendingAdd.begin(); k != pendingAdd.end(); ++k) { ConnectionQueueItem::Iter i = find(downPool.begin(), downPool.end(), *k); if(i == downPool.end()) { // Hm, connection must have failed before it could be collected... getDown.push_back(*k); } else { ConnectionQueueItem* cqi = *i; downPool.erase(i); dcassert(find(active.begin(), active.end(), cqi) == active.end()); active.push_back(cqi); dcassert(cqi->getConnection()); dcassert(cqi->getConnection()->getCQI() == cqi); cqi->getConnection()->removeListener(this); DownloadManager::getInstance()->addConnection(cqi->getConnection()); } } pendingAdd.clear(); } bool tooMany = ((SETTING(DOWNLOAD_SLOTS) != 0) && DownloadManager::getInstance()->getDownloads() >= (size_t)SETTING(DOWNLOAD_SLOTS)); bool tooFast = ((SETTING(MAX_DOWNLOAD_SPEED) != 0 && DownloadManager::getInstance()->getAverageSpeed() >= (SETTING(MAX_DOWNLOAD_SPEED)*1024))); bool startDown = !tooMany && !tooFast; int attempts = 0; ConnectionQueueItem::Iter i = pendingDown.begin(); while(i != pendingDown.end()) { ConnectionQueueItem* cqi = *i; dcassert(cqi->getUser()); if(!cqi->getUser()->isOnline()) { // Not online anymore...remove him from the pending... i = pendingDown.erase(i); removed.push_back(cqi); continue; } if( ((cqi->getLastAttempt() + 60*1000) < aTick) && (attempts < 2) ) { cqi->setLastAttempt(aTick); if(!QueueManager::getInstance()->hasDownload(cqi->getUser())) { i = pendingDown.erase(i); removed.push_back(cqi); continue; } if(cqi->getUser()->isSet(User::PASSIVE) && (SETTING(CONNECTION_TYPE) != SettingsManager::CONNECTION_ACTIVE)) { i = pendingDown.erase(i); failPassive.push_back(cqi); continue; } // Always start high-priority downloads unless we have 3 more than maxdownslots already... if(!startDown) { bool extraFull = (SETTING(DOWNLOAD_SLOTS) != 0) && (DownloadManager::getInstance()->getDownloads() >= (size_t)(SETTING(DOWNLOAD_SLOTS)+3)); startDown = !extraFull && QueueManager::getInstance()->hasDownload(cqi->getUser(), QueueItem::HIGHEST); } if(cqi->getState() == ConnectionQueueItem::WAITING) { if(startDown) { cqi->setState(ConnectionQueueItem::CONNECTING); cqi->getUser()->connect(); fire(ConnectionManagerListener::StatusChanged(), cqi); attempts++; } else { cqi->setState(ConnectionQueueItem::NO_DOWNLOAD_SLOTS); fire(ConnectionManagerListener::Failed(), cqi, STRING(ALL_DOWNLOAD_SLOTS_TAKEN)); } } else if(cqi->getState() == ConnectionQueueItem::NO_DOWNLOAD_SLOTS && startDown) { cqi->setState(ConnectionQueueItem::WAITING); } } else if(((cqi->getLastAttempt() + 50*1000) < aTick) && (cqi->getState() == ConnectionQueueItem::CONNECTING)) { fire(ConnectionManagerListener::Failed(), cqi, STRING(CONNECTION_TIMEOUT)); cqi->setState(ConnectionQueueItem::WAITING); } ++i; } } ConnectionQueueItem::Iter m; for(m = removed.begin(); m != removed.end(); ++m) { fire(ConnectionManagerListener::Removed(), *m); delete *m; } for(m = failPassive.begin(); m != failPassive.end(); ++m) { QueueManager::getInstance()->removeSources((*m)->getUser(), QueueItem::Source::FLAG_PASSIVE); fire(ConnectionManagerListener::Removed(), *m); delete *m; } for(User::Iter n = getDown.begin(); n != getDown.end(); ++n) { getDownloadConnection(*n); } }