00001 #include "config.h"
00002
00003 #ifdef HAVE_UNISTD_H
00004 #include <unistd.h>
00005 #endif
00006
00007 #include <iostream>
00008 #include <iomanip>
00009 #include <string>
00010
00011
00012 #include <time.h>
00013 #include <sys/types.h>
00014
00015 #include "types.h"
00016 #include "error.h"
00017 #include "fs.h"
00018 #include "estring.h"
00019 #include "strfmt.h"
00020 #include "rmath.h"
00021
00022 #include "timer.h"
00023
00024
00025
00026 const std::string make_time_string_(timer::value_type a_t)
00027 {
00028 std::string es;
00029 struct tm* l = 0;
00030 estring tmp_str;
00031 std::string str;
00032
00033 l = localtime(&a_t);
00034 if (l == 0) {
00035 TRY_nomem(es = "Could not convert time_t to localtime: \"");
00036 TRY_nomem(es += estring(a_t));
00037 TRY_nomem(es += "\"");
00038 throw(ERROR(errno,es));
00039 }
00040
00041 TRY(str += estring(l->tm_year + 1900).fmt_str(4,estring::right,'0','x'),
00042 "Error generating string from year");
00043
00044 TRY_nomem(str += ".");
00045
00046 TRY(str += estring(l->tm_mon + 1).fmt_str(2,estring::right,'0','x'),
00047 "Error generating string from month");
00048
00049 TRY_nomem(str += ".");
00050
00051 TRY(str += estring(l->tm_mday).fmt_str(2,estring::right,'0','x'),
00052 "Error generating string from day");
00053
00054 TRY_nomem(str += " ");
00055
00056 TRY(str += estring(l->tm_hour).fmt_str(2,estring::right,'0','x'),
00057 "Error generating string from hour");
00058
00059 TRY_nomem(str += ":");
00060
00061 TRY(str += estring(l->tm_min).fmt_str(2,estring::right,'0','x'),
00062 "Error generating string from minute");
00063
00064 TRY_nomem(str += ":");
00065
00066 TRY(str += estring(l->tm_sec).fmt_str(2,estring::right,'0','x'),
00067 "Error generating string from seconds");
00068
00069 return(str);
00070 }
00071
00072
00073 timer::timer()
00074 {
00075 clear();
00076 start();
00077 }
00078
00079
00080 timer::timer(const timer& a_timer)
00081 {
00082 assign(a_timer);
00083 }
00084
00085
00086 timer::timer(const value_type a_start)
00087 {
00088 assign(a_start);
00089 }
00090
00091
00092 timer::timer(const value_type a_start, const value_type a_stop)
00093 {
00094 assign(a_start,a_stop);
00095 }
00096
00097
00098 void timer::clear(void)
00099 {
00100 m_start = 0;
00101 m_stop = 0;
00102 m_started = false;
00103 m_stopped = false;
00104 m_duration = 0;
00105 m_use_localtime = true;
00106 }
00107
00108
00109 void timer::mf_start_value(const timer::value_type a_t)
00110 {
00111 m_start = a_t;
00112 m_started = true;
00113 }
00114
00115
00116 void timer::mf_stop_value(const timer::value_type a_t)
00117 {
00118 m_stop = a_t;
00119 m_stopped = true;
00120 }
00121
00122
00123 const timer::duration_type
00124 timer::mf_calculate_duration(
00125 const timer::value_type a_start,
00126 const timer::value_type a_stop
00127 ) const
00128 {
00129 duration_type duration;
00130
00131 duration = difftime(a_stop,a_start);
00132
00133 return(duration);
00134 }
00135
00136
00137 void timer::start(void)
00138 {
00139 mf_start_value(time(0));
00140 }
00141
00142
00143 void timer::stop(void)
00144 {
00145 mf_stop_value(time(0));
00146 m_duration = mf_calculate_duration(m_start,m_stop);
00147 }
00148
00149
00150 const timer::value_type timer::start_value(void) const
00151 {
00152 return(m_start);
00153 }
00154
00155
00156 const timer::value_type timer::stop_value(void) const
00157 {
00158 return(m_stop);
00159 }
00160
00161
00162 void timer::assign(const timer& a_timer)
00163 {
00164 clear();
00165 mf_start_value(a_timer.start_value());
00166 mf_stop_value(a_timer.stop_value());
00167 m_started = a_timer.is_started();
00168 m_stopped = a_timer.is_stopped();
00169 if (m_stopped)
00170 m_duration = mf_calculate_duration(m_start,m_stop);
00171 }
00172
00173
00174 void timer::assign(const timer::value_type a_start)
00175 {
00176 clear();
00177 mf_start_value(a_start);
00178 }
00179
00180
00181 void timer::assign(
00182 const timer::value_type a_start,
00183 const timer::value_type a_stop)
00184 {
00185 clear();
00186 mf_start_value(a_start);
00187 mf_stop_value(a_stop);
00188 m_duration = mf_calculate_duration(m_start,m_stop);
00189 }
00190
00191
00192 timer& timer::operator=(const timer& a_timer)
00193 {
00194 assign(a_timer);
00195
00196 return(*this);
00197 }
00198
00199
00200 void timer::use_localtime(const bool a_switch)
00201 {
00202 m_use_localtime = a_switch;
00203 }
00204
00205
00206 const bool timer::use_localtime(void) const
00207 {
00208 return(m_use_localtime);
00209 }
00210
00211
00212 const std::string timer::mf_make_timer_string(const value_type a_t) const
00213 {
00214 std::string es;
00215 struct tm* l = 0;
00216 std::string str;
00217 const char* month_names[] = {
00218 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00219 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00220 };
00221
00222 if (m_use_localtime) {
00223 l = localtime(&a_t);
00224 if (l == 0) {
00225 TRY_nomem(es = "Could not convert time_t to localtime: \"");
00226 TRY_nomem(es += estring(a_t));
00227 TRY_nomem(es += "\"");
00228 throw(ERROR(errno,es));
00229 }
00230 }
00231 else {
00232 l = gmtime(&a_t);
00233 if (l == 0) {
00234 TRY_nomem(es = "Could not convert time_t to GMT: \"");
00235 TRY_nomem(es += estring(a_t));
00236 TRY_nomem(es += "\"");
00237 throw(ERROR(errno,es));
00238 }
00239 }
00240
00241 TRY(str += estring(l->tm_year + 1900).fmt_str(4,estring::right,'0','x'),
00242 "Error generating string from year");
00243
00244 TRY_nomem(str += " ");
00245
00246 TRY(str += estring(month_names[l->tm_mon]).fmt_str(3,estring::right,' ','x'),
00247 "Error generating string from month");
00248
00249 TRY_nomem(str += " ");
00250
00251 TRY(str += estring(l->tm_mday).fmt_str(2,estring::right,' ','x'),
00252 "Error generating string from day");
00253
00254 TRY_nomem(str += " ");
00255
00256 TRY(str += estring(l->tm_hour).fmt_str(2,estring::right,'0','x'),
00257 "Error generating string from hour");
00258
00259 TRY_nomem(str += ":");
00260
00261 TRY(str += estring(l->tm_min).fmt_str(2,estring::right,'0','x'),
00262 "Error generating string from minute");
00263
00264 TRY_nomem(str += ":");
00265
00266 TRY(str += estring(l->tm_sec).fmt_str(2,estring::right,'0','x'),
00267 "Error generating string from seconds");
00268
00269 return(str);
00270 }
00271
00272
00273 const std::string timer::mf_make_string(const timer::value_type a_t) const
00274 {
00275 std::string str;
00276
00277 TRY_nomem(str = mf_make_timer_string(a_t));
00278
00279 return(str);
00280 }
00281
00282
00283 const std::string timer::mf_make_string(const timer::duration_type a_d) const
00284 {
00285 uint64 deciseconds = 0;
00286 uint64 seconds = 0;
00287 uint64 minutes = 0;
00288 uint64 hours = 0;
00289 uint64 days = 0;
00290 uint64 years = 0;
00291 std::string str;
00292 bool negative = false;
00293
00294 if (a_d < 0) {
00295 negative = true;
00296 deciseconds = static_cast<uint64>(-a_d * 10.0);
00297 }
00298 else
00299 deciseconds = static_cast<uint64>(a_d * 10.0);
00300
00301 if (deciseconds >= 10) {
00302 seconds = deciseconds / 10;
00303 deciseconds %= 10;
00304 }
00305 if (seconds >= 60) {
00306 minutes = seconds / 60;
00307 seconds %= 60;
00308 }
00309 if (minutes >= 60) {
00310 hours = minutes / 60;
00311 minutes %= 60;
00312 }
00313 if (hours >= 24) {
00314 days = hours / 24;
00315 hours %= 24;
00316 }
00317 if (days >= 365) {
00318 years = days / 365;
00319 days %= 365;
00320 }
00321
00322 if (negative) {
00323 TRY_nomem(str += "-");
00324 }
00325
00326 if (years > 0) {
00327 TRY_nomem(str += estring(years));
00328 TRY_nomem(str += "y ");
00329 }
00330
00331 if ((years > 0) || (days > 0)) {
00332 TRY_nomem(str += estring(days));
00333 TRY_nomem(str += "d ");
00334 }
00335
00336 if ((years > 0) || (days > 0) || (hours > 0)) {
00337 TRY(str += estring(hours).fmt_str(2,estring::right,'0','x'),
00338 "Error generating string from hours");
00339 TRY_nomem(str += ":");
00340 }
00341
00342 TRY(str += estring(minutes).fmt_str(2,estring::right,'0','x'),
00343 "Error generating string from minutes");
00344
00345 TRY_nomem(str += ":");
00346
00347 TRY(str += estring(seconds).fmt_str(2,estring::right,'0','x'),
00348 "Error generating string from seconds");
00349
00350 TRY_nomem(str += ".");
00351
00352 TRY(str += estring(deciseconds).fmt_str(1,estring::right,'0','x'),
00353 "Error generating string from deciseconds");
00354
00355 return(str);
00356 }
00357
00358
00359 const std::string timer::started_at(void) const
00360 {
00361 std::string str;
00362
00363 if (!is_started())
00364 throw(INTERNAL_ERROR(0,"Request for start time from an unstarted timer"));
00365 TRY_nomem(str = mf_make_string(m_start));
00366
00367 return(str);
00368 }
00369
00370
00371 const std::string timer::stopped_at(void) const
00372 {
00373 std::string str;
00374
00375 if (!is_started())
00376 throw(INTERNAL_ERROR(0,"Request for stop time from an unstarted timer"));
00377 if (!is_stopped())
00378 throw(INTERNAL_ERROR(0,"Request for stop time from a running timer"));
00379 TRY_nomem(str = mf_make_string(m_stop));
00380
00381 return(str);
00382 }
00383
00384
00385 const std::string timer::duration(void) const
00386 {
00387 std::string str;
00388
00389 if (!is_started())
00390 throw(INTERNAL_ERROR(0,"Request for stop time from an unstarted timer"));
00391 if (!is_stopped())
00392 throw(INTERNAL_ERROR(0,"Request for duration from a running timer"));
00393 TRY_nomem(str = mf_make_string(m_duration));
00394
00395 return(str);
00396 }
00397
00398
00399 const bool timer::is_started(void) const
00400 {
00401 return(m_started);
00402 }
00403
00404
00405 const bool timer::is_stopped(void) const
00406 {
00407 return(m_stopped);
00408 }
00409
00410
00411 const timer::duration_type timer::duration_secs(void) const
00412 {
00413 if (!is_started())
00414 throw(INTERNAL_ERROR(0,"Request for duration from an unstarted timer"));
00415 if (!is_stopped())
00416 throw(INTERNAL_ERROR(0,"Request for duration from a running timer"));
00417
00418 return(m_duration);
00419 }
00420
00421
00422 const timer::duration_type timer::duration_mins(void) const
00423 {
00424 duration_type value;
00425
00426 value = duration_secs()/static_cast<duration_type>(60.0);
00427
00428 return(value);
00429 }
00430
00431
00432 const timer::duration_type timer::duration_hours(void) const
00433 {
00434 duration_type value;
00435
00436 value = duration_mins()/static_cast<duration_type>(60.0);
00437
00438 return(value);
00439 }
00440
00441
00442 const timer::duration_type timer::duration_days(void) const
00443 {
00444 duration_type value;
00445
00446 value = duration_hours()/static_cast<duration_type>(24.0);
00447
00448 return(value);
00449 }
00450
00451
00452 const timer::duration_type timer::duration_years(void) const
00453 {
00454 duration_type value;
00455
00456 value = duration_days()/static_cast<duration_type>(365.0);
00457
00458 return(value);
00459 }
00460
00461
00462
00463 const std::string timer::eta(unsigned int a_percent_complete) const
00464 {
00465 safe_num<duration_type> total_duration;
00466 safe_num<duration_type> eta;
00467 std::string es;
00468 std::string str;
00469
00470 if (!is_started())
00471 throw(INTERNAL_ERROR(0,"Attempt to calculate ETA for unstarted timer"));
00472 if (!is_stopped())
00473 throw(INTERNAL_ERROR(0,"Attempt to calculate ETA for a running timer"));
00474 if (a_percent_complete == 0) {
00475 TRY_nomem(str = "??:??.?");
00476 return(str);
00477 }
00478
00479 TRY_nomem(es = "Could not calculate ETA");
00480 TRY(
00481 total_duration = m_duration;
00482 total_duration *= 100;
00483 total_duration /= a_percent_complete;
00484 eta = total_duration - safe_num<duration_type>(m_duration);
00485 ,es);
00486 TRY_nomem(str = mf_make_string(eta.value()));
00487
00488 return(str);
00489 }
00490
00491
00492
00493 const std::string timer::eta(
00494 unsigned int a_complete, unsigned int a_total) const
00495 {
00496 safe_num<unsigned int> percent_complete;
00497 std::string es;
00498 std::string str;
00499
00500 if (!is_started())
00501 throw(INTERNAL_ERROR(0,"Attempt to calculate ETA for unstarted timer"));
00502 if (!is_stopped())
00503 throw(INTERNAL_ERROR(0,"Attempt to calculate ETA for a running timer"));
00504 if (a_total == 0) {
00505 TRY_nomem(str = "??:??.?");
00506 return(str);
00507 }
00508
00509 TRY_nomem(es = "Could not calculate ETA");
00510 TRY(
00511 percent_complete = a_complete;
00512 percent_complete *= 100;
00513 percent_complete /= a_total;
00514 ,es);
00515
00516 TRY_nomem(str = eta(percent_complete.value()));
00517
00518 return(str);
00519 }
00520
00521
00522 const std::string timer::bps(uint64 a_bytes) const
00523 {
00524 uint64 bps;
00525 std::string str;
00526
00527 if (!is_started())
00528 throw(INTERNAL_ERROR(0,"Attempt to calculate bps for unstarted timer"));
00529 if (!is_stopped())
00530 throw(INTERNAL_ERROR(0,"Attempt to calculate bps for a running timer"));
00531
00532 if (m_duration == 0)
00533 bps = a_bytes;
00534 else
00535 bps = static_cast<uint64>(a_bytes / m_duration);
00536 TRY_nomem(str = throughput_to_string(bps));
00537
00538 return(str);
00539 }
00540
00541
00542 const std::string current_time(void)
00543 {
00544 std::string str;
00545
00546 TRY_nomem(str = make_time_string_(time(0)));
00547
00548 return(str);
00549 }
00550
00551
00552 std::string stamp(const pid_t a_pid, const int a_indention)
00553 {
00554 std::string str;
00555 int indent;
00556 pid_t this_pid;
00557
00558 indent = a_indention;
00559 TRY_nomem(str = current_time());
00560 TRY_nomem(str += " [");
00561 if (a_pid == 0)
00562 this_pid = pid();
00563 else
00564 this_pid = a_pid;
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 TRY_nomem(str +=
00577 estring(static_cast<unsigned long>(this_pid)).fmt_str(
00578 6,estring::right,' ',' '
00579 )
00580 );
00581
00582 TRY_nomem(str += "]");
00583 TRY_nomem(str += "> ");
00584 for (; indent > 0; str += " ", --indent);
00585
00586 return(str);
00587 }
00588