io.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 1999-2009 Soeren Sonnenburg
00008  * Written (W) 1999-2009 Gunnar Raetsch
00009  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
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         // ignore msg if prio's level is under loglevel,
00286         // but not if prio's level higher than MSG_WARN
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 }

SHOGUN Machine Learning Toolbox - Documentation