00001 #include "config.h"
00002
00003 #include <iostream>
00004 #include <string>
00005 #include <vector>
00006 #include <algorithm>
00007
00008 #include "asserts.h"
00009 #include "error.h"
00010 #include "estring.h"
00011 #include "fs.h"
00012 #include "rconfig.h"
00013 #include "timer.h"
00014 #include "logger.h"
00015 #include "estat.h"
00016 #include "vaulter.h"
00017 #include "strfmt.h"
00018 #include "archiver.h"
00019 #include "table.h"
00020
00021 #include "reporter.h"
00022
00023
00024
00025
00026 vault_stats_report::vault_stats_report()
00027 {
00028 clear();
00029 }
00030
00031
00032 vault_stats_report::vault_stats_report(const vault_stats_report& a_class)
00033 {
00034 clear();
00035 assign(a_class);
00036 }
00037
00038
00039 vault_stats_report::vault_stats_report(
00040 const std::string& a_message,
00041 const filesystem& a_class
00042 )
00043 {
00044 clear();
00045 assign(a_message,a_class);
00046 }
00047
00048
00049 vault_stats_report::~vault_stats_report()
00050 {
00051 }
00052
00053
00054 void vault_stats_report::clear(void)
00055 {
00056 m_total_blocks = 0;
00057 m_free_blocks = 0;
00058 m_total_inodes = 0;
00059 m_free_inodes = 0;
00060 }
00061
00062
00063 void vault_stats_report::assign(
00064 const vault_stats_report& a_class
00065 )
00066 {
00067 assign(
00068 a_class.message(),
00069 a_class.time(),
00070 a_class.total_blocks(),
00071 a_class.free_blocks(),
00072 a_class.total_inodes(),
00073 a_class.free_inodes()
00074 );
00075 }
00076
00077
00078 void vault_stats_report::assign(
00079 const std::string& a_message,
00080 const filesystem& a_class
00081 )
00082 {
00083 assign(
00084 a_message,
00085 current_time(),
00086 a_class.total_blocks(),
00087 a_class.free_blocks(),
00088 a_class.total_inodes(),
00089 a_class.free_inodes()
00090 );
00091 }
00092
00093
00094 void vault_stats_report::assign(
00095 const std::string& a_message,
00096 const std::string& a_time,
00097 const uint64 a_total_blocks,
00098 const uint64 a_free_blocks,
00099 const uint64 a_total_inodes,
00100 const uint64 a_free_inodes
00101 )
00102 {
00103 TRY_nomem(m_message = a_message);
00104 m_total_blocks = a_total_blocks;
00105 m_free_blocks = a_free_blocks;
00106 m_total_inodes = a_total_inodes;
00107 m_free_inodes = a_free_inodes;
00108
00109 TRY_nomem(m_time = a_time);
00110 }
00111
00112
00113 const std::string& vault_stats_report::time(void) const
00114 {
00115 return(m_time);
00116 }
00117
00118
00119 const std::string& vault_stats_report::message(void) const
00120 {
00121 return(m_message);
00122 }
00123
00124
00125 const uint64 vault_stats_report::total_blocks(void) const
00126 {
00127 return(m_total_blocks);
00128 }
00129
00130
00131 const uint64 vault_stats_report::free_blocks(void) const
00132 {
00133 return(m_free_blocks);
00134 }
00135
00136
00137 const uint64 vault_stats_report::total_inodes(void) const
00138 {
00139 return(m_total_inodes);
00140 }
00141
00142
00143 const uint64 vault_stats_report::free_inodes(void) const
00144 {
00145 return(m_free_inodes);
00146 }
00147
00148
00149 vault_stats_report&
00150 vault_stats_report::operator=(const vault_stats_report& a_class)
00151 {
00152 assign(a_class);
00153 return(*this);
00154 }
00155
00156
00157
00158
00159 vault_report::vault_report()
00160 {
00161 clear();
00162 }
00163
00164
00165 vault_report::~vault_report()
00166 {
00167 }
00168
00169
00170 void vault_report::clear(void)
00171 {
00172 m_reports.clear();
00173 }
00174
00175
00176 void vault_report::add_report(
00177 const vault_stats_report& a_class
00178 )
00179 {
00180 TRY_nomem(m_reports.push_back(a_class));
00181 }
00182
00183
00184 void vault_report::write_report(std::ostream& out)
00185 {
00186 table tab, tab2;
00187 estring estr;
00188 std::vector<vault_stats_report>::const_iterator vi;
00189 uint64 ui64b, ui64e, ui64t;
00190
00191 estr = "Vault Statistics";
00192 estr.align(estring::center);
00193 tab << estr << table_endl;
00194
00195 estr = "";
00196 estr.fillchar('-');
00197 estr.align(estring::left);
00198 tab << estr << table_endl;
00199
00200
00201 tab2
00202 << "Time"
00203 << " "
00204 << "Message"
00205 << " "
00206 << "Free Blocks"
00207 << " "
00208 << "Free Inodes"
00209 << " "
00210 << table_endl;
00211
00212
00213 estr.align(estring::left);
00214 estr.fillchar('-');
00215 estr = "";
00216 tab2
00217 << estr
00218 << " "
00219 << estr
00220 << " "
00221 << estr
00222 << " "
00223 << estr
00224 << table_endl;
00225
00226
00227 estr.fillchar(' ');
00228 for (vi = m_reports.begin(); vi != m_reports.end(); ++vi) {
00229 tab2
00230 << vi->time()
00231 << " ";
00232
00233 estr.align(estring::right);
00234 estr = vi->message();
00235 tab2 << estr;
00236
00237 tab2 << " ";
00238
00239 estr.align(estring::center);
00240
00241 estr = " ";
00242 estr += percent_string(vi->free_blocks(), vi->total_blocks());
00243 tab2 << estr;
00244
00245 tab2 << " ";
00246
00247 estr = " ";
00248 estr += percent_string(vi->free_inodes(), vi->total_inodes());
00249 tab2 << estr;
00250
00251 tab2 << table_endl;
00252 }
00253
00254
00255 estr.align(estring::left);
00256 estr.fillchar('-');
00257 estr = "";
00258 tab2
00259 << " "
00260 << " "
00261 << " "
00262 << " "
00263 << estr
00264 << " "
00265 << estr
00266 << table_endl;
00267
00268
00269 estr.align(estring::right);
00270 estr.fillchar(' ');
00271 estr = "Total Difference:";
00272
00273
00274 tab2
00275 << " "
00276 << " "
00277 << estr
00278 << " ";
00279
00280 estr.align(estring::center);
00281 ASSERT(m_reports.size() > 0);
00282 ui64b = m_reports[0].free_blocks();
00283 ui64e = m_reports[m_reports.size()-1].free_blocks();
00284 ui64t = m_reports[0].total_blocks();
00285 if (ui64b > ui64e) {
00286 estr = "-";
00287 estr += percent_string(ui64b - ui64e, ui64t);
00288 }
00289 else {
00290 estr = "+";
00291 estr += percent_string(ui64e - ui64b, ui64t);
00292 }
00293 tab2 << estr;
00294
00295 tab2 << " ";
00296
00297 ui64b = m_reports[0].free_inodes();
00298 ui64e = m_reports[m_reports.size()-1].free_inodes();
00299 ui64t = m_reports[0].total_inodes();
00300 if (ui64b > ui64e) {
00301 estr = "-";
00302 estr += percent_string(ui64b - ui64e, ui64t);
00303 }
00304 else {
00305 estr = "+";
00306 estr += percent_string(ui64e - ui64b, ui64t);
00307 }
00308 tab2 << estr;
00309
00310 tab2 << table_endl;
00311
00312 tab << tab2;
00313
00314 out << tab;
00315 }
00316
00317
00318 void vault_report::format_synopsis(table& a_table)
00319 {
00320 estring estr;
00321
00322 estr.align(estring::right);
00323 estr = "Timestamp:";
00324 a_table << estr << " " << config.timestamp().str() << table_endl;
00325
00326 estr = "Vault Selected:";
00327 a_table << estr << " " << vaulter.vault() << table_endl;
00328 }
00329
00330
00331
00332
00333 job_path_report::job_path_report()
00334 {
00335 clear();
00336 }
00337
00338
00339 job_path_report::job_path_report(const job_path_report& a_class)
00340 {
00341 clear();
00342 assign(a_class);
00343 }
00344
00345
00346 job_path_report::job_path_report(
00347 const std::string a_source,
00348 const timer a_time,
00349 const uint16 a_exit_code,
00350 const uint16 a_signal_num,
00351 const rsync_behavior::value_type a_behavior,
00352 const std::string a_error_message
00353 )
00354 {
00355 clear();
00356 assign(
00357 a_source,
00358 a_time,
00359 a_exit_code,
00360 a_signal_num,
00361 a_behavior,
00362 a_error_message
00363 );
00364 }
00365
00366
00367 job_path_report::~job_path_report()
00368 {
00369 }
00370
00371
00372 void job_path_report::clear(void)
00373 {
00374 m_source.erase();
00375 m_time.clear();
00376 m_exit_code = 0;
00377 m_signal_num = 0;
00378 m_error_msg.erase();
00379 m_behavior = rsync_behavior::retry;
00380 }
00381
00382
00383 void job_path_report::assign(const job_path_report& a_class)
00384 {
00385 assign(
00386 a_class.m_source,
00387 a_class.m_time,
00388 a_class.m_exit_code,
00389 a_class.m_signal_num,
00390 a_class.m_behavior,
00391 a_class.m_error_msg
00392 );
00393 }
00394
00395
00396 void job_path_report::assign(
00397 const std::string a_source,
00398 const timer a_time,
00399 const uint16 a_exit_code,
00400 const uint16 a_signal_num,
00401 const rsync_behavior::value_type a_behavior,
00402 const std::string a_error_message
00403 )
00404 {
00405 TRY_nomem(m_source = a_source);
00406 TRY_nomem(m_error_msg = a_error_message);
00407 TRY_nomem(m_time = a_time);
00408 m_exit_code = a_exit_code;
00409 m_signal_num = a_signal_num;
00410 m_behavior = a_behavior;
00411 }
00412
00413
00414 const bool job_path_report::status(void) const
00415 {
00416
00417
00418
00419
00420
00421
00422
00423 if (
00424
00425
00426
00427
00428 ((m_exit_code == 0) || (m_behavior == rsync_behavior::ok))
00429 && (m_signal_num == 0)
00430 ) {
00431
00432 return(true);
00433 }
00434
00435 return(false);
00436 }
00437
00438
00439 void job_path_report::source(const std::string& a_class)
00440 {
00441 TRY_nomem(m_source = a_class);
00442 }
00443
00444
00445 const std::string& job_path_report::source(void) const
00446 {
00447 return(m_source);
00448 }
00449
00450
00451 void job_path_report::time(const timer& a_class)
00452 {
00453 TRY_nomem(m_time = a_class);
00454 }
00455
00456
00457 const timer& job_path_report::time(void) const
00458 {
00459 return(m_time);
00460 }
00461
00462
00463 void job_path_report::exit_code(const int a_exit_code)
00464 {
00465 m_exit_code = a_exit_code;
00466 }
00467
00468
00469 const int job_path_report::exit_code(void) const
00470 {
00471 return(m_exit_code);
00472 }
00473
00474
00475 void job_path_report::signal_num(const int a_signal_num)
00476 {
00477 m_signal_num = a_signal_num;
00478 }
00479
00480
00481 const int job_path_report::signal_num(void) const
00482 {
00483 return(m_signal_num);
00484 }
00485
00486
00487 void job_path_report::error_msg(const std::string& a_class)
00488 {
00489 TRY_nomem(m_error_msg = a_class);
00490 }
00491
00492
00493 const std::string& job_path_report::error_msg(void) const
00494 {
00495 return(m_error_msg);
00496 }
00497
00498
00499 job_path_report& job_path_report::operator=(const job_path_report& a_class)
00500 {
00501 assign(a_class);
00502 return(*this);
00503 }
00504
00505
00506
00507
00508 const char *reportio::tags[] = {
00509 "[RSYNC]: ",
00510 "[REPORT]: ",
00511 0
00512 };
00513
00514
00515
00516 void reportio::write_rsync_out(const std::string& a_str)
00517 {
00518 std::cout.flush();
00519 std::cout << tags[rsync] << a_str << std::endl;
00520 std::cout.flush();
00521 }
00522
00523
00524
00525 void reportio::write_rsync_err(const std::string& a_str)
00526 {
00527 std::cerr.flush();
00528 std::cerr << tags[rsync] << a_str << std::endl;
00529 std::cerr.flush();
00530 }
00531
00532
00533
00534 void reportio::write_report(
00535 const std::string a_source,
00536 const timer& a_timer,
00537 const int a_exit_code,
00538 const int a_signal_num,
00539 const rsync_behavior::value_type& a_behavior,
00540 const std::string& a_error_msg
00541 )
00542 {
00543 estring str;
00544
00545 str += estring(a_source.size());
00546 str += " ";
00547 str += a_source;
00548 str += " ";
00549 str += estring(static_cast<uint64>(a_timer.start_value()));
00550 str += " ";
00551 str += estring(static_cast<uint64>(a_timer.stop_value()));
00552 str += " ";
00553 str += estring(a_exit_code);
00554 str += " ";
00555 str += estring(a_signal_num);
00556 str += " ";
00557 str += estring(static_cast<uint64>(a_behavior));
00558 str += " ";
00559 str += estring(a_error_msg.size());
00560 str += " ";
00561 str += a_error_msg;
00562 str += " ";
00563
00564 std::cout.flush();
00565 std::cout << tags[report] << str << std::endl;
00566 std::cout.flush();
00567 }
00568
00569
00570
00571 job_path_report reportio::parse(const std::string& a_str)
00572 {
00573 estring es;
00574 job_path_report jpr;
00575 estring estr;
00576 estring::size_type idx;
00577 estring::size_type size;
00578 estring tmp;
00579 estring source;
00580 timer::value_type start_time;
00581 timer::value_type stop_time;
00582 int exit_code;
00583 int signal_num;
00584 estring error_msg;
00585 rsync_behavior::behavior_type behavior;
00586
00587 TRY_nomem(estr = a_str);
00588 idx = estr.find(tags[report]);
00589 if (idx == std::string::npos) {
00590 estring es;
00591
00592 es = "Invalid job report: \"";
00593 es += a_str;
00594 es += "\"";
00595
00596 throw(INTERNAL_ERROR(0,es));
00597 }
00598
00599
00600
00601 estr.erase(0,idx+strlen(tags[report]));
00602
00603 idx = estr.find(' ');
00604 tmp = estr.substr(0,idx);
00605 estr.erase(0,idx+1);
00606 size = tmp;
00607 source = estr.substr(0,size);
00608 estr.erase(0,size+1);
00609
00610 idx = estr.find(' ');
00611 tmp = estr.substr(0,idx);
00612 estr.erase(0,idx+1);
00613 start_time = static_cast<uint64>(tmp);
00614
00615 idx = estr.find(' ');
00616 tmp = estr.substr(0,idx);
00617 estr.erase(0,idx+1);
00618 stop_time = static_cast<uint64>(tmp);
00619
00620 idx = estr.find(' ');
00621 tmp = estr.substr(0,idx);
00622 estr.erase(0,idx+1);
00623 exit_code = tmp;
00624
00625 idx = estr.find(' ');
00626 tmp = estr.substr(0,idx);
00627 estr.erase(0,idx+1);
00628 signal_num = tmp;
00629
00630 idx = estr.find(' ');
00631 tmp = estr.substr(0,idx);
00632 estr.erase(0,idx+1);
00633 behavior =
00634 static_cast<rsync_behavior::value_type>(
00635 static_cast<uint64>(tmp)
00636 );
00637
00638 idx = estr.find(' ');
00639 tmp = estr.substr(0,idx);
00640 estr.erase(0,idx+1);
00641 size = tmp;
00642 error_msg = estr.substr(0,size);
00643 estr.erase(0,size+1);
00644
00645 jpr.assign(
00646 source,
00647 timer(start_time,stop_time),
00648 exit_code,
00649 signal_num,
00650 behavior,
00651 error_msg
00652 );
00653
00654 return(jpr);
00655 }
00656
00657
00658 bool reportio::is_report(const std::string& a_class)
00659 {
00660 estring::size_type idx;
00661
00662 idx = a_class.find(tags[report]);
00663 if (idx == std::string::npos) {
00664 return(false);
00665 }
00666 return(true);
00667 }
00668
00669
00670
00671
00672 single_job_report::single_job_report()
00673 {
00674 clear();
00675 }
00676
00677
00678 single_job_report::~single_job_report()
00679 {
00680 }
00681
00682
00683 void single_job_report::clear(void)
00684 {
00685 m_reports.clear();
00686 m_id.erase();
00687 }
00688
00689
00690 void single_job_report::add_report(const job_path_report& a_class)
00691 {
00692 TRY_nomem(m_reports.push_back(a_class));
00693 }
00694
00695
00696 const std::vector<job_path_report>& single_job_report::reports(void) const
00697 {
00698 return(m_reports);
00699 }
00700
00701
00702 void single_job_report::id(const std::string& a_str)
00703 {
00704 TRY_nomem(m_id = a_str);
00705 }
00706
00707
00708 const std::string& single_job_report::id(void) const
00709 {
00710 return(m_id);
00711 }
00712
00713
00714
00715 const bool single_job_report::status(void) const
00716 {
00717 bool value = true;
00718 std::vector<job_path_report>::const_iterator jpri;
00719
00720 for (jpri = m_reports.begin(); jpri != m_reports.end(); ++jpri) {
00721 if (!jpri->status())
00722 value = false;
00723 }
00724
00725 return(value);
00726 }
00727
00728
00729
00730
00731 jobs_report::jobs_report()
00732 {
00733 clear();
00734 }
00735
00736
00737 jobs_report::~jobs_report()
00738 {
00739 }
00740
00741
00742 void jobs_report::clear(void)
00743 {
00744 m_jobs.clear();
00745 }
00746
00747
00748 void jobs_report::add_report(const single_job_report& a_class)
00749 {
00750 TRY_nomem(m_jobs.push_back(a_class));
00751 }
00752
00753
00754 const std::vector<single_job_report>& jobs_report::reports(void) const
00755 {
00756 return(m_jobs);
00757 }
00758
00759
00760 void jobs_report::write_report(std::ostream& a_out)
00761 {
00762 std::vector<single_job_report>::const_iterator ji;
00763 std::vector<job_path_report>::const_iterator jpi;
00764 estring estr;
00765 estring estr2;
00766 estring hsep;
00767 estring vsep;
00768 estring vsep2;
00769
00770 hsep.fillchar('-');
00771 vsep = " | ";
00772 vsep2 = "|";
00773
00774 for (ji = m_jobs.begin(); ji != m_jobs.end(); ++ji) {
00775 table t1, t2;
00776 bool first_line = true;
00777
00778 if (ji != m_jobs.begin())
00779 a_out << std::endl;
00780
00781 estr.align(estring::left);
00782 estr = "Job: ";
00783 estr += ji->id();
00784 t1 << estr;
00785 t1 << table_endl;
00786
00787 t1 << hsep;
00788 t1 << table_endl;
00789
00790 t2 << "Job" << vsep << "Path" << " " << " "
00791 << table_endl;
00792 t2 << "Status" << vsep << "Status" << " " << "Source"
00793 << table_endl;
00794 t2 << hsep << vsep << hsep << " " << hsep << table_endl;
00795
00796 for (jpi = ji->reports().begin(); jpi != ji->reports().end(); ++jpi) {
00797 if (jpi != ji->reports().begin())
00798 t2 << table_endl;
00799
00800 if (first_line) {
00801 if (ji->status())
00802 t2 << "OK";
00803 else
00804 t2 << "ERROR";
00805 first_line = false;
00806 }
00807 else {
00808 t2 << " " << vsep << " " << " " << table_endl << " ";
00809 }
00810
00811 t2 << table_repeat << vsep;
00812
00813 if (jpi->status())
00814 t2 << "OK";
00815 else
00816 t2 << "ERROR";
00817
00818 t2 << " ";
00819
00820 t2 << jpi->source();
00821
00822 t2 << table_endl;
00823
00824 t2 << " " << table_repeat << vsep << " " << " ";
00825
00826 table t3, t4;
00827
00828 t3 << "+" << hsep << hsep << table_endl;
00829 t3 << table_repeat << vsep2 << " ";
00830
00831 estr.align(estring::right);
00832 estr2.align(estring::right);
00833
00834 estr = "Start:";
00835 estr2 = jpi->time().started_at();
00836 estr2 += " ";
00837 t4 << " " << estr << " " << estr2 << table_endl;
00838
00839 estr = "Finish:";
00840 estr2 = jpi->time().stopped_at();
00841 estr2 += " ";
00842 t4 << " " << estr << " " << estr2 << table_endl;
00843
00844 estr = "Duration:";
00845 estr2 = jpi->time().duration();
00846 t4 << " " << estr << " " << estr2 << table_endl;
00847
00848 t3 << t4 << table_endl;
00849
00850 estr2.align(estring::left);
00851 if (!jpi->status()) {
00852 table t5;
00853
00854 t3 << vsep2 << " " << " " << table_endl;
00855 t3 << table_repeat << vsep2 << " ";
00856
00857 estr = "Exit Code:";
00858 estr2 = estring(jpi->exit_code());
00859 if (jpi->exit_code() != 0) {
00860 estr2 += " ";
00861 estr2 += rsync_estat_str.exit(jpi->exit_code());
00862 }
00863 t5 << " " << estr << " " << estr2 << table_endl;
00864
00865 estr = "Signal Num:";
00866 estr2 = estring(jpi->signal_num());
00867 if (jpi->signal_num() != 0) {
00868 estr2 += " ";
00869 estr2 += rsync_estat_str.signal(jpi->signal_num());
00870 }
00871 t5 << " " << estr << " " << estr2 << table_endl;
00872
00873 if (jpi->error_msg().size() > 0) {
00874 estr = "Error Msg:";
00875 estr2 = jpi->error_msg();
00876 t5 << " " << estr << " " << estr2 << table_endl;
00877 }
00878
00879 t3 << t5;
00880 }
00881
00882
00883
00884 t2 << t3;
00885 }
00886
00887 t1 << t2;
00888
00889 a_out << t1;
00890 }
00891 }
00892
00893
00894 void jobs_report::format_synopsis(table& a_table)
00895 {
00896 estring estr, estr2;
00897 std::vector<single_job_report>::const_iterator sjri;
00898 uint16 jobs_good = 0;
00899 uint16 jobs_bad = 0;
00900 uint16 jobs_total = 0;
00901
00902 estr.align(estring::right);
00903
00904 for (sjri = m_jobs.begin(); sjri != m_jobs.end(); ++sjri) {
00905 if (sjri->status())
00906 ++jobs_good;
00907 else
00908 ++jobs_bad;
00909 ++jobs_total;
00910 }
00911
00912 estr = "Successful Jobs:";
00913 estr2 = estring(jobs_good);
00914 estr2 += " out of ";
00915 estr2 += estring(m_jobs.size());
00916 estr2 += " (";
00917 estr2 += percent_string(jobs_good, jobs_total);
00918 estr2 += ")";
00919
00920 a_table << estr << " " << estr2 << table_endl;
00921 }
00922
00923
00924
00925
00926 report_manager::report_manager()
00927 {
00928 m_initialized = false;
00929 }
00930
00931
00932 report_manager::~report_manager()
00933 {
00934 }
00935
00936
00937 void report_manager::init(void)
00938 {
00939 if (!config.initialized()) {
00940 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
00941 }
00942 m_initialized = true;
00943 }
00944
00945
00946 const bool report_manager::initialized(void) const
00947 {
00948 return(m_initialized);
00949 }
00950
00951
00952 void report_manager::clear(void)
00953 {
00954 m_total_time.clear();
00955 m_vault.clear();
00956 m_jobs.clear();
00957 }
00958
00959
00960 void report_manager::set_total_time(const timer& a_class)
00961 {
00962 if (!initialized())
00963 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
00964
00965 m_total_time = a_class;
00966 }
00967
00968
00969 vault_report& report_manager::vault(void)
00970 {
00971 return(m_vault);
00972 }
00973
00974
00975 jobs_report& report_manager::jobs(void)
00976 {
00977 return(m_jobs);
00978 }
00979
00980
00981 void report_manager::print_report(void)
00982 {
00983 estring lstr;
00984
00985 if (!initialized())
00986 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
00987
00988 lstr = "Reporter - Printing report to stdout...\n";
00989 logger.write(lstr);
00990
00991 write_report(std::cout);
00992
00993 lstr = "Reporter - Done\n";
00994 logger.write(lstr);
00995 }
00996
00997
00998 void report_manager::file_report(void)
00999 {
01000 std::ofstream out;
01001 std::string filename;
01002 std::string es;
01003 estring lstr;
01004 bool done = false;
01005 int count = 0;
01006
01007 if (!initialized())
01008 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
01009
01010 while (!done) {
01011 TRY_nomem(filename = config.log_dir());
01012 TRY_nomem(filename += "/");
01013 TRY_nomem(filename += config.timestamp().str());
01014 TRY_nomem(filename += ".report");
01015 if (count != 0) {
01016 TRY_nomem(filename += ".");
01017 TRY_nomem(filename += estring(count));
01018 }
01019 if (exists(filename))
01020 ++count;
01021 else
01022 done = true;
01023 }
01024 out.open(filename.c_str());
01025 if (!out.is_open()) {
01026 TRY_nomem(es = "Could not open report file: \"");
01027 TRY_nomem(es += filename);
01028 TRY_nomem(es += "\"");
01029 throw(ERROR(errno,es));
01030 }
01031
01032 lstr = "Reporter - Writing report to file...\n";
01033 logger.write(lstr);
01034 write_report(out);
01035
01036 out.close();
01037
01038 lstr = "Reporter - Done\n";
01039 logger.write(lstr);
01040 }
01041
01042
01043 void report_manager::write_report(std::ostream& a_out)
01044 {
01045 estring estr;
01046 estring es;
01047
01048 mf_write_header(a_out);
01049
01050 a_out << std::endl;
01051
01052 mf_write_synopsis(a_out);
01053
01054 a_out << std::endl;
01055
01056 m_jobs.write_report(a_out);
01057
01058 a_out << std::endl;
01059
01060 m_vault.write_report(a_out);
01061
01062 a_out << std::endl;
01063 }
01064
01065
01066 void report_manager::format_synopsis(table& a_table)
01067 {
01068 estring estr;
01069 estring estr2;
01070
01071 estr.align(estring::right);
01072 estr2.align(estring::right);
01073
01074 estr = "Start Time:";
01075 estr2 = m_total_time.started_at();
01076 estr2 += " ";
01077
01078 a_table << estr << " " << estr2 << table_endl;
01079
01080 estr = "Finish Time:";
01081 estr2 = m_total_time.stopped_at();
01082 estr2 += " ";
01083
01084 a_table << estr << " " << estr2 << table_endl;
01085
01086 estr = "Duration:";
01087 estr2 = m_total_time.duration();
01088
01089 a_table << estr << " " << estr2 << table_endl;
01090 }
01091
01092 void report_manager::mf_write_header(std::ostream& a_out)
01093 {
01094 table t;
01095 estring estr;
01096
01097 estr = "Rsync Vault Manager - ";
01098 estr += VERSION;
01099
01100 t << estr << table_endl;
01101
01102 estr = "";
01103 estr.fillchar('=');
01104 t << estr;
01105
01106 a_out << t;
01107 }
01108
01109 void report_manager::mf_write_synopsis(std::ostream& a_out)
01110 {
01111 table t;
01112 estring estr;
01113
01114 format_synopsis(t);
01115 vault().format_synopsis(t);
01116 jobs().format_synopsis(t);
01117
01118 a_out << t;
01119 }
01120
01121
01122
01123
01124 report_manager reporter;
01125