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