/* */ #include "ConsoleStatCalc.h" #include "RequestGroupMan.h" #include "RequestGroup.h" #include "FileAllocationMan.h" #include "FileAllocationEntry.h" #include "CheckIntegrityMan.h" #include "CheckIntegrityEntry.h" #include "Util.h" #ifdef ENABLE_BITTORRENT # include "BtContext.h" #endif // ENABLE_BITTORRENT #ifdef HAVE_TERMIOS_H #include #endif // HAVE_TERMIOS_H #ifdef HAVE_SYS_IOCTL_H #include #endif // HAVE_SYS_IOCTL_H #include #include #include #include #include #include #include namespace aria2 { static void printProgress(std::ostream& o, const SharedHandle& rg) { TransferStat stat = rg->calculateStat(); unsigned int eta = 0; if(rg->getTotalLength() > 0 && stat.getDownloadSpeed() > 0) { eta = (rg->getTotalLength()-rg->getCompletedLength())/stat.getDownloadSpeed(); } o << "[" << "#" << rg->getGID() << " "; #ifdef ENABLE_BITTORRENT if(rg->downloadFinished() && !dynamic_pointer_cast(rg->getDownloadContext()).isNull()) { o << "SEEDING" << "(" << "ratio:" << std::fixed << std::setprecision(1) << ((stat.getAllTimeUploadLength()*10)/rg->getCompletedLength())/10.0 << ")"; } else #endif // ENABLE_BITTORRENT { o << "SIZE:" << Util::abbrevSize(rg->getCompletedLength()) << "B" << "/" << Util::abbrevSize(rg->getTotalLength()) << "B"; if(rg->getTotalLength() > 0) { o << "(" << 100*rg->getCompletedLength()/rg->getTotalLength() << "%)"; } } o << " " << "CN:" << rg->getNumConnection(); if(!rg->downloadFinished()) { o << " " << "SPD:" << std::fixed << std::setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s"; } if(stat.getSessionUploadLength() > 0) { o << " " << "UP:" << std::fixed << std::setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s" << "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << "B)"; } if(eta > 0) { o << " " << "ETA:" << Util::secfmt(eta); } o << "]"; } class PrintSummary { private: size_t _cols; public: PrintSummary(size_t cols):_cols(cols) {} void operator()(const SharedHandle& rg) { const char SEP_CHAR = '-'; printProgress(std::cout, rg); std::cout << "\n" << "FILE: " << rg->getFilePath() << "\n" << std::setfill(SEP_CHAR) << std::setw(_cols) << SEP_CHAR << "\n"; } }; static void printProgressSummary(const std::deque >& groups, size_t cols) { const char SEP_CHAR = '='; time_t now; time(&now); std::cout << " *** Download Progress Summary"; { time_t now; struct tm* staticNowtmPtr; char buf[26]; if(time(&now) != (time_t)-1 && (staticNowtmPtr = localtime(&now)) != 0 && asctime_r(staticNowtmPtr, buf) != 0) { char* lfptr = strchr(buf, '\n'); if(lfptr) { *lfptr = '\0'; } std::cout << " as of " << buf; } } std::cout << " *** " << "\n" << std::setfill(SEP_CHAR) << std::setw(cols) << SEP_CHAR << "\n"; std::for_each(groups.begin(), groups.end(), PrintSummary(cols)); } ConsoleStatCalc::ConsoleStatCalc(time_t summaryInterval): _summaryInterval(summaryInterval), _summaryIntervalCount(0) {} void ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan, const FileAllocationManHandle& fileAllocationMan, const CheckIntegrityManHandle& checkIntegrityMan) { if(!_cp.elapsed(1)) { return; } _cp.reset(); ++_summaryIntervalCount; bool isTTY = isatty(STDOUT_FILENO) == 1; unsigned short int cols = 80; if(isTTY) { #ifdef HAVE_TERMIOS_H struct winsize size; if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == 0) { cols = size.ws_col; } #endif // HAVE_TERMIOS_H std::cout << '\r' << std::setfill(' ') << std::setw(cols) << ' ' << '\r'; } std::ostringstream o; if(requestGroupMan->countRequestGroup() > 0) { if(_summaryInterval > 0 && _summaryIntervalCount%_summaryInterval == 0) { printProgressSummary(requestGroupMan->getRequestGroups(), cols); _summaryIntervalCount = 0; std::cout << "\n"; } RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0); printProgress(o, firstRequestGroup); if(requestGroupMan->countRequestGroup() > 1) { o << "(" << requestGroupMan->countRequestGroup()-1 << "more...)"; } } if(requestGroupMan->countRequestGroup() > 1 && !requestGroupMan->downloadFinished()) { TransferStat stat = requestGroupMan->calculateStat(); o << " " << "[TOTAL SPD:" << std::fixed << std::setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]"; } { FileAllocationEntryHandle entry = fileAllocationMan->getCurrentFileAllocationEntry(); if(!entry.isNull()) { o << " " << "[FileAlloc:" << "#" << entry->getRequestGroup()->getGID() << " " << Util::abbrevSize(entry->getCurrentLength()) << "B" << "/" << Util::abbrevSize(entry->getTotalLength()) << "B" << "("; if(entry->getTotalLength() > 0) { o << 100*entry->getCurrentLength()/entry->getTotalLength(); } else { o << "--"; } o << "%)" << "]"; if(fileAllocationMan->countFileAllocationEntryInQueue() > 0) { o << "(" << fileAllocationMan->countFileAllocationEntryInQueue() << "waiting...)"; } } } #ifdef ENABLE_MESSAGE_DIGEST { CheckIntegrityEntryHandle entry = checkIntegrityMan->getFirstCheckIntegrityEntry(); if(!entry.isNull()) { o << " " << "[Checksum:" << "#" << entry->getRequestGroup()->getGID() << " " << Util::abbrevSize(entry->getCurrentLength()) << "B" << "/" << Util::abbrevSize(entry->getTotalLength()) << "B" << "(" << 100*entry->getCurrentLength()/entry->getTotalLength() << "%)" << "]"; if(checkIntegrityMan->countCheckIntegrityEntry() > 1) { o << "(" << checkIntegrityMan->countCheckIntegrityEntry()-1 << "more...)"; } } } #endif // ENABLE_MESSAGE_DIGEST std::string readout = o.str(); if(isTTY) { std::string::iterator last = readout.begin(); if(readout.size() > cols) { std::advance(last, cols); } else { last = readout.end(); } std::copy(readout.begin(), last, std::ostream_iterator(std::cout)); std::cout << std::flush; } else { std::copy(readout.begin(), readout.end(), std::ostream_iterator(std::cout)); std::cout << std::endl; } } } // namespace aria2