|
@@ -48,9 +48,113 @@
|
|
|
#include <unistd.h>
|
|
|
#include <iomanip>
|
|
|
#include <iostream>
|
|
|
+#include <algorithm>
|
|
|
+#include <cstring>
|
|
|
+#include <sstream>
|
|
|
+#include <iterator>
|
|
|
|
|
|
namespace aria2 {
|
|
|
|
|
|
+static void printProgress(std::ostream& o, const SharedHandle<RequestGroup>& 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<BtContext>(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<RequestGroup>& 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<SharedHandle<RequestGroup> >& 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,
|
|
@@ -60,104 +164,67 @@ ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
|
|
|
return;
|
|
|
}
|
|
|
_cp.reset();
|
|
|
+ ++_summaryIntervalCount;
|
|
|
+
|
|
|
bool isTTY = isatty(STDOUT_FILENO) == 1;
|
|
|
+ unsigned short int cols = 80;
|
|
|
if(isTTY) {
|
|
|
struct winsize size;
|
|
|
- if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == -1) {
|
|
|
- size.ws_col = 80;
|
|
|
+ if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) == 0) {
|
|
|
+ cols = size.ws_col;
|
|
|
}
|
|
|
- std::cout << '\r' << std::setw(size.ws_col) << ' ' << '\r';
|
|
|
+ std::cout << '\r' << std::setfill(' ') << std::setw(cols) << ' ' << '\r';
|
|
|
}
|
|
|
+ std::ostringstream o;
|
|
|
if(requestGroupMan->countRequestGroup() > 0) {
|
|
|
- RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0);
|
|
|
- TransferStat stat = firstRequestGroup->calculateStat();
|
|
|
- unsigned int eta = 0;
|
|
|
- if(firstRequestGroup->getTotalLength() > 0 && stat.getDownloadSpeed() > 0) {
|
|
|
- eta = (firstRequestGroup->getTotalLength()-firstRequestGroup->getCompletedLength())/stat.getDownloadSpeed();
|
|
|
+ if(_summaryInterval > 0 && _summaryIntervalCount%_summaryInterval == 0) {
|
|
|
+ printProgressSummary(requestGroupMan->getRequestGroups(), cols);
|
|
|
+ _summaryIntervalCount = 0;
|
|
|
+ std::cout << "\n";
|
|
|
}
|
|
|
|
|
|
- std::cout << "["
|
|
|
- << "#" << firstRequestGroup->getGID() << " ";
|
|
|
-#ifdef ENABLE_BITTORRENT
|
|
|
- if(firstRequestGroup->downloadFinished() &&
|
|
|
- !dynamic_pointer_cast<BtContext>(firstRequestGroup->getDownloadContext()).isNull()) {
|
|
|
- std::cout << "SEEDING" << "(" << "ratio:"
|
|
|
- << std::fixed << std::setprecision(1)
|
|
|
- << ((stat.getAllTimeUploadLength()*10)/firstRequestGroup->getCompletedLength())/10.0
|
|
|
- << ")";
|
|
|
- } else
|
|
|
-#endif // ENABLE_BITTORRENT
|
|
|
- {
|
|
|
- std::cout << "SIZE:"
|
|
|
- << Util::abbrevSize(firstRequestGroup->getCompletedLength())
|
|
|
- << "B"
|
|
|
- << "/"
|
|
|
- << Util::abbrevSize(firstRequestGroup->getTotalLength())
|
|
|
- << "B";
|
|
|
- if(firstRequestGroup->getTotalLength() > 0) {
|
|
|
- std::cout << "("
|
|
|
- << 100*firstRequestGroup->getCompletedLength()/firstRequestGroup->getTotalLength()
|
|
|
- << "%)";
|
|
|
- }
|
|
|
- }
|
|
|
- std::cout << " "
|
|
|
- << "CN:"
|
|
|
- << firstRequestGroup->getNumConnection();
|
|
|
- if(!firstRequestGroup->downloadFinished()) {
|
|
|
- std::cout << " "
|
|
|
- << "SPD:"
|
|
|
- << std::fixed << std::setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s";
|
|
|
- }
|
|
|
- if(stat.getSessionUploadLength() > 0) {
|
|
|
- std::cout << " "
|
|
|
- << "UP:"
|
|
|
- << std::fixed << std::setprecision(2) << stat.getUploadSpeed()/1024.0 << "KiB/s"
|
|
|
- << "(" << Util::abbrevSize(stat.getAllTimeUploadLength()) << "B)";
|
|
|
- }
|
|
|
- if(eta > 0) {
|
|
|
- std::cout << " "
|
|
|
- << "ETA:"
|
|
|
- << Util::secfmt(eta);
|
|
|
- }
|
|
|
- std::cout << "]";
|
|
|
+ RequestGroupHandle firstRequestGroup = requestGroupMan->getRequestGroup(0);
|
|
|
+
|
|
|
+ printProgress(o, firstRequestGroup);
|
|
|
+
|
|
|
if(requestGroupMan->countRequestGroup() > 1) {
|
|
|
- std::cout << "("
|
|
|
- << requestGroupMan->countRequestGroup()-1
|
|
|
- << "more...)";
|
|
|
+ o << "("
|
|
|
+ << requestGroupMan->countRequestGroup()-1
|
|
|
+ << "more...)";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if(requestGroupMan->countRequestGroup() > 1 &&
|
|
|
!requestGroupMan->downloadFinished()) {
|
|
|
TransferStat stat = requestGroupMan->calculateStat();
|
|
|
- std::cout << " "
|
|
|
- << "[TOTAL SPD:"
|
|
|
- << std::fixed << std::setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]";
|
|
|
+ o << " "
|
|
|
+ << "[TOTAL SPD:"
|
|
|
+ << std::fixed << std::setprecision(2) << stat.getDownloadSpeed()/1024.0 << "KiB/s" << "]";
|
|
|
}
|
|
|
|
|
|
{
|
|
|
FileAllocationEntryHandle entry = fileAllocationMan->getCurrentFileAllocationEntry();
|
|
|
if(!entry.isNull()) {
|
|
|
- std::cout << " "
|
|
|
- << "[FileAlloc:"
|
|
|
- << "#" << entry->getRequestGroup()->getGID() << " "
|
|
|
- << Util::abbrevSize(entry->getCurrentLength())
|
|
|
- << "B"
|
|
|
- << "/"
|
|
|
- << Util::abbrevSize(entry->getTotalLength())
|
|
|
- << "B"
|
|
|
- << "(";
|
|
|
+ o << " "
|
|
|
+ << "[FileAlloc:"
|
|
|
+ << "#" << entry->getRequestGroup()->getGID() << " "
|
|
|
+ << Util::abbrevSize(entry->getCurrentLength())
|
|
|
+ << "B"
|
|
|
+ << "/"
|
|
|
+ << Util::abbrevSize(entry->getTotalLength())
|
|
|
+ << "B"
|
|
|
+ << "(";
|
|
|
if(entry->getTotalLength() > 0) {
|
|
|
- std::cout << 100*entry->getCurrentLength()/entry->getTotalLength();
|
|
|
+ o << 100*entry->getCurrentLength()/entry->getTotalLength();
|
|
|
} else {
|
|
|
- std::cout << "--";
|
|
|
+ o << "--";
|
|
|
}
|
|
|
- std::cout << "%)"
|
|
|
- << "]";
|
|
|
+ o << "%)"
|
|
|
+ << "]";
|
|
|
if(fileAllocationMan->countFileAllocationEntryInQueue() > 0) {
|
|
|
- std::cout << "("
|
|
|
- << fileAllocationMan->countFileAllocationEntryInQueue()
|
|
|
- << "waiting...)";
|
|
|
+ o << "("
|
|
|
+ << fileAllocationMan->countFileAllocationEntryInQueue()
|
|
|
+ << "waiting...)";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -165,29 +232,38 @@ ConsoleStatCalc::calculateStat(const RequestGroupManHandle& requestGroupMan,
|
|
|
{
|
|
|
CheckIntegrityEntryHandle entry = checkIntegrityMan->getFirstCheckIntegrityEntry();
|
|
|
if(!entry.isNull()) {
|
|
|
- std::cout << " "
|
|
|
- << "[Checksum:"
|
|
|
- << "#" << entry->getRequestGroup()->getGID() << " "
|
|
|
- << Util::abbrevSize(entry->getCurrentLength())
|
|
|
- << "B"
|
|
|
- << "/"
|
|
|
- << Util::abbrevSize(entry->getTotalLength())
|
|
|
- << "B"
|
|
|
- << "("
|
|
|
- << 100*entry->getCurrentLength()/entry->getTotalLength()
|
|
|
- << "%)";
|
|
|
- std::cout << "]";
|
|
|
+ o << " "
|
|
|
+ << "[Checksum:"
|
|
|
+ << "#" << entry->getRequestGroup()->getGID() << " "
|
|
|
+ << Util::abbrevSize(entry->getCurrentLength())
|
|
|
+ << "B"
|
|
|
+ << "/"
|
|
|
+ << Util::abbrevSize(entry->getTotalLength())
|
|
|
+ << "B"
|
|
|
+ << "("
|
|
|
+ << 100*entry->getCurrentLength()/entry->getTotalLength()
|
|
|
+ << "%)"
|
|
|
+ << "]";
|
|
|
if(checkIntegrityMan->countCheckIntegrityEntry() > 1) {
|
|
|
- std::cout << "("
|
|
|
- << checkIntegrityMan->countCheckIntegrityEntry()-1
|
|
|
- << "more...)";
|
|
|
+ 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<char>(std::cout));
|
|
|
std::cout << std::flush;
|
|
|
} else {
|
|
|
+ std::copy(readout.begin(), readout.end(), std::ostream_iterator<char>(std::cout));
|
|
|
std::cout << std::endl;
|
|
|
}
|
|
|
}
|