00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "lib/config.h"
00013
00014 #include "lib/io.h"
00015 #include "lib/ShogunException.h"
00016 #include "lib/Signal.h"
00017 #include "lib/common.h"
00018 #include "lib/Time.h"
00019 #include "lib/Mathematics.h"
00020
00021 #include <stdio.h>
00022 #include <stdarg.h>
00023 #include <ctype.h>
00024
00025 #include <stdlib.h>
00026
00027 using namespace shogun;
00028
00029 const EMessageType CIO::levels[NUM_LOG_LEVELS]={MSG_GCDEBUG, MSG_DEBUG, MSG_INFO, MSG_NOTICE,
00030 MSG_WARN, MSG_ERROR, MSG_CRITICAL, MSG_ALERT, MSG_EMERGENCY, MSG_MESSAGEONLY};
00031
00032 const char* CIO::message_strings[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0",
00033 "[NOTICE] \0", "\033[1;34m[WARN]\033[0m \0", "\033[1;31m[ERROR]\033[0m \0",
00034 "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"};
00035
00037 char CIO::file_buffer[FBUFSIZE];
00038
00040 char CIO::directory_name[FBUFSIZE];
00041
00042 CIO::CIO()
00043 : target(stdout), last_progress_time(0), progress_start_time(0),
00044 last_progress(1), show_progress(false), show_file_and_line(false),
00045 loglevel(MSG_WARN), refcount(0)
00046 {
00047 }
00048
00049 CIO::CIO(const CIO& orig)
00050 : target(orig.get_target()), last_progress_time(0),
00051 progress_start_time(0), last_progress(1),
00052 show_progress(orig.get_show_progress()),
00053 show_file_and_line(orig.get_show_file_and_line()),
00054 loglevel(orig.get_loglevel()), refcount(0)
00055 {
00056 }
00057
00058 void CIO::message(EMessageType prio, const char* file,
00059 int32_t line, const char *fmt, ... ) const
00060 {
00061 const char* msg_intro=get_msg_intro(prio);
00062
00063 if (msg_intro)
00064 {
00065 char str[4096];
00066 snprintf(str, sizeof(str), "%s", msg_intro);
00067 int len=strlen(msg_intro);
00068 char* s=str+len;
00069
00070 if (show_file_and_line && line>0)
00071 {
00072 snprintf(s, sizeof(str)-len, "In file %s line %d: ", file, line);
00073 len=strlen(str);
00074 s=str+len;
00075 }
00076
00077 va_list list;
00078 va_start(list,fmt);
00079 vsnprintf(s, sizeof(str)-len, fmt, list);
00080 va_end(list);
00081
00082 switch (prio)
00083 {
00084 case MSG_GCDEBUG:
00085 case MSG_DEBUG:
00086 case MSG_INFO:
00087 case MSG_NOTICE:
00088 case MSG_MESSAGEONLY:
00089 if (sg_print_message)
00090 sg_print_message(target, str);
00091 break;
00092
00093 case MSG_WARN:
00094 if (sg_print_warning)
00095 sg_print_warning(target, str);
00096 break;
00097
00098 case MSG_ERROR:
00099 case MSG_CRITICAL:
00100 case MSG_ALERT:
00101 case MSG_EMERGENCY:
00102 if (sg_print_error)
00103 sg_print_error(target, str);
00104 throw ShogunException(str);
00105 break;
00106 default:
00107 break;
00108 }
00109
00110 fflush(target);
00111 }
00112 }
00113
00114 void CIO::buffered_message(EMessageType prio, const char *fmt, ... ) const
00115 {
00116 const char* msg_intro=get_msg_intro(prio);
00117
00118 if (msg_intro)
00119 {
00120 fprintf(target, "%s", msg_intro);
00121 va_list list;
00122 va_start(list,fmt);
00123 vfprintf(target,fmt,list);
00124 va_end(list);
00125 }
00126 }
00127
00128 void CIO::progress(
00129 float64_t current_val, float64_t min_val, float64_t max_val,
00130 int32_t decimals, const char* prefix)
00131 {
00132 if (!show_progress)
00133 return;
00134
00135 float64_t runtime = CTime::get_curtime();
00136
00137 char str[1000];
00138 float64_t v=-1, estimate=0, total_estimate=0 ;
00139
00140 if (max_val-min_val>0.0)
00141 v=100*(current_val-min_val+1)/(max_val-min_val+1);
00142
00143 if (decimals < 1)
00144 decimals = 1;
00145
00146 if (last_progress>v)
00147 {
00148 last_progress_time = runtime;
00149 progress_start_time = runtime;
00150 last_progress = v;
00151 }
00152 else
00153 {
00154 v=CMath::clamp(v,1e-5,100.0);
00155 last_progress = v-1e-6;
00156
00157 if ((v!=100.0) && (runtime - last_progress_time<0.5))
00158 return;
00159
00160 last_progress_time = runtime;
00161 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
00162 total_estimate = (last_progress_time-progress_start_time)/(v/100);
00163 }
00164
00165 if (estimate>120)
00166 {
00167 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
00168 message(MSG_MESSAGEONLY, "", -1, str, prefix, v, estimate/60, total_estimate/60);
00169 }
00170 else
00171 {
00172 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
00173 message(MSG_MESSAGEONLY, "", -1, str, prefix, v, estimate, total_estimate);
00174 }
00175
00176 fflush(target);
00177 }
00178
00179 void CIO::absolute_progress(
00180 float64_t current_val, float64_t val, float64_t min_val, float64_t max_val,
00181 int32_t decimals, const char* prefix)
00182 {
00183 if (!show_progress)
00184 return;
00185
00186 float64_t runtime = CTime::get_curtime();
00187
00188 char str[1000];
00189 float64_t v=-1, estimate=0, total_estimate=0 ;
00190
00191 if (max_val-min_val>0)
00192 v=100*(val-min_val+1)/(max_val-min_val+1);
00193
00194 if (decimals < 1)
00195 decimals = 1;
00196
00197 if (last_progress>v)
00198 {
00199 last_progress_time = runtime;
00200 progress_start_time = runtime;
00201 last_progress = v;
00202 }
00203 else
00204 {
00205 v=CMath::clamp(v,1e-5,100.0);
00206 last_progress = v-1e-6;
00207
00208 if ((v!=100.0) && (runtime - last_progress_time<100))
00209 return;
00210
00211 last_progress_time = runtime;
00212 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
00213 total_estimate = (last_progress_time-progress_start_time)/(v/100);
00214 }
00215
00216 if (estimate>120)
00217 {
00218 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
00219 message(MSG_MESSAGEONLY, "", -1, str, prefix, current_val, estimate/60, total_estimate/60);
00220 }
00221 else
00222 {
00223 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
00224 message(MSG_MESSAGEONLY, "", -1, str, prefix, current_val, estimate, total_estimate);
00225 }
00226
00227 fflush(target);
00228 }
00229
00230 void CIO::done()
00231 {
00232 if (!show_progress)
00233 return;
00234
00235 message(MSG_INFO, "", -1, "done.\n");
00236 }
00237
00238 char* CIO::skip_spaces(char* str)
00239 {
00240 int32_t i=0;
00241
00242 if (str)
00243 {
00244 for (i=0; isspace(str[i]); i++);
00245
00246 return &str[i];
00247 }
00248 else
00249 return str;
00250 }
00251
00252 char* CIO::skip_blanks(char* str)
00253 {
00254 int32_t i=0;
00255
00256 if (str)
00257 {
00258 for (i=0; isblank(str[i]); i++);
00259
00260 return &str[i];
00261 }
00262 else
00263 return str;
00264 }
00265
00266 EMessageType CIO::get_loglevel() const
00267 {
00268 return loglevel;
00269 }
00270
00271 void CIO::set_loglevel(EMessageType level)
00272 {
00273 loglevel=level;
00274 }
00275
00276 void CIO::set_target(FILE* t)
00277 {
00278 target=t;
00279 }
00280
00281 const char* CIO::get_msg_intro(EMessageType prio) const
00282 {
00283 for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--)
00284 {
00285
00286
00287 if (levels[i]<loglevel && prio<=MSG_WARN)
00288 return NULL;
00289
00290 if (levels[i]==prio)
00291 return message_strings[i];
00292 }
00293
00294 return NULL;
00295 }