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