Updated Progress Bar

pull/90/head
Blackrabbit 2016-09-10 18:50:35 +02:00
parent 422447fc19
commit 90d5ce823d
14 changed files with 224 additions and 148 deletions

View File

@ -127,6 +127,7 @@ int Main( int argc, char **argv )
( "ignore", po::value<std::string>(), "Perl RegExp to ignore files (matched against relative paths)." )
( "upload-speed,U", po::value<unsigned>(), "Limit upload speed in kbytes per second" )
( "download-speed,D", po::value<unsigned>(), "Limit download speed in kbytes per second" )
( "progress-bar", "Enable progress bar for upload/download of files")
;
po::variables_map vm;
@ -150,13 +151,16 @@ int Main( int argc, char **argv )
InitLog(vm) ;
Config config(vm) ;
Log( "config file name %1%", config.Filename(), log::verbose );
std::unique_ptr<http::Agent> http( new http::CurlAgent );
if ( vm.count( "log-http" ) )
http->SetLog( new http::ResponseLog( vm["log-http"].as<std::string>(), ".txt" ) );
ProgressBar *pb = new ProgressBar(vm.count( "progress-bar" ) != 0);
http->SetProgressBar(pb);
if ( vm.count( "auth" ) )
{
OAuth2 token( http.get(), client_id, client_secret ) ;
@ -179,6 +183,7 @@ int Main( int argc, char **argv )
config.Set( "refresh_token", Val( token.RefreshToken() ) ) ;
config.Save() ;
}
std::string refresh_token ;
try
@ -211,12 +216,17 @@ int Main( int argc, char **argv )
if ( vm.count( "dry-run" ) == 0 )
{
//The progress bar should just be enabled when actual file transfers take place
pb->SetShowProgressBar(true);
drive.Update() ;
pb->SetShowProgressBar(false);
drive.UpdateChangeStamp();
drive.SaveState() ;
}
else
drive.DryRun() ;
config.Save() ;
Log( "Finished!", log::info ) ;
return 0 ;

View File

@ -120,8 +120,6 @@ void Drive::Update()
{
Log( "Synchronizing files", log::info ) ;
m_state.Sync( m_syncer, m_options ) ;
UpdateChangeStamp( ) ;
}
void Drive::DryRun()

View File

@ -44,6 +44,7 @@ public :
void Update() ;
void DryRun() ;
void SaveState() ;
void UpdateChangeStamp() ;
struct Error : virtual Exception {} ;
@ -53,8 +54,7 @@ private :
void ReadChanges() ;
void FromRemote( const Entry& entry ) ;
void FromChange( const Entry& entry ) ;
void UpdateChangeStamp( ) ;
private :
Syncer *m_syncer ;
fs::path m_root ;

View File

@ -120,9 +120,9 @@ std::string Entry::Name() const
return !m_filename.empty() ? m_filename : m_title ;
}
long Entry::DownloadFileBytes() const
long Entry::Size() const
{
return m_downloadFileBytes;
return m_size ;
}
} // end of namespace gr

View File

@ -61,7 +61,7 @@ public :
const std::vector<std::string>& ParentHrefs() const ;
long DownloadFileBytes() const;
long Size() const ;
protected :
std::string m_title ;
@ -82,7 +82,7 @@ protected :
DateTime m_mtime ;
bool m_is_removed ;
long m_downloadFileBytes;
long m_size ;
} ;
} // end of namespace gr

View File

@ -149,7 +149,7 @@ void Resource::AssignIDs( const Entry& remote )
m_content = remote.ContentSrc() ;
m_is_editable = remote.IsEditable() ;
m_etag = remote.ETag() ;
m_downloadFileBytes = remote.DownloadFileBytes();
m_downloadFileBytes = remote.Size() ;
}
}

View File

@ -66,9 +66,12 @@ void Entry2::Update( const Val& item )
m_is_removed = file["labels"]["trashed"].Bool() ;
if (file.Has("fileSize"))
m_downloadFileBytes = file["fileSize"].U64() ;
else
m_downloadFileBytes = 0;
{
m_size = file["fileSize"].U64() ;
} else
{
m_size = 0;
}
if ( !m_is_dir )
{

View File

@ -22,6 +22,7 @@
#include <string>
#include "ResponseLog.hh"
#include "util/Types.hh"
#include "util/ProgressBar.hh"
namespace gr {
@ -86,6 +87,8 @@ public :
virtual std::string Escape( const std::string& str ) = 0 ;
virtual std::string Unescape( const std::string& str ) = 0 ;
virtual void SetProgressBar( ProgressBar* ) = 0;
} ;
} } // end of namespace

View File

@ -38,9 +38,6 @@
#include <iostream>
#include <signal.h>
#include <math.h>
#include <sys/ioctl.h>
#include <unistd.h>
namespace {
@ -113,11 +110,16 @@ void CurlAgent::SetLog(ResponseLog *log)
m_log.reset( log );
}
void CurlAgent::SetProgressBar(ProgressBar *progressbar)
{
m_pb.reset(progressbar);
}
std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis )
{
char *str = static_cast<char*>(ptr) ;
std::string line( str, str + size*nmemb ) ;
// Check for error (HTTP 400 and above)
if ( line.substr( 0, 5 ) == "HTTP/" && line[9] >= '4' )
pthis->m_pimpl->error = true;
@ -127,7 +129,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
if ( pthis->m_log.get() )
pthis->m_log->Write( str, size*nmemb );
static const std::string loc = "Location: " ;
std::size_t pos = line.find( loc ) ;
if ( pos != line.npos )
@ -135,7 +137,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
std::size_t end_pos = line.find( "\r\n", pos ) ;
pthis->m_pimpl->location = line.substr( loc.size(), end_pos - loc.size() ) ;
}
return size*nmemb ;
}
@ -146,9 +148,10 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
if ( pthis->m_log.get() )
pthis->m_log->Write( (const char*)ptr, size*nmemb );
if (pthis->totalDownlaodSize > 0) {
if ( pthis->totalDownloadSize > 0 )
{
pthis->downloadedBytes += (curl_off_t)size*nmemb;
CurlAgent::progress_callback(pthis, pthis->totalDownlaodSize, pthis->downloadedBytes, 0L, 0L);
CurlAgent::progress_callback(pthis, pthis->totalDownloadSize, pthis->downloadedBytes, 0L, 0L);
}
if ( pthis->m_pimpl->error && pthis->m_pimpl->error_data.size() < 65536 )
@ -161,101 +164,10 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
}
unsigned short int CurlAgent::DetermineTerminalSize() {
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_col;
}
std::string CurlAgent::CalculateByteSize(curl_off_t bytes, bool withSuffix) {
long double KB = bytes / 1024;
long double MB = KB / 1024;
long double GB = MB / 1024;
std::string res;
std::string suffix;
std::ostringstream ss;
ss << std::fixed << std::setprecision(2);
if (GB > 1) {
ss << GB;
suffix = "GB";
}
else if (MB > 1) {
ss << MB;
suffix = "MB";
} else {
ss << KB;
suffix = "KB";
}
res = ss.str() + (withSuffix ? suffix : "");
return res;
}
int CurlAgent::progress_callback(void *ptr, curl_off_t TotalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t TotalToUpload, curl_off_t NowUploaded) {
curl_off_t processed = (TotalDownloadSize > TotalToUpload) ? finishedDownloadSize : NowUploaded;
curl_off_t total = (TotalDownloadSize > TotalToUpload) ? TotalDownloadSize : TotalToUpload;
if (total <= 0.0)
return 0;
//libcurl seems to process more bytes then the actual file size :)
if (processed > total)
processed = total;
int availableSize = CurlAgent::DetermineTerminalSize() - 30; //10 for prefix of percent and 20 for suffix of file size
int totalDots;
if (availableSize > 100)
totalDots = 100;
else if (availableSize < 0)
totalDots = 10;
else
totalDots = availableSize;
double fraction = (float)processed / total;
if ((fraction*100) < 100.0)
((CurlAgent*)ptr)->hundredpercentDone = false;
if (!((CurlAgent*)ptr)->hundredpercentDone) {
printf("\33[2K\r"); //delete previous output line
int dotz = round(fraction * totalDots);
int count=0;
printf(" [%3.0f%%] [", fraction*100);
for (; count < dotz-1; count++) {
printf("=");
}
printf(">");
for (; count < totalDots-1; count++) {
printf(" ");
}
printf("] ");
printf("%s/%s", CalculateByteSize(processed, false).c_str(), CalculateByteSize(total, true).c_str());
printf("\r");
if ((fraction*100) >= 100.0) {
((CurlAgent*)ptr)->hundredpercentDone = true;
printf("\n");
}
fflush(stdout);
}
return 0;
int CurlAgent::progress_callback(void *ptr, curl_off_t totalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t totalToUpload, curl_off_t finishedUploaded)
{
((CurlAgent*)ptr)->m_pb->PrintProgressBar(totalDownloadSize, finishedDownloadSize, totalToUpload, finishedUploaded);
return 0;
}
@ -276,11 +188,9 @@ long CurlAgent::ExecCurl(
struct curl_slist *slist = SetHeader( m_pimpl->curl, hdr ) ;
if (progressBar) {
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
}
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
CURLcode curl_code = ::curl_easy_perform(curl);
@ -324,8 +234,8 @@ long CurlAgent::Request(
Init() ;
CURL *curl = m_pimpl->curl ;
progressBar = false;
totalDownlaodSize = 0;
this->totalDownloadSize = downloadFileBytes;
// set common options
::curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str() );
@ -335,17 +245,6 @@ long CurlAgent::Request(
::curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadFileCallback ) ;
::curl_easy_setopt(curl, CURLOPT_READDATA , in ) ;
::curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>( in->Size() ) ) ;
if (url.compare("https://accounts.google.com/o/oauth2/token"))
progressBar = true;
else
progressBar = false;
} else {
if (!boost::starts_with(url, "https://www.googleapis.com/")) {
progressBar = true;
totalDownlaodSize = downloadFileBytes;
} else
progressBar = false;
}
return ExecCurl( url, dest, hdr ) ;

View File

@ -46,6 +46,7 @@ public :
ResponseLog* GetLog() const ;
void SetLog( ResponseLog *log ) ;
void SetProgressBar( ProgressBar *progressbar) ;
long Request(
const std::string& method,
@ -62,13 +63,8 @@ public :
std::string Escape( const std::string& str ) ;
std::string Unescape( const std::string& str ) ;
bool hundredpercentDone;
long totalDownlaodSize;
long downloadedBytes;
static int progress_callback(void *ptr, curl_off_t TotalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t TotalToUpload, curl_off_t NowUploaded);
static std::string CalculateByteSize(curl_off_t bytes, bool withSuffix);
static unsigned short int DetermineTerminalSize() ;
private :
static std::size_t HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis ) ;
@ -83,14 +79,12 @@ private :
private :
struct Impl ;
<<<<<<< 357d7ac833ece9e279242b3608c157a691709dc3
std::unique_ptr<Impl> m_pimpl ;
std::unique_ptr<ResponseLog> m_log ;
=======
std::auto_ptr<Impl> m_pimpl ;
std::auto_ptr<ResponseLog> m_log ;
bool progressBar ;
>>>>>>> Progress bar for upload/download of files
std::unique_ptr<Impl> m_pimpl ;
std::unique_ptr<ResponseLog> m_log ;
std::unique_ptr<ProgressBar> m_pb ;
long totalDownloadSize;
long downloadedBytes;
} ;
} } // end of namespace

View File

@ -48,6 +48,11 @@ void AuthAgent::SetLog( http::ResponseLog *log )
return m_agent->SetLog( log );
}
void AuthAgent::SetProgressBar( ProgressBar *progressbar )
{
return m_agent->SetProgressBar( progressbar );
}
void AuthAgent::SetUploadSpeed( unsigned kbytes )
{
m_agent->SetUploadSpeed( kbytes );

View File

@ -58,6 +58,8 @@ public :
void SetUploadSpeed( unsigned kbytes ) ;
void SetDownloadSpeed( unsigned kbytes ) ;
void SetProgressBar( ProgressBar *progressbar ) ;
private :
http::Header AppendHeader( const http::Header& hdr ) const ;
bool CheckRetry( long response ) ;

View File

@ -0,0 +1,133 @@
#include "ProgressBar.hh"
#include <sys/ioctl.h>
#include <math.h>
#include <unistd.h>
#include <sstream>
#include <iomanip>
#include <iostream>
namespace gr
{
ProgressBar::ProgressBar(bool enable_parameter)
{
this->progressBar_enabled = enable_parameter;
}
ProgressBar::~ProgressBar()
{
}
void ProgressBar::SetShowProgressBar(bool showProgressBar)
{
this->showProgressBar = showProgressBar;
}
unsigned short int ProgressBar::DetermineTerminalSize()
{
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
return w.ws_col;
}
std::string ProgressBar::CalculateByteSize(long bytes)
{
long double KB = bytes / 1024;
long double MB = KB / 1024;
long double GB = MB / 1024;
std::string res;
std::string suffix;
std::ostringstream ss;
ss << std::fixed << std::setprecision(2);
if (GB > 1)
{
ss << GB;
suffix = "GB";
}
else if (MB > 1)
{
ss << MB;
suffix = "MB";
}
else
{
ss << KB;
suffix = "KB";
}
res = ss.str() + suffix;
return res;
}
void ProgressBar::PrintProgressBar(long TotalDownloadSize, long finishedDownloadSize, long TotalToUpload, long NowUploaded)
{
if (this->showProgressBar && this->progressBar_enabled)
{
long processed = (TotalDownloadSize > TotalToUpload) ? finishedDownloadSize : NowUploaded;
long total = (TotalDownloadSize > TotalToUpload) ? TotalDownloadSize : TotalToUpload;
if (total <= 0.0)
return;
//libcurl seems to process more bytes then the actual file size :)
if (processed > total)
processed = total;
int availableSize = this->DetermineTerminalSize() - 32; //10 for prefix of percent and 22 for suffix of file size
int totalDots;
if (availableSize > 100)
totalDots = 100;
else if (availableSize < 0)
totalDots = 10;
else
totalDots = availableSize;
double fraction = (float) processed / total;
if ((fraction * 100) < 100.0)
this->hundredpercentDone = false;
if (!this->hundredpercentDone)
{
printf("\33[2K\r"); //delete previous output line
int dotz = round(fraction * totalDots);
int count = 0;
printf(" [%3.0f%%] [", fraction * 100);
for (; count < dotz - 1; count++)
{
printf("=");
}
printf(">");
for (; count < totalDots - 1; count++)
{
printf(" ");
}
printf("] ");
printf("%s/%s", this->CalculateByteSize(processed).c_str(), this->CalculateByteSize(total).c_str());
printf("\r");
if ((fraction * 100) >= 100.0)
{
this->hundredpercentDone = true;
printf("\n");
}
fflush(stdout);
}
}
}
}

View File

@ -0,0 +1,29 @@
#include <string>
#pragma once
namespace gr
{
class ProgressBar
{
public:
ProgressBar(bool enable_parameter);
virtual ~ProgressBar();
void PrintProgressBar(long TotalDownloadSize, long finishedDownloadSize, long TotalToUpload, long NowUploaded);
void SetShowProgressBar(bool showProgressBar);
private:
static std::string CalculateByteSize(long bytes);
static unsigned short int DetermineTerminalSize();
bool hundredpercentDone = false;
bool showProgressBar = false;
bool progressBar_enabled = false;
};
}
;