00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "lib/config.h"
00013 #include "lib/matlab.h"
00014 #include "lib/octave.h"
00015 #include "lib/r.h"
00016 #include "lib/python.h"
00017
00018 #include "lib/io.h"
00019 #include "lib/ShogunException.h"
00020 #include "lib/Signal.h"
00021 #include "lib/common.h"
00022 #include "lib/Time.h"
00023 #include "lib/Mathematics.h"
00024
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027
00028 #include <stdio.h>
00029 #include <stdarg.h>
00030 #include <ctype.h>
00031 #include <dirent.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034
00035 const EMessageType CIO::levels[NUM_LOG_LEVELS]={M_DEBUG, M_INFO, M_NOTICE, M_WARN, M_ERROR, M_CRITICAL, M_ALERT, M_EMERGENCY, M_MESSAGEONLY};
00036 const char* CIO::message_strings[NUM_LOG_LEVELS]={"[DEBUG] ", "[INFO] ", "[NOTICE] ", "\033[1;34m[WARN]\033[0m ", "\033[1;31m[ERROR]\033[0m ", "[CRITICAL] ", "[ALERT] ", "[EMERGENCY] ", ""};
00037
00039 char file_buffer[FBUFSIZE];
00040
00042 char directory_name[FBUFSIZE];
00043
00044 CIO::CIO()
00045 : target(stdout), last_progress_time(0), progress_start_time(0),
00046 last_progress(1), show_progress(false), loglevel(M_WARN)
00047 {
00048 }
00049
00050 CIO::CIO(const CIO& orig)
00051 : target(orig.get_target()), last_progress_time(0),
00052 progress_start_time(0), last_progress(1),
00053 show_progress(orig.get_show_progress()), loglevel(orig.get_loglevel())
00054 {
00055 }
00056
00057 void CIO::message(EMessageType prio, const char *fmt, ... ) const
00058 {
00059 const char* msg_intro=get_msg_intro(prio);
00060 if (!msg_intro)
00061 return;
00062
00063 char str[4096];
00064 va_list list;
00065 va_start(list,fmt);
00066 vsnprintf(str, sizeof(str), 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 defined(WIN32) && defined(HAVE_MATLAB)
00076 fprintf(target, "%s", msg_intro);
00077 mexPrintf("%s", str);
00078 #elif defined(HAVE_R)
00079 if (target==stdout)
00080 {
00081 Rprintf((char*) "%s", msg_intro);
00082 Rprintf((char*) "%s", str);
00083 }
00084 else
00085 {
00086 fprintf(target, "%s", msg_intro);
00087 fprintf(target, "%s", str);
00088 }
00089 #else
00090 fprintf(target, "%s", msg_intro);
00091 fprintf(target, "%s", str);
00092 #endif
00093 break;
00094
00095 case M_WARN:
00096 #if defined(HAVE_MATLAB)
00097 mexWarnMsgTxt(str);
00098 #elif defined(HAVE_OCTAVE)
00099 ::warning(str);
00100 #elif defined(HAVE_PYTHON) // no check for swig necessary
00101 PyErr_Warn(NULL, str);
00102 #elif defined(HAVE_R)
00103 if (target==stdout)
00104 {
00105 Rprintf((char*) "%s", msg_intro);
00106 Rprintf((char*) "%s", str);
00107 }
00108 else
00109 {
00110 fprintf(target, "%s", msg_intro);
00111 fprintf(target, "%s", str);
00112 }
00113 #else
00114 fprintf(target, "%s", msg_intro);
00115 fprintf(target, "%s", str);
00116 #endif
00117 break;
00118
00119 case M_ERROR:
00120 case M_CRITICAL:
00121 case M_ALERT:
00122 case M_EMERGENCY:
00123 #if defined(WIN32) && defined(HAVE_MATLAB)
00124 mexPrintf("%s", str);
00125 #elif defined(HAVE_PYTHON)
00126
00127 #elif defined(HAVE_R)
00128 if (target==stdout)
00129 {
00130 Rprintf((char*) "%s", msg_intro);
00131 Rprintf((char*) "%s", str);
00132 }
00133 else
00134 {
00135 fprintf(target, "%s", msg_intro);
00136 fprintf(target, "%s", str);
00137 }
00138 #else
00139 fprintf(target, "%s", str);
00140 #endif
00141 throw ShogunException(str);
00142 break;
00143 default:
00144 break;
00145 }
00146
00147 fflush(target);
00148 }
00149
00150 void CIO::buffered_message(EMessageType prio, const char *fmt, ... ) const
00151 {
00152 const char* msg_intro=get_msg_intro(prio);
00153 if (!msg_intro)
00154 return;
00155
00156 fprintf(target, "%s", msg_intro);
00157 va_list list;
00158 va_start(list,fmt);
00159 vfprintf(target,fmt,list);
00160 va_end(list);
00161 }
00162
00163 void CIO::progress(
00164 float64_t current_val, float64_t min_val, float64_t max_val,
00165 int32_t decimals, const char* prefix)
00166 {
00167 if (!show_progress)
00168 return;
00169
00170 int64_t runtime = CTime::get_runtime();
00171
00172 char str[1000];
00173 float64_t v=-1, estimate=0, total_estimate=0 ;
00174
00175 if (max_val-min_val>0.0)
00176 v=100*(current_val-min_val+1)/(max_val-min_val+1);
00177
00178 if (decimals < 1)
00179 decimals = 1;
00180
00181 if (last_progress>v)
00182 {
00183 last_progress_time = runtime ;
00184 progress_start_time = runtime;
00185 last_progress = v ;
00186 }
00187 else
00188 {
00189 if (v>100) v=100.0 ;
00190 if (v<=0) v=1e-5 ;
00191 last_progress = v-1e-6 ; ;
00192
00193 if ((v!=100.0) && (runtime - last_progress_time<10))
00194 return ;
00195
00196 last_progress_time = runtime ;
00197 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00198 total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00199 }
00200
00201 if (estimate/100>120)
00202 {
00203 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
00204 message(M_MESSAGEONLY, str, prefix, v, (float32_t)estimate/100/60, (float32_t)total_estimate/100/60);
00205 }
00206 else
00207 {
00208 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
00209 message(M_MESSAGEONLY, str, prefix, v, (float32_t)estimate/100, (float32_t)total_estimate/100);
00210 }
00211
00212 fflush(target);
00213 }
00214
00215 void CIO::absolute_progress(
00216 float64_t current_val, float64_t val, float64_t min_val, float64_t max_val,
00217 int32_t decimals, const char* prefix)
00218 {
00219 if (!show_progress)
00220 return;
00221
00222 int64_t runtime = CTime::get_runtime();
00223
00224 char str[1000];
00225 float64_t v=-1, estimate=0, total_estimate=0 ;
00226
00227 if (max_val-min_val>0)
00228 v=100*(val-min_val+1)/(max_val-min_val+1);
00229
00230 if (decimals < 1)
00231 decimals = 1;
00232
00233 if (last_progress>v)
00234 {
00235 last_progress_time = runtime ;
00236 progress_start_time = runtime;
00237 last_progress = v ;
00238 }
00239 else
00240 {
00241 if (v>100) v=100.0 ;
00242 if (v<=0) v=1e-6 ;
00243 last_progress = v-1e-5 ; ;
00244
00245 if ((v!=100.0) && (runtime - last_progress_time<100))
00246 return ;
00247
00248 last_progress_time = runtime ;
00249 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00250 total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00251 }
00252
00253 if (estimate/100>120)
00254 {
00255 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
00256 message(M_MESSAGEONLY, str, prefix, current_val, (float32_t)estimate/100/60, (float32_t)total_estimate/100/60);
00257 }
00258 else
00259 {
00260 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
00261 message(M_MESSAGEONLY, str, prefix, current_val, (float32_t)estimate/100, (float32_t)total_estimate/100);
00262 }
00263
00264 fflush(target);
00265 }
00266
00267 void CIO::done()
00268 {
00269 if (!show_progress)
00270 return;
00271
00272 message(M_INFO, "done.\n");
00273 }
00274
00275 char* CIO::skip_spaces(char* str)
00276 {
00277 int32_t i=0;
00278
00279 if (str)
00280 {
00281 for (i=0; isspace(str[i]); i++);
00282
00283 return &str[i];
00284 }
00285 else
00286 return str;
00287 }
00288
00289 char* CIO::skip_blanks(char* str)
00290 {
00291 int32_t i=0;
00292
00293 if (str)
00294 {
00295 for (i=0; isblank(str[i]); i++);
00296
00297 return &str[i];
00298 }
00299 else
00300 return str;
00301 }
00302
00303 EMessageType CIO::get_loglevel() const
00304 {
00305 return loglevel;
00306 }
00307
00308 void CIO::set_loglevel(EMessageType level)
00309 {
00310 loglevel=level;
00311 }
00312
00313 bool CIO::get_show_progress() const
00314 {
00315 return show_progress;
00316 }
00317
00318 void CIO::set_target(FILE* t)
00319 {
00320 target=t;
00321 }
00322
00323 const char* CIO::get_msg_intro(EMessageType prio) const
00324 {
00325 for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--)
00326 {
00327
00328
00329 if (levels[i]<loglevel && prio<=M_WARN)
00330 return NULL;
00331
00332 if (levels[i]==prio)
00333 return message_strings[i];
00334 }
00335
00336 return NULL;
00337 }
00338
00339 char* CIO::concat_filename(const char* filename)
00340 {
00341 if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE)
00342 SG_SERROR("filename too long");
00343 return file_buffer;
00344 }
00345
00346 int CIO::filter(CONST_DIRENT_T* d)
00347 {
00348 if (d)
00349 {
00350 char* fname=concat_filename(d->d_name);
00351
00352 if (!access(fname, R_OK))
00353 {
00354 struct stat s;
00355 if (!stat(fname, &s) && S_ISREG(s.st_mode))
00356 return 1;
00357 }
00358 }
00359
00360 return 0;
00361 }