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 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         // ignore msg if prio's level is under loglevel,
00279         // but not if prio's level higher than M_WARN
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 }

SHOGUN Machine Learning Toolbox - Documentation