reporter.cc

Go to the documentation of this file.
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 /** C'tor */
00026 vault_stats_report::vault_stats_report()
00027 {
00028         clear();
00029 }
00030 
00031 /** C'tor */
00032 vault_stats_report::vault_stats_report(const vault_stats_report& a_class)
00033 {
00034         clear();
00035         assign(a_class);
00036 }
00037 
00038 /** C'tor */
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 /** D'tor */
00049 vault_stats_report::~vault_stats_report()
00050 {
00051 }
00052 
00053 /** Clear all values */
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 /** Assignment */
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 /** Assignment */
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 /** Assignment */
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 /** Return a string timestamp */
00113 const std::string& vault_stats_report::time(void) const
00114 {
00115         return(m_time);
00116 }
00117 
00118 /** Return the message */
00119 const std::string& vault_stats_report::message(void) const
00120 {
00121         return(m_message);
00122 }
00123 
00124 /** Return the total number of blocks in the vault */
00125 const uint64 vault_stats_report::total_blocks(void) const
00126 {
00127         return(m_total_blocks);
00128 }
00129 
00130 /** Return the number of free blocks in the vault */
00131 const uint64 vault_stats_report::free_blocks(void) const
00132 {
00133         return(m_free_blocks);
00134 }
00135 
00136 /** Return the total number of inodes in the vault */
00137 const uint64 vault_stats_report::total_inodes(void) const
00138 {
00139         return(m_total_inodes);
00140 }
00141 
00142 /** Return the number of free inodes in the vault */
00143 const uint64 vault_stats_report::free_inodes(void) const
00144 {
00145         return(m_free_inodes);
00146 }
00147 
00148 /** Assignment operator */
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 /** C'tor */
00159 vault_report::vault_report()
00160 {
00161         clear();
00162 }
00163 
00164 /** D'tor */
00165 vault_report::~vault_report()
00166 {
00167 }
00168 
00169 /** Clear all values */
00170 void vault_report::clear(void)
00171 {
00172         m_reports.clear();
00173 }
00174 
00175 /** Add a vault report to the list */
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 /** Format and print the vault report to the given stream */
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         // Header
00201         tab2
00202                 << "Time"
00203                 << " "
00204                 << "Message"
00205                 << " "
00206                 << "Free Blocks"
00207                 << " "
00208                 << "Free Inodes"
00209                 << " "
00210                 << table_endl;
00211         
00212         // Separators
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         // Vault messages/statistics
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         // Separators
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         // Final
00269         estr.align(estring::right);
00270         estr.fillchar(' ');
00271         estr = "Total Difference:";
00272         // estr.align(estring::center);
00273         // estr.fillchar(' ');
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 /** Generate a synopsis report */
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 /** C'tor */
00333 job_path_report::job_path_report()
00334 {
00335         clear();
00336 }
00337 
00338 /** C'tor */
00339 job_path_report::job_path_report(const job_path_report& a_class)
00340 {
00341         clear();
00342         assign(a_class);
00343 }
00344 
00345 /** C'tor */
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 std::string a_error_message
00352         )
00353 {
00354         clear();
00355         assign(a_source, a_time, a_exit_code, a_signal_num, a_error_message);
00356 }
00357 
00358 /** D'tor */
00359 job_path_report::~job_path_report()
00360 {
00361 }
00362 
00363 /** Clear all values */
00364 void job_path_report::clear(void)
00365 {
00366         m_source.erase();
00367         m_time.clear();
00368         m_exit_code = 0;
00369         m_signal_num = 0;
00370         m_error_msg.erase();
00371 }
00372 
00373 /** Assignment */
00374 void job_path_report::assign(const job_path_report& a_class)
00375 {
00376         assign(
00377                 a_class.m_source, 
00378                 a_class.m_time,
00379                 a_class.m_exit_code,
00380                 a_class.m_signal_num,
00381                 a_class.m_error_msg
00382                 );
00383 }
00384 
00385 /** Assignment */
00386 void job_path_report::assign(
00387         const std::string a_source,
00388         const timer a_time,
00389         const uint16 a_exit_code,
00390         const uint16 a_signal_num,
00391         const std::string a_error_message
00392         )
00393 {
00394         TRY_nomem(m_source = a_source);
00395         TRY_nomem(m_error_msg = a_error_message);
00396         TRY_nomem(m_time = a_time);
00397         m_exit_code = a_exit_code;
00398         m_signal_num = a_signal_num;
00399 }
00400 
00401 /** Return true if rsync succeeded archiving this path */
00402 const bool job_path_report::status(void) const
00403 {
00404         if ((m_exit_code == 0) && (m_signal_num == 0)) {
00405                 return(true);
00406         }
00407         return(false);
00408 }
00409 
00410 /** Set the path archived for this report */
00411 void job_path_report::source(const std::string& a_class)
00412 {
00413         TRY_nomem(m_source = a_class);
00414 }
00415 
00416 /** Return a string of the path archived */
00417 const std::string& job_path_report::source(void) const
00418 {
00419         return(m_source);
00420 }
00421 
00422 /** Set the timer values for this report */
00423 void job_path_report::time(const timer& a_class)
00424 {
00425         TRY_nomem(m_time = a_class);
00426 }
00427 
00428 /** Return the timer object for this report */
00429 const timer& job_path_report::time(void) const
00430 {
00431         return(m_time);
00432 }
00433 
00434 /** Set rsync's return exit code when archiving this path */
00435 void job_path_report::exit_code(const int a_exit_code)
00436 {
00437         m_exit_code = a_exit_code;
00438 }
00439 
00440 /** Return rsync's exit code */
00441 const int job_path_report::exit_code(void) const
00442 {
00443         return(m_exit_code);
00444 }
00445 
00446 /** Set rsync's signal number from archiving this path */
00447 void job_path_report::signal_num(const int a_signal_num)
00448 {
00449         m_signal_num = a_signal_num;
00450 }
00451 
00452 /** Return rsync's signal number */
00453 const int job_path_report::signal_num(void) const
00454 {
00455         return(m_signal_num);
00456 }
00457 
00458 /** Set a descriptive error message for this report */
00459 void job_path_report::error_msg(const std::string& a_class)
00460 {
00461         TRY_nomem(m_error_msg = a_class);
00462 }
00463 
00464 /** Return the error message */
00465 const std::string& job_path_report::error_msg(void) const
00466 {
00467         return(m_error_msg);
00468 }
00469 
00470 /** Assignment operator */
00471 job_path_report& job_path_report::operator=(const job_path_report& a_class)
00472 {
00473         assign(a_class);
00474         return(*this);
00475 }
00476 
00477 //-----------------------------------------------------------------------------
00478 
00479 /** Report type tags */
00480 const char *reportio::tags[] = {
00481         "[RSYNC]: ",
00482         "[REPORT]: ",
00483         0
00484 };
00485 
00486 /** Write a report line for output from rsync to parent on child's std::cout 
00487  */
00488 void reportio::write_rsync_out(const std::string& a_str)
00489 {
00490         std::cout.flush();
00491         std::cout << tags[rsync] << a_str << std::endl;
00492         std::cout.flush();
00493 }
00494 
00495 /** Write a report line for output from rsync to parent on child's std::cerr
00496  */
00497 void reportio::write_rsync_err(const std::string& a_str)
00498 {
00499         std::cerr.flush();
00500         std::cerr << tags[rsync] << a_str << std::endl;
00501         std::cerr.flush();
00502 }
00503 
00504 /** Generate and submit a report to the parent process on child's std::cout
00505  */
00506 void reportio::write_report(
00507                 const std::string a_source,
00508                 const timer& a_timer,
00509                 const int a_exit_code,
00510                 const int a_signal_num,
00511                 const std::string& a_error_msg
00512         )
00513 {
00514         estring str;
00515 
00516         str += estring(a_source.size());
00517         str += " ";
00518         str += a_source;
00519         str += " ";
00520         str += estring(static_cast<uint64>(a_timer.start_value()));
00521         str += " ";
00522         str += estring(static_cast<uint64>(a_timer.stop_value()));
00523         str += " ";
00524         str += estring(a_exit_code);
00525         str += " ";
00526         str += estring(a_signal_num);
00527         str += " ";
00528         str += estring(a_error_msg.size());
00529         str += " ";
00530         str += a_error_msg;
00531         str += " ";
00532 
00533         std::cout.flush();
00534         std::cout << tags[report] << str << std::endl;
00535         std::cout.flush();
00536 }
00537 
00538 /** Parse a received report from a child process and return a job_path_report
00539  */
00540 job_path_report reportio::parse(const std::string& a_str)
00541 {
00542         estring es;
00543         job_path_report jpr;
00544         estring estr;
00545         estring::size_type idx;
00546         estring::size_type size;
00547         estring tmp;
00548         estring source;
00549         timer::value_type start_time;
00550         timer::value_type stop_time;
00551         int exit_code;
00552         int signal_num;
00553         estring error_msg;
00554 
00555         TRY_nomem(estr = a_str);
00556         idx = estr.find(tags[report]);
00557         if (idx == std::string::npos) {
00558                 estring es;
00559 
00560                 es = "Invalid job report: \"";
00561                 es += a_str;
00562                 es += "\"";
00563 
00564                 throw(INTERNAL_ERROR(0,es));
00565         }
00566         
00567         // TODO: A lot of assumptions are being made here, put in some checking code
00568 
00569         estr.erase(0,idx+strlen(tags[report]));
00570 
00571         idx = estr.find(' ');
00572         tmp = estr.substr(0,idx);
00573         estr.erase(0,idx+1);
00574         size = tmp;
00575         source = estr.substr(0,size);
00576         estr.erase(0,size+1);
00577 
00578         idx = estr.find(' ');
00579         tmp = estr.substr(0,idx);
00580         estr.erase(0,idx+1);
00581         start_time = static_cast<uint64>(tmp);
00582 
00583         idx = estr.find(' ');
00584         tmp = estr.substr(0,idx);
00585         estr.erase(0,idx+1);
00586         stop_time = static_cast<uint64>(tmp);
00587 
00588         idx = estr.find(' ');
00589         tmp = estr.substr(0,idx);
00590         estr.erase(0,idx+1);
00591         exit_code = tmp;
00592 
00593         idx = estr.find(' ');
00594         tmp = estr.substr(0,idx);
00595         estr.erase(0,idx+1);
00596         signal_num = tmp;
00597 
00598         idx = estr.find(' ');
00599         tmp = estr.substr(0,idx);
00600         estr.erase(0,idx+1);
00601         size = tmp;
00602         error_msg = estr.substr(0,size);
00603         estr.erase(0,size+1);
00604 
00605         jpr.assign(
00606                 source,
00607                 timer(start_time,stop_time),
00608                 exit_code,
00609                 signal_num,
00610                 error_msg
00611         );
00612 
00613         return(jpr);
00614 }
00615 
00616 /** Return true if the given string looks like a valid report */
00617 bool reportio::is_report(const std::string& a_class)
00618 {
00619         estring::size_type idx;
00620 
00621         idx = a_class.find(tags[report]);
00622         if (idx == std::string::npos) {
00623                 return(false);
00624         }
00625         return(true);
00626 }
00627 
00628 //-----------------------------------------------------------------------------
00629 
00630 /** C'tor */
00631 single_job_report::single_job_report()
00632 {
00633         clear();
00634 }
00635 
00636 /** D'tor */
00637 single_job_report::~single_job_report()
00638 {
00639 }
00640 
00641 /** Clear all values  */
00642 void single_job_report::clear(void)
00643 {
00644         m_reports.clear();
00645         m_id.erase();
00646 }
00647 
00648 /** Add a path report for this job */
00649 void single_job_report::add_report(const job_path_report& a_class)
00650 {
00651         TRY_nomem(m_reports.push_back(a_class));
00652 }
00653 
00654 /** Return a const vector of all path reports */
00655 const std::vector<job_path_report>& single_job_report::reports(void) const
00656 {
00657         return(m_reports);
00658 }
00659 
00660 /** Set a descriptive ID for this job report */
00661 void single_job_report::id(const std::string& a_str)
00662 {
00663         TRY_nomem(m_id = a_str);
00664 }
00665 
00666 /** Return the descriptive id for this job report */
00667 const std::string& single_job_report::id(void) const
00668 {
00669         return(m_id);
00670 }
00671 
00672 /** If all path reports say that rsync was successful, then return true, else
00673  * return false */
00674 const bool single_job_report::status(void) const
00675 {
00676         bool value = true;
00677         std::vector<job_path_report>::const_iterator jpri;
00678 
00679         for (jpri = m_reports.begin(); jpri != m_reports.end(); ++jpri) {
00680                 if (!jpri->status())
00681                         value = false;
00682         }
00683 
00684         return(value);
00685 }
00686 
00687 //-----------------------------------------------------------------------------
00688 
00689 /** C'tor */
00690 jobs_report::jobs_report()
00691 {
00692         clear();
00693 }
00694 
00695 /** D'tor */
00696 jobs_report::~jobs_report()
00697 {
00698 }
00699 
00700 /** Clear all values */
00701 void jobs_report::clear(void)
00702 {
00703         m_jobs.clear();
00704 }
00705 
00706 /** Add a job report to the list */
00707 void jobs_report::add_report(const single_job_report& a_class)
00708 {
00709         TRY_nomem(m_jobs.push_back(a_class));
00710 }
00711 
00712 /** Return a const vector of all job reports */
00713 const std::vector<single_job_report>& jobs_report::reports(void) const
00714 {
00715         return(m_jobs);
00716 }
00717 
00718 /** Format job reports and output to the given stream */
00719 void jobs_report::write_report(std::ostream& a_out)
00720 {
00721         std::vector<single_job_report>::const_iterator ji;
00722         std::vector<job_path_report>::const_iterator jpi;
00723         estring estr;
00724         estring estr2;
00725         estring hsep;
00726         estring vsep;
00727         estring vsep2;
00728 
00729         hsep.fillchar('-');
00730         vsep = " | ";
00731         vsep2 = "|";
00732         
00733         for (ji = m_jobs.begin(); ji != m_jobs.end(); ++ji) {
00734                 table t1, t2;
00735                 bool first_line = true;
00736 
00737                 if (ji != m_jobs.begin())
00738                         a_out << std::endl;
00739 
00740                 estr.align(estring::left);
00741                 estr = "Job: ";
00742                 estr += ji->id();
00743                 t1 << estr;
00744                 t1 << table_endl;
00745 
00746                 t1 << hsep;
00747                 t1 << table_endl;
00748 
00749                 t2 << "Job" << vsep << "Path" << " " << " " 
00750                         << table_endl;
00751                 t2 << "Status" << vsep << "Status" << " " << "Source" 
00752                         << table_endl;
00753                 t2 << hsep << vsep << hsep << " " << hsep << table_endl;
00754 
00755                 for (jpi = ji->reports().begin(); jpi != ji->reports().end(); ++jpi) {
00756                         if (jpi != ji->reports().begin())
00757                                 t2 << table_endl;
00758 
00759                         if (first_line) {
00760                                 if (ji->status())
00761                                         t2 << "OK";
00762                                 else
00763                                         t2 << "ERROR";
00764                                 first_line = false;
00765                         }
00766                         else {
00767                                 t2 << " " << vsep << " " << " " << table_endl << " ";
00768                         }
00769 
00770                         t2 << table_repeat << vsep;
00771 
00772                         if (jpi->status())
00773                                 t2 << "OK";
00774                         else
00775                                 t2 << "ERROR";
00776 
00777                         t2 << " ";
00778 
00779                         t2 << jpi->source();
00780 
00781                         t2 << table_endl;
00782 
00783                         t2 << " " << table_repeat << vsep << " " << " ";
00784 
00785                         table t3, t4;
00786 
00787                         t3 << "+" << hsep << hsep << table_endl;
00788                         t3 << table_repeat << vsep2 << " ";
00789 
00790                         estr.align(estring::right);
00791                         estr2.align(estring::right);
00792 
00793                         estr = "Start:";
00794                         estr2 = jpi->time().started_at();
00795                         estr2 += "  ";
00796                         t4 << " " << estr << " " << estr2 << table_endl;
00797 
00798                         estr = "Finish:";
00799                         estr2 = jpi->time().stopped_at();
00800                         estr2 += "  ";
00801                         t4 << " " << estr << " " << estr2 << table_endl;
00802 
00803                         estr = "Duration:";
00804                         estr2 = jpi->time().duration();
00805                         t4 << " " << estr << " " << estr2 << table_endl;
00806 
00807                         t3 << t4 << table_endl;
00808 
00809                         estr2.align(estring::left);
00810                         if (!jpi->status()) {
00811                                 table t5;
00812 
00813                                 t3 << vsep2 << " " << " " << table_endl;
00814                                 t3 << table_repeat << vsep2 << " ";
00815 
00816                                 estr = "Exit Code:";
00817                                 estr2 = estring(jpi->exit_code());
00818                                 if (jpi->exit_code() != 0) {
00819                                         estr2 += " ";
00820                                         estr2 += rsync_estat_str.exit(jpi->exit_code());
00821                                 }
00822                                 t5 << " " << estr << " " << estr2 << table_endl;
00823 
00824                                 estr = "Signal Num:";
00825                                 estr2 = estring(jpi->signal_num());
00826                                 if (jpi->signal_num() != 0) {
00827                                         estr2 += " ";
00828                                         estr2 += rsync_estat_str.signal(jpi->signal_num());
00829                                 }
00830                                 t5 << " " << estr << " " << estr2 << table_endl;
00831 
00832                                 if (jpi->error_msg().size() > 0) {
00833                                         estr = "Error Msg:";
00834                                         estr2 = jpi->error_msg();
00835                                         t5 << " " << estr << " " << estr2 << table_endl;
00836                                 }
00837 
00838                                 t3 << t5;
00839                         }
00840 
00841                         // TODO: File statistics should go here
00842 
00843                         t2 << t3;
00844                 }
00845 
00846                 t1 << t2;
00847 
00848                 a_out << t1;
00849         }
00850 }
00851 
00852 /** Generate a synopsis report */
00853 void jobs_report::format_synopsis(table& a_table)
00854 {
00855         estring estr, estr2;
00856         std::vector<single_job_report>::const_iterator sjri;
00857         uint16 jobs_good = 0;
00858         uint16 jobs_bad = 0;
00859         uint16 jobs_total = 0;
00860 
00861         estr.align(estring::right);
00862 
00863         for (sjri = m_jobs.begin(); sjri != m_jobs.end(); ++sjri) {
00864                 if (sjri->status())
00865                         ++jobs_good;
00866                 else
00867                         ++jobs_bad;
00868                 ++jobs_total;
00869         }
00870 
00871         estr = "Successful Jobs:";
00872         estr2 = estring(jobs_good);
00873         estr2 += " out of ";
00874         estr2 += estring(m_jobs.size());
00875         estr2 += " (";
00876         estr2 += percent_string(jobs_good, jobs_total);
00877         estr2 += ")";
00878 
00879         a_table << estr << " " << estr2 << table_endl;
00880 }
00881 
00882 //-----------------------------------------------------------------------------
00883 
00884 /** C'tor */
00885 report_manager::report_manager()
00886 {
00887         m_initialized = false;
00888 }
00889 
00890 /** D'tor */
00891 report_manager::~report_manager()
00892 {
00893 }
00894 
00895 /** Initialize */
00896 void report_manager::init(void)
00897 {
00898         if (!config.initialized()) {
00899                 throw(INTERNAL_ERROR(0,"Configuration manager is not initialized"));
00900         }
00901         m_initialized = true;
00902 }
00903 
00904 /** Return whether or not this object has been inintialized */
00905 const bool report_manager::initialized(void) const
00906 {
00907         return(m_initialized);
00908 }
00909 
00910 /** Clear all values */
00911 void report_manager::clear(void)
00912 {
00913         m_total_time.clear();
00914         m_vault.clear();
00915         m_jobs.clear();
00916 }
00917 
00918 /** Report the overall RVM time */
00919 void report_manager::set_total_time(const timer& a_class)
00920 {
00921         if (!initialized())
00922                 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
00923 
00924         m_total_time = a_class;
00925 }
00926 
00927 /** Return the vault reporter object */
00928 vault_report& report_manager::vault(void)
00929 {
00930         return(m_vault);
00931 }
00932 
00933 /** Return the jobs reporter object */
00934 jobs_report& report_manager::jobs(void)
00935 {
00936         return(m_jobs);
00937 }
00938 
00939 /** Print report to standard output */
00940 void report_manager::print_report(void)
00941 {
00942         estring lstr;
00943 
00944         if (!initialized())
00945                 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
00946 
00947         lstr = "Reporter - Printing report to stdout...\n";
00948         logger.write(lstr);
00949 
00950         write_report(std::cout);
00951 
00952         lstr = "Reporter - Done\n";
00953         logger.write(lstr);
00954 }
00955 
00956 /** Save report to a file */
00957 void report_manager::file_report(void)
00958 {
00959         std::ofstream out;
00960         std::string filename;
00961         std::string es;
00962         estring lstr;
00963         bool done = false;
00964         int count = 0;
00965 
00966         if (!initialized())
00967                 throw(INTERNAL_ERROR(0,"Report manager is not initialized"));
00968         
00969         while (!done) {
00970                 TRY_nomem(filename = config.log_dir());
00971                 TRY_nomem(filename += "/");
00972                 TRY_nomem(filename += config.timestamp().str());
00973                 TRY_nomem(filename += ".report");
00974                 if (count != 0) {
00975                         TRY_nomem(filename += ".");
00976                         TRY_nomem(filename += estring(count));
00977                 }
00978                 if (exists(filename))
00979                         ++count;
00980                 else
00981                         done = true;
00982         }
00983         out.open(filename.c_str());
00984         if (!out.is_open()) {
00985                 TRY_nomem(es = "Could not open report file: \"");
00986                 TRY_nomem(es += filename);
00987                 TRY_nomem(es += "\"");
00988                 throw(ERROR(errno,es));
00989         }
00990 
00991         lstr = "Reporter - Writing report to file...\n";
00992         logger.write(lstr);
00993         write_report(out);
00994 
00995         out.close();
00996 
00997         lstr = "Reporter - Done\n";
00998         logger.write(lstr);
00999 }
01000 
01001 /** Write report to the given stream */
01002 void report_manager::write_report(std::ostream& a_out)
01003 {
01004         estring estr;
01005         estring es;
01006 
01007         mf_write_header(a_out);
01008 
01009         a_out << std::endl;
01010 
01011         mf_write_synopsis(a_out);
01012 
01013         a_out << std::endl;
01014 
01015         m_jobs.write_report(a_out);
01016         
01017         a_out << std::endl;
01018 
01019         m_vault.write_report(a_out);
01020 
01021         a_out << std::endl;
01022 }
01023 
01024 /** Generate a synopsis report */
01025 void report_manager::format_synopsis(table& a_table)
01026 {
01027         estring estr;
01028         estring estr2;
01029 
01030         estr.align(estring::right);
01031         estr2.align(estring::right);
01032 
01033         estr = "Start Time:";
01034         estr2 = m_total_time.started_at();
01035         estr2 += "  ";
01036 
01037         a_table << estr << " " << estr2 << table_endl;
01038 
01039         estr = "Finish Time:";
01040         estr2 = m_total_time.stopped_at();
01041         estr2 += "  ";
01042 
01043         a_table << estr << " " << estr2 << table_endl;
01044 
01045         estr = "Duration:";
01046         estr2 = m_total_time.duration();
01047 
01048         a_table << estr << " " << estr2 << table_endl;
01049 }
01050 
01051 void report_manager::mf_write_header(std::ostream& a_out)
01052 {
01053         table t;
01054         estring estr;
01055 
01056         estr = "Rsync Vault Manager - ";
01057         estr += VERSION;
01058 
01059         t << estr << table_endl;
01060 
01061         estr = "";
01062         estr.fillchar('=');
01063         t << estr;
01064 
01065         a_out << t;
01066 }
01067 
01068 void report_manager::mf_write_synopsis(std::ostream& a_out)
01069 {
01070         table t;
01071         estring estr;
01072 
01073         format_synopsis(t);
01074         vault().format_synopsis(t);
01075         jobs().format_synopsis(t);
01076 
01077         a_out << t;
01078 }
01079 
01080 //-----------------------------------------------------------------------------
01081 
01082 /** The global report manager */
01083 report_manager reporter;
01084 

Generated on Wed Jun 21 10:50:04 2006 for rvm by  doxygen 1.4.2