diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index dccd655b..9a907d6f 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -835,44 +834,12 @@ bool RequestGroupMan::addServerStat(const SharedHandle& serverStat) bool RequestGroupMan::loadServerStat(const std::string& filename) { - std::ifstream in(filename.c_str(), std::ios::binary); - if(!in) { - A2_LOG_ERROR(fmt(MSG_OPENING_READABLE_SERVER_STAT_FILE_FAILED, - filename.c_str())); - return false; - } - if(serverStatMan_->load(in)) { - A2_LOG_NOTICE(fmt(MSG_SERVER_STAT_LOADED, filename.c_str())); - return true; - } else { - A2_LOG_ERROR(fmt(MSG_READING_SERVER_STAT_FILE_FAILED, filename.c_str())); - return false; - } + return serverStatMan_->load(filename); } bool RequestGroupMan::saveServerStat(const std::string& filename) const { - std::string tempfile = filename; - tempfile += "__temp"; - { - std::ofstream out(tempfile.c_str(), std::ios::binary); - if(!out) { - A2_LOG_ERROR(fmt(MSG_OPENING_WRITABLE_SERVER_STAT_FILE_FAILED, - filename.c_str())); - return false; - } - if(!serverStatMan_->save(out)) { - 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; - } + return serverStatMan_->save(filename); } void RequestGroupMan::removeStaleServerStat(time_t timeout) diff --git a/src/ServerStat.cc b/src/ServerStat.cc index c841059a..395dc16e 100644 --- a/src/ServerStat.cc +++ b/src/ServerStat.cc @@ -41,6 +41,8 @@ #include "Logger.h" #include "LogFactory.h" #include "fmt.h" +#include "a2functional.h" +#include "util.h" namespace aria2 { @@ -204,17 +206,20 @@ bool ServerStat::operator==(const ServerStat& serverStat) const return hostname_ == serverStat.hostname_ && protocol_ == serverStat.protocol_; } -std::ostream& operator<<(std::ostream& o, const ServerStat& serverStat) +std::string ServerStat::toString() const { - o << "host=" << serverStat.getHostname() << ", " - << "protocol=" << serverStat.getProtocol() << ", " - << "dl_speed=" << serverStat.getDownloadSpeed() << ", " - << "sc_avg_speed=" << serverStat.getSingleConnectionAvgSpeed() << ", " - << "mc_avg_speed=" << serverStat.getMultiConnectionAvgSpeed() << ", " - << "last_updated=" << serverStat.getLastUpdated().getTime() << ", " - << "counter=" << serverStat.getCounter() << ", " - << "status=" << ServerStat::STATUS_STRING[serverStat.getStatus()]; - return o; + std::string res; + strappend(res, "host=", getHostname(), ", "); + strappend(res, "protocol=", getProtocol(), ", "); + strappend(res, "dl_speed=", util::uitos(getDownloadSpeed()), ", "); + strappend(res, "sc_avg_speed=", util::uitos(getSingleConnectionAvgSpeed()), + ", "); + strappend(res, "mc_avg_speed=", util::uitos(getMultiConnectionAvgSpeed()), + ", "); + strappend(res, "last_updated=", util::itos(getLastUpdated().getTime()), ", "); + strappend(res, "counter=", util::uitos(getCounter()), ", "); + strappend(res, "status=", ServerStat::STATUS_STRING[getStatus()]); + return res; } } // namespace aria2 diff --git a/src/ServerStat.h b/src/ServerStat.h index 361d5e9e..327a2a5a 100644 --- a/src/ServerStat.h +++ b/src/ServerStat.h @@ -146,6 +146,8 @@ public: bool operator<(const ServerStat& serverStat) const; bool operator==(const ServerStat& serverStat) const; + + std::string toString() const; private: std::string hostname_; @@ -166,8 +168,6 @@ private: void setStatusInternal(STATUS status); }; -std::ostream& operator<<(std::ostream& o, const ServerStat& serverStat); - class ServerStatFaster { public: bool operator() diff --git a/src/ServerStatMan.cc b/src/ServerStatMan.cc index 4b1f93b6..18f3cf3c 100644 --- a/src/ServerStatMan.cc +++ b/src/ServerStatMan.cc @@ -34,8 +34,9 @@ /* copyright --> */ #include "ServerStatMan.h" +#include +#include #include -#include #include #include #include @@ -44,6 +45,11 @@ #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 { @@ -80,17 +86,44 @@ bool ServerStatMan::add(const SharedHandle& serverStat) } } -bool ServerStatMan::save(std::ostream& out) const +bool ServerStatMan::save(const std::string& filename) const { - for(std::deque >::const_iterator i = - serverStats_.begin(), eoi = serverStats_.end(); i != eoi; ++i) { - out << *(*i) << "\n"; + std::string tempfile = filename; + tempfile += "__temp"; + { + BufferedFile fp(tempfile, BufferedFile::WRITE); + if(!fp) { + A2_LOG_ERROR(fmt(MSG_OPENING_WRITABLE_SERVER_STAT_FILE_FAILED, + utf8ToNative(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, + utf8ToNative(filename).c_str())); + } + } + if(fp.close() == EOF) { + A2_LOG_ERROR(fmt(MSG_WRITING_SERVER_STAT_FILE_FAILED, + utf8ToNative(filename).c_str())); + return false; + } + } + if(File(tempfile).renameTo(filename)) { + A2_LOG_NOTICE(fmt(MSG_SERVER_STAT_SAVED, + utf8ToNative(filename).c_str())); + return true; + } else { + A2_LOG_ERROR(fmt(MSG_WRITING_SERVER_STAT_FILE_FAILED, + utf8ToNative(filename).c_str())); + return false; } - out.flush(); - return !out.bad(); } -bool ServerStatMan::load(std::istream& in) +bool ServerStatMan::load(const std::string& filename) { static const std::string S_HOST = "host"; static const std::string S_PROTOCOL = "protocol"; @@ -101,9 +134,24 @@ bool ServerStatMan::load(std::istream& in) static const std::string S_COUNTER = "counter"; static const std::string S_STATUS = "status"; - std::string line; - while(getline(in, line)) { - line = util::strip(line); + BufferedFile fp(filename, BufferedFile::READ); + if(!fp) { + A2_LOG_ERROR(fmt(MSG_OPENING_READABLE_SERVER_STAT_FILE_FAILED, + utf8ToNative(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, + utf8ToNative(filename).c_str())); + return false; + } + } + std::string line = util::stripIter(&buf[0], &buf[strlen(buf)]); if(line.empty()) { continue; } @@ -143,7 +191,8 @@ bool ServerStatMan::load(std::istream& in) continue; } } - return !in.bad(); + A2_LOG_NOTICE(fmt(MSG_SERVER_STAT_LOADED, utf8ToNative(filename).c_str())); + return true; } namespace { diff --git a/src/ServerStatMan.h b/src/ServerStatMan.h index fea6e384..47a8c075 100644 --- a/src/ServerStatMan.h +++ b/src/ServerStatMan.h @@ -38,7 +38,6 @@ #include #include -#include #include "SharedHandle.h" #include "a2time.h" @@ -58,9 +57,9 @@ public: bool add(const SharedHandle& serverStat); - bool load(std::istream& in); + bool load(const std::string& filename); - bool save(std::ostream& out) const; + bool save(const std::string& filename) const; void removeStaleServerStat(time_t timeout); private: diff --git a/test/ServerStatManTest.cc b/test/ServerStatManTest.cc index 02f111ca..fe25b36f 100644 --- a/test/ServerStatManTest.cc +++ b/test/ServerStatManTest.cc @@ -1,13 +1,14 @@ #include "ServerStatMan.h" #include -#include #include #include "ServerStat.h" #include "Exception.h" #include "util.h" +#include "BufferedFile.h" +#include "TestUtil.h" namespace aria2 { @@ -78,9 +79,8 @@ void ServerStatManTest::testSave() CPPUNIT_ASSERT(ssm.add(localhost_ftp)); CPPUNIT_ASSERT(ssm.add(mirror)); - std::stringstream ss; - CPPUNIT_ASSERT(ssm.save(ss)); - std::string out = ss.str(); + std::string filename = A2_TEST_OUT_DIR"/aria2_ServerStatManTest_testSave"; + CPPUNIT_ASSERT(ssm.save(filename)); CPPUNIT_ASSERT_EQUAL (std::string ("host=localhost, protocol=ftp," @@ -106,20 +106,22 @@ void ServerStatManTest::testSave() " last_updated=1210000002," " counter=0," " status=ERROR\n"), - out); + readFile(filename)); } void ServerStatManTest::testLoad() { + std::string filename = A2_TEST_OUT_DIR"/aria2_ServerStatManTest_testLoad"; std::string in = "host=localhost, protocol=ftp, dl_speed=30000, last_updated=1210000001, status=OK\n" "host=localhost, protocol=http, dl_speed=25000, sc_avg_speed=101, mc_avg_speed=102, last_updated=1210000000, counter=6, status=OK\n" "host=mirror, protocol=http, dl_speed=0, last_updated=1210000002, status=ERROR\n"; - - std::stringstream ss(in); + BufferedFile fp(filename, BufferedFile::WRITE); + CPPUNIT_ASSERT_EQUAL((size_t)in.size(), fp.write(in.data(), in.size())); + CPPUNIT_ASSERT(fp.close() != EOF); ServerStatMan ssm; - CPPUNIT_ASSERT(ssm.load(ss)); + CPPUNIT_ASSERT(ssm.load(filename)); SharedHandle localhost_http = ssm.find("localhost", "http"); CPPUNIT_ASSERT(localhost_http); diff --git a/test/ServerStatTest.cc b/test/ServerStatTest.cc index af9cd0ab..7787ea11 100644 --- a/test/ServerStatTest.cc +++ b/test/ServerStatTest.cc @@ -14,7 +14,7 @@ class ServerStatTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ServerStatTest); CPPUNIT_TEST(testSetStatus); - CPPUNIT_TEST(testOperatorOstream); + CPPUNIT_TEST(testToString); CPPUNIT_TEST_SUITE_END(); public: void setUp() {} @@ -22,7 +22,7 @@ public: void tearDown() {} void testSetStatus(); - void testOperatorOstream(); + void testToString(); }; @@ -44,7 +44,7 @@ void ServerStatTest::testSetStatus() CPPUNIT_ASSERT_EQUAL(ServerStat::OK, ss.getStatus()); } -void ServerStatTest::testOperatorOstream() +void ServerStatTest::testToString() { ServerStat localhost_http("localhost", "http"); localhost_http.setDownloadSpeed(90000); @@ -53,33 +53,24 @@ void ServerStatTest::testOperatorOstream() localhost_http.setMultiConnectionAvgSpeed(102); localhost_http.setCounter(5); - std::stringstream ss; - - ss << localhost_http; - CPPUNIT_ASSERT_EQUAL (std::string ("host=localhost, protocol=http, dl_speed=90000," " sc_avg_speed=101, mc_avg_speed=102," " last_updated=1000, counter=5, status=OK"), - ss.str()); - - ss.str(""); + localhost_http.toString()); ServerStat localhost_ftp("localhost", "ftp"); localhost_ftp.setDownloadSpeed(10000); localhost_ftp.setLastUpdated(Time(1210000000)); localhost_ftp.setStatus("ERROR"); - ss << localhost_ftp; - CPPUNIT_ASSERT_EQUAL (std::string ("host=localhost, protocol=ftp, dl_speed=10000," " sc_avg_speed=0, mc_avg_speed=0," " last_updated=1210000000, counter=0, status=ERROR"), - ss.str()); - + localhost_ftp.toString()); } } // namespace aria2