[thin_restore] Add a progress monitor

This commit is contained in:
Joe Thornber 2014-08-05 11:47:57 +01:00
parent f534664f96
commit fccc1dfcb0
6 changed files with 134 additions and 4 deletions

View File

@ -46,6 +46,7 @@ SOURCE=\
base/base64.cc \
base/endian_utils.cc \
base/error_state.cc \
base/progress_monitor.cc \
\
caching/hint_array.cc \
caching/superblock.cc \
@ -377,6 +378,7 @@ ERA_DUMP_SOURCE=\
base/base64.cc \
base/error_state.cc \
base/endian_utils.cc \
base/progress_monitor.cc \
\
era/writeset_tree.cc \
era/era_detail.cc \

75
base/progress_monitor.cc Normal file
View File

@ -0,0 +1,75 @@
#include "base/progress_monitor.h"
#include <iostream>
//----------------------------------------------------------------
namespace {
using namespace std;
class progress_bar : public base::progress_monitor {
public:
progress_bar(string const &title)
: title_(title),
progress_width_(50),
spinner_(0) {
update_percent(0);
}
void update_percent(unsigned p) {
unsigned nr_equals = max<unsigned>(progress_width_ * p / 100, 1);
unsigned nr_spaces = progress_width_ - nr_equals;
cout << title_ << ": [";
for (unsigned i = 0; i < nr_equals - 1; i++)
cout << '=';
if (nr_equals < progress_width_)
cout << '>';
for (unsigned i = 0; i < nr_spaces; i++)
cout << ' ';
cout << "] " << spinner_char() << " " << p << "%\r" << flush;
spinner_++;
}
private:
char spinner_char() const {
char cs[] = {'|', '/', '-', '\\'};
unsigned index = spinner_ % sizeof(cs);
return cs[index];
}
std::string title_;
unsigned progress_width_;
unsigned spinner_;
};
class quiet_progress : public base::progress_monitor {
public:
void update_percent(unsigned p) {
}
};
}
//----------------------------------------------------------------
base::progress_monitor::ptr
base::create_progress_bar(std::string const &title)
{
return progress_monitor::ptr(new progress_bar(title));
}
base::progress_monitor::ptr
base::create_quiet_progress_monitor()
{
return progress_monitor::ptr(new quiet_progress());
}
//----------------------------------------------------------------

25
base/progress_monitor.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef BASE_PROGRESS_MONITOR_H
#define BASE_PROGRESS_MONITOR_H
#include <boost/shared_ptr.hpp>
#include <string>
//----------------------------------------------------------------
namespace base {
class progress_monitor {
public:
typedef boost::shared_ptr<progress_monitor> ptr;
virtual ~progress_monitor() {}
virtual void update_percent(unsigned) = 0;
};
progress_monitor::ptr create_progress_bar(std::string const &title);
progress_monitor::ptr create_quiet_progress_monitor();
}
//----------------------------------------------------------------
#endif

View File

@ -41,6 +41,24 @@ using namespace thin_provisioning;
//----------------------------------------------------------------
namespace {
size_t get_file_length(string const &file) {
struct stat info;
int r;
r = ::stat(file.c_str(), &info);
if (r)
throw runtime_error("Couldn't stat backup path");
return info.st_size;
}
progress_monitor::ptr create_monitor() {
if (isatty(fileno(stdout)))
return create_progress_bar("Restoring");
else
return create_quiet_progress_monitor();
}
int restore(string const &backup_file, string const &dev) {
try {
// The block size gets updated by the restorer.
@ -49,7 +67,9 @@ namespace {
check_file_exists(backup_file);
ifstream in(backup_file.c_str(), ifstream::in);
parse_xml(in, restorer);
progress_monitor::ptr monitor = create_monitor();
parse_xml(in, restorer, get_file_length(backup_file), monitor);
} catch (std::exception &e) {
cerr << e.what() << endl;

View File

@ -256,7 +256,8 @@ tp::create_xml_emitter(ostream &out)
}
void
tp::parse_xml(std::istream &in, emitter::ptr e)
tp::parse_xml(std::istream &in, emitter::ptr e,
size_t input_length, base::progress_monitor::ptr monitor)
{
XML_Parser parser = XML_ParserCreate(NULL);
if (!parser)
@ -265,8 +266,10 @@ tp::parse_xml(std::istream &in, emitter::ptr e)
XML_SetUserData(parser, e.get());
XML_SetElementHandler(parser, start_tag, end_tag);
size_t total = 0;
while (!in.eof()) {
char buffer[4096];
char buffer[1024 * 1024];
in.read(buffer, sizeof(buffer));
size_t len = in.gcount();
int done = in.eof();
@ -280,6 +283,9 @@ tp::parse_xml(std::istream &in, emitter::ptr e)
<< endl;
throw runtime_error(out.str());
}
total += len;
monitor->update_percent(total * 100 / input_length);
}
}

View File

@ -20,6 +20,7 @@
#define XML_FORMAT_H
#include "emitter.h"
#include "base/progress_monitor.h"
#include <iosfwd>
@ -27,7 +28,8 @@
namespace thin_provisioning {
emitter::ptr create_xml_emitter(std::ostream &out);
void parse_xml(std::istream &in, emitter::ptr e);
void parse_xml(std::istream &in, emitter::ptr e,
size_t input_length, base::progress_monitor::ptr p);
}
//----------------------------------------------------------------