/* */ #include "AnnounceList.h" #include #include "A2STR.h" #include "SimpleRandomizer.h" #include "util.h" namespace aria2 { const std::string AnnounceList::STARTED("started"); const std::string AnnounceList::STOPPED("stopped"); const std::string AnnounceList::COMPLETED("completed"); AnnounceList::AnnounceList (const std::vector >& announceList): _currentTrackerInitialized(false) { reconfigure(announceList); } AnnounceList::AnnounceList (const std::deque >& announceTiers): _tiers(announceTiers), _currentTrackerInitialized(false) { resetIterator(); } void AnnounceList::reconfigure (const std::vector >& announceList) { for(std::vector >::const_iterator itr = announceList.begin(), eoi = announceList.end(); itr != eoi; ++itr) { if((*itr).empty()) { continue; } std::deque urls((*itr).begin(), (*itr).end()); SharedHandle tier(new AnnounceTier(urls)); _tiers.push_back(tier); } resetIterator(); } void AnnounceList::reconfigure(const std::string& url) { std::deque urls; urls.push_back(url); _tiers.push_back(SharedHandle(new AnnounceTier(urls))); resetIterator(); } void AnnounceList::resetIterator() { _currentTier = _tiers.begin(); if(_currentTier != _tiers.end() && (*_currentTier)->urls.size()) { _currentTracker = (*_currentTier)->urls.begin(); _currentTrackerInitialized = true; } else { _currentTrackerInitialized = false; } } std::string AnnounceList::getAnnounce() const { if(_currentTrackerInitialized) { return *_currentTracker; } else { return A2STR::NIL; } } void AnnounceList::announceSuccess() { if(_currentTrackerInitialized) { (*_currentTier)->nextEvent(); std::string url = *_currentTracker; (*_currentTier)->urls.erase(_currentTracker); (*_currentTier)->urls.push_front(url); _currentTier = _tiers.begin(); _currentTracker = (*_currentTier)->urls.begin(); } } void AnnounceList::announceFailure() { if(_currentTrackerInitialized) { ++_currentTracker; if(_currentTracker == (*_currentTier)->urls.end()) { // force next event (*_currentTier)->nextEventIfAfterStarted(); ++_currentTier; if(_currentTier == _tiers.end()) { _currentTrackerInitialized = false; } else { _currentTracker = (*_currentTier)->urls.begin(); } } } } AnnounceTier::AnnounceEvent AnnounceList::getEvent() const { if(_currentTrackerInitialized) { return (*_currentTier)->event; } else { return AnnounceTier::STARTED; } } void AnnounceList::setEvent(AnnounceTier::AnnounceEvent event) { if(_currentTrackerInitialized) { (*_currentTier)->event = event; } } std::string AnnounceList::getEventString() const { if(_currentTrackerInitialized) { switch((*_currentTier)->event) { case AnnounceTier::STARTED: case AnnounceTier::STARTED_AFTER_COMPLETION: return STARTED; case AnnounceTier::STOPPED: return STOPPED; case AnnounceTier::COMPLETED: return COMPLETED; default: return A2STR::NIL; } } else { return A2STR::NIL; } } class FindStoppedAllowedTier { public: bool operator()(const SharedHandle& tier) const { switch(tier->event) { case AnnounceTier::DOWNLOADING: case AnnounceTier::STOPPED: case AnnounceTier::COMPLETED: case AnnounceTier::SEEDING: return true; default: return false; } } }; class FindCompletedAllowedTier { public: bool operator()(const SharedHandle& tier) const { switch(tier->event) { case AnnounceTier::DOWNLOADING: case AnnounceTier::COMPLETED: return true; default: return false; } } }; size_t AnnounceList::countStoppedAllowedTier() const { return count_if(_tiers.begin(), _tiers.end(), FindStoppedAllowedTier()); } size_t AnnounceList::countCompletedAllowedTier() const { return count_if(_tiers.begin(), _tiers.end(), FindCompletedAllowedTier()); } void AnnounceList::setCurrentTier (const std::deque >::iterator& itr) { if(itr != _tiers.end()) { _currentTier = itr; _currentTracker = (*_currentTier)->urls.begin(); } } template InputIterator find_wrap_if(InputIterator first, InputIterator last, InputIterator current, Predicate pred) { InputIterator itr = std::find_if(current, last, pred); if(itr == last) { itr = std::find_if(first, current, pred); } return itr; } void AnnounceList::moveToStoppedAllowedTier() { std::deque >::iterator itr = find_wrap_if(_tiers.begin(), _tiers.end(), _currentTier, FindStoppedAllowedTier()); setCurrentTier(itr); } void AnnounceList::moveToCompletedAllowedTier() { std::deque >::iterator itr = find_wrap_if(_tiers.begin(), _tiers.end(), _currentTier, FindCompletedAllowedTier()); setCurrentTier(itr); } void AnnounceList::shuffle() { for(std::deque >::const_iterator itr = _tiers.begin(), eoi = _tiers.end(); itr != eoi; ++itr) { std::deque& urls = (*itr)->urls; std::random_shuffle(urls.begin(), urls.end(), *(SimpleRandomizer::getInstance().get())); } } bool AnnounceList::allTiersFailed() const { return _currentTier == _tiers.end(); } void AnnounceList::resetTier() { resetIterator(); } bool AnnounceList::currentTierAcceptsStoppedEvent() const { if(_currentTrackerInitialized) { return FindStoppedAllowedTier()(*_currentTier); } else { return false; } } bool AnnounceList::currentTierAcceptsCompletedEvent() const { if(_currentTrackerInitialized) { return FindCompletedAllowedTier()(*_currentTier); } else { return false; } } } // namespace aria2