/* */ #include "ServerStatMan.h" #include #include #include #include #include #include #include "ServerStat.h" #include "util.h" #include "RecoverableException.h" #include "a2functional.h" #include "BufferedFile.h" #include "message.h" #include "fmt.h" #include "LogFactory.h" #include "File.h" namespace aria2 { ServerStatMan::ServerStatMan() {} ServerStatMan::~ServerStatMan() {} SharedHandle ServerStatMan::find(const std::string& hostname, const std::string& protocol) const { SharedHandle ss(new ServerStat(hostname, protocol)); std::deque >::const_iterator i = std::lower_bound(serverStats_.begin(), serverStats_.end(), ss, DerefLess >()); if(i != serverStats_.end() && (*i)->getHostname() == hostname && (*i)->getProtocol() == protocol) { return *i; } else { return SharedHandle(); } } bool ServerStatMan::add(const SharedHandle& serverStat) { std::deque >::iterator i = std::lower_bound(serverStats_.begin(), serverStats_.end(), serverStat, DerefLess >()); if(i != serverStats_.end() && *(*i) == *serverStat) { return false; } else { serverStats_.insert(i, serverStat); return true; } } bool ServerStatMan::save(const std::string& filename) const { std::string tempfile = filename; tempfile += "__temp"; { BufferedFile fp(tempfile, BufferedFile::WRITE); if(!fp) { A2_LOG_ERROR(fmt(MSG_OPENING_WRITABLE_SERVER_STAT_FILE_FAILED, filename.c_str())); return false; } for(std::deque >::const_iterator i = serverStats_.begin(), eoi = serverStats_.end(); i != eoi; ++i) { std::string l = (*i)->toString(); l += "\n"; if(fp.write(l.data(), l.size()) != l.size()) { A2_LOG_ERROR(fmt(MSG_WRITING_SERVER_STAT_FILE_FAILED, filename.c_str())); } } if(fp.close() == EOF) { A2_LOG_ERROR(fmt(MSG_WRITING_SERVER_STAT_FILE_FAILED, filename.c_str())); return false; } } if(File(tempfile).renameTo(filename)) { A2_LOG_NOTICE(fmt(MSG_SERVER_STAT_SAVED, filename.c_str())); return true; } else { A2_LOG_ERROR(fmt(MSG_WRITING_SERVER_STAT_FILE_FAILED, filename.c_str())); return false; } } bool ServerStatMan::load(const std::string& filename) { static const std::string S_HOST = "host"; static const std::string S_PROTOCOL = "protocol"; static const std::string S_DL_SPEED = "dl_speed"; static const std::string S_SC_AVG_SPEED = "sc_avg_speed"; static const std::string S_MC_AVG_SPEED = "mc_avg_speed"; static const std::string S_LAST_UPDATED = "last_updated"; static const std::string S_COUNTER = "counter"; static const std::string S_STATUS = "status"; BufferedFile fp(filename, BufferedFile::READ); if(!fp) { A2_LOG_ERROR(fmt(MSG_OPENING_READABLE_SERVER_STAT_FILE_FAILED, filename.c_str())); return false; } char buf[4096]; while(1) { if(!fp.getsn(buf, sizeof(buf))) { if(fp.eof()) { break; } else { A2_LOG_ERROR(fmt(MSG_READING_SERVER_STAT_FILE_FAILED, filename.c_str())); return false; } } std::string line = util::stripIter(&buf[0], &buf[strlen(buf)]); if(line.empty()) { continue; } std::vector items; util::split(line, std::back_inserter(items), ","); std::map m; for(std::vector::const_iterator i = items.begin(), eoi = items.end(); i != eoi; ++i) { std::pair p; util::divide(p, *i, '='); p.first = util::strip(p.first); p.second = util::strip(p.second); m[p.first] = p.second; } if(m[S_HOST].empty() || m[S_PROTOCOL].empty()) { continue; } SharedHandle sstat(new ServerStat(m[S_HOST], m[S_PROTOCOL])); try { sstat->setDownloadSpeed(util::parseUInt(m[S_DL_SPEED])); // Old serverstat file doesn't contains SC_AVG_SPEED if(m.find(S_SC_AVG_SPEED) != m.end()) { sstat->setSingleConnectionAvgSpeed(util::parseUInt(m[S_SC_AVG_SPEED])); } // Old serverstat file doesn't contains MC_AVG_SPEED if(m.find(S_MC_AVG_SPEED) != m.end()) { sstat->setMultiConnectionAvgSpeed(util::parseUInt(m[S_MC_AVG_SPEED])); } // Old serverstat file doesn't contains COUNTER_SPEED if(m.find(S_COUNTER) != m.end()) { sstat->setCounter(util::parseUInt(m[S_COUNTER])); } sstat->setLastUpdated(Time(util::parseInt(m[S_LAST_UPDATED]))); sstat->setStatus(m[S_STATUS]); add(sstat); } catch(RecoverableException& e) { continue; } } A2_LOG_NOTICE(fmt(MSG_SERVER_STAT_LOADED, filename.c_str())); return true; } namespace { class FindStaleServerStat { private: time_t timeout_; Time time_; public: FindStaleServerStat(time_t timeout):timeout_(timeout) {} bool operator()(const SharedHandle& ss) const { return ss->getLastUpdated().difference(time_) >= timeout_; } }; } // namespace void ServerStatMan::removeStaleServerStat(time_t timeout) { serverStats_.erase(std::remove_if(serverStats_.begin(), serverStats_.end(), FindStaleServerStat(timeout)), serverStats_.end()); } } // namespace aria2