Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Logging_Strategy.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: Logging_Strategy.cpp,v 1.1.1.2.2.1 2003/03/13 19:44:21 chad Exp $
00003 
00004 #include "ace/Get_Opt.h"
00005 #include "ace/streams.h"
00006 #include "ace/Log_Msg.h"
00007 #include "ace/Reactor.h"
00008 #include "ace/Logging_Strategy.h"
00009 
00010 ACE_RCSID(lib, Logging_Strategy, "$Id: Logging_Strategy.cpp,v 1.1.1.2.2.1 2003/03/13 19:44:21 chad Exp $")
00011 
00012 // Parse the string containing (thread) priorities and set them
00013 // accordingly.
00014 
00015 void
00016 ACE_Logging_Strategy::priorities (ACE_TCHAR *priority_string,
00017                                   ACE_Log_Msg::MASK_TYPE mask)
00018 {
00019   u_long priority_mask = 0;
00020 
00021   // Choose priority mask to change.
00022 
00023   if (mask == ACE_Log_Msg::PROCESS)
00024     priority_mask = process_priority_mask_;
00025   else
00026     priority_mask = thread_priority_mask_;
00027 
00028   ACE_TCHAR *strtokp;
00029 
00030   // Parse string and alternate priority mask.
00031 
00032   for (ACE_TCHAR *priority = ACE_OS_String::strtok_r (priority_string,
00033                                                       ACE_LIB_TEXT ("|"),
00034                                                       &strtokp);
00035        priority != 0;
00036        priority = ACE_OS_String::strtok_r (0,
00037                                            ACE_LIB_TEXT ("|"),
00038                                            &strtokp))
00039     {
00040       if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("SHUTDOWN")) == 0)
00041         ACE_SET_BITS (priority_mask, LM_SHUTDOWN);
00042       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~SHUTDOWN")) == 0)
00043         ACE_CLR_BITS (priority_mask, LM_SHUTDOWN);
00044       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("TRACE")) == 0)
00045         ACE_SET_BITS (priority_mask, LM_TRACE);
00046       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~TRACE")) == 0)
00047         ACE_CLR_BITS (priority_mask, LM_TRACE);
00048       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("DEBUG")) == 0)
00049         ACE_SET_BITS (priority_mask, LM_DEBUG);
00050       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~DEBUG")) == 0)
00051         ACE_CLR_BITS (priority_mask, LM_DEBUG);
00052       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("INFO")) == 0)
00053         ACE_SET_BITS (priority_mask, LM_INFO);
00054       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~INFO")) == 0)
00055         ACE_CLR_BITS (priority_mask, LM_INFO);
00056       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("NOTICE")) == 0)
00057         ACE_SET_BITS (priority_mask, LM_NOTICE);
00058       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~NOTICE")) == 0)
00059         ACE_CLR_BITS (priority_mask, LM_NOTICE);
00060       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("WARNING")) == 0)
00061         ACE_SET_BITS (priority_mask, LM_WARNING);
00062       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~WARNING")) == 0)
00063         ACE_CLR_BITS (priority_mask, LM_WARNING);
00064       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("STARTUP")) == 0)
00065         ACE_SET_BITS (priority_mask, LM_STARTUP);
00066       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~STARTUP")) == 0)
00067         ACE_CLR_BITS (priority_mask, LM_STARTUP);
00068       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("ERROR")) == 0)
00069         ACE_SET_BITS (priority_mask, LM_ERROR);
00070       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~ERROR")) == 0)
00071         ACE_CLR_BITS (priority_mask, LM_ERROR);
00072       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("CRITICAL")) == 0)
00073         ACE_SET_BITS (priority_mask, LM_CRITICAL);
00074       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~CRITICAL")) == 0)
00075         ACE_CLR_BITS (priority_mask, LM_CRITICAL);
00076       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("ALERT")) == 0)
00077         ACE_SET_BITS (priority_mask, LM_ALERT);
00078       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~ALERT")) == 0)
00079         ACE_CLR_BITS (priority_mask, LM_ALERT);
00080       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("EMERGENCY")) == 0)
00081         ACE_SET_BITS (priority_mask, LM_EMERGENCY);
00082       else if (ACE_OS::strcmp (priority, ACE_LIB_TEXT ("~EMERGENCY")) == 0)
00083         ACE_CLR_BITS (priority_mask, LM_EMERGENCY);
00084     }
00085 
00086   // Affect right priority mask.
00087 
00088   if (mask == ACE_Log_Msg::PROCESS)
00089     process_priority_mask_ = priority_mask;
00090   else
00091     thread_priority_mask_ = priority_mask;
00092 }
00093 
00094 // Parse the string containing all the flags and set the flags
00095 // accordingly.
00096 
00097 void
00098 ACE_Logging_Strategy::tokenize (ACE_TCHAR *flag_string)
00099 {
00100   ACE_TCHAR *strtokp;
00101 
00102   for (ACE_TCHAR *flag = ACE_OS::strtok_r (flag_string,
00103                                            ACE_LIB_TEXT ("|"),
00104                                            &strtokp);
00105        flag != 0;
00106        flag = ACE_OS::strtok_r (0, ACE_LIB_TEXT ("|"), &strtokp))
00107     {
00108       if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("STDERR")) == 0)
00109         ACE_SET_BITS (this->flags_, ACE_Log_Msg::STDERR);
00110       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("LOGGER")) == 0)
00111         ACE_SET_BITS (this->flags_, ACE_Log_Msg::LOGGER);
00112       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("OSTREAM")) == 0)
00113         ACE_SET_BITS (this->flags_, ACE_Log_Msg::OSTREAM);
00114       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("VERBOSE")) == 0)
00115         ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE);
00116       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("VERBOSE_LITE")) == 0)
00117         ACE_SET_BITS (this->flags_, ACE_Log_Msg::VERBOSE_LITE);
00118       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("SILENT")) == 0)
00119         ACE_SET_BITS (this->flags_, ACE_Log_Msg::SILENT);
00120       else if (ACE_OS::strcmp (flag, ACE_LIB_TEXT ("SYSLOG")) == 0)
00121         ACE_SET_BITS (this->flags_, ACE_Log_Msg::SYSLOG);
00122     }
00123 }
00124 
00125 int
00126 ACE_Logging_Strategy::parse_args (int argc, ACE_TCHAR *argv[])
00127 {
00128   ACE_TRACE ("ACE_Logging_Strategy::parse_args");
00129   ACE_TCHAR *temp;
00130 
00131   // Perform data member initializations.  BTW, do *not* initialize
00132   // <thread_priority_mask_> or <process_priority_mask_> here to avoid
00133   // unduing the behavior in <init>, where these are set by
00134   // <ACE_Log_Msg::instance>.
00135   this->flags_ = 0;
00136   this->wipeout_logfile_ = 0;
00137   this->count_ = 0;
00138   this->fixed_number_ = 0;
00139   this->order_files_ = 0;
00140   this->max_file_number_ = 1;
00141   this->interval_ = ACE_DEFAULT_LOGFILE_POLL_INTERVAL;
00142   this->max_size_ = 0;
00143 
00144   ACE_Get_Opt get_opt (argc, argv,
00145                        ACE_LIB_TEXT ("f:i:k:m:n:N:op:s:t:w"), 0);
00146 
00147   for (int c; (c = get_opt ()) != -1; )
00148     {
00149       switch (c)
00150         {
00151         case 'f':
00152           temp = get_opt.opt_arg ();
00153           // Now tokenize the string to get all the flags
00154           this->tokenize (temp);
00155           // If LOGGER was specified, set up the default logger key.
00156           // The key can be changed by the -k option also, so if it's
00157           // been set already, don't set it.
00158           if (ACE_BIT_ENABLED (this->flags_, ACE_Log_Msg::LOGGER) &&
00159               this->logger_key_ == 0)
00160             this->logger_key_ = ACE::strnew (ACE_DEFAULT_LOGGER_KEY);
00161           break;
00162         case 'i':
00163           // Interval (in secs) at which logfile size is sampled.
00164           this->interval_ = ACE_OS::strtoul (get_opt.opt_arg (), 0, 10);
00165           break;
00166         case 'k':
00167           // Ensure that the LOGGER flag is set
00168           ACE_SET_BITS (this->flags_, ACE_Log_Msg::LOGGER);
00169           delete [] this->logger_key_;
00170           this->logger_key_ = ACE::strnew (get_opt.opt_arg ());
00171           break;
00172         case 'm':
00173           // Maximum logfile size (in KB).  Must be a non-zero value.
00174           this->max_size_ = ACE_OS::strtoul (get_opt.opt_arg (), 0, 10);
00175           this->max_size_ <<= 10;       // convert to KB
00176           break;
00177         case 'n':
00178           delete [] this->program_name_;
00179           this->program_name_ = ACE::strnew (get_opt.opt_arg ());
00180           break;
00181         case 'N':
00182           // The max number for the log_file being created
00183           this->max_file_number_ = ACE_OS::atoi (get_opt.opt_arg ()) - 1;
00184           this->fixed_number_ = 1;
00185           break;
00186         case 'o':
00187           // Log_files generation order
00188           this->order_files_ = 1;
00189           break;
00190         case 'p':
00191           temp = get_opt.opt_arg ();
00192           // Now tokenize the string to setup process log priority
00193           this->priorities (temp, ACE_Log_Msg::PROCESS);
00194           break;
00195         case 's':
00196           // Ensure that the OSTREAM flag is set
00197           ACE_SET_BITS (this->flags_, ACE_Log_Msg::OSTREAM);
00198           delete [] this->filename_;
00199           this->filename_ = ACE::strnew (get_opt.opt_arg ());
00200           break;
00201         case 't':
00202           temp = get_opt.opt_arg ();
00203           // Now tokenize the string to setup thread log priority
00204           this->priorities (temp, ACE_Log_Msg::THREAD);
00205           break;
00206         case 'w':
00207           // Cause the logfile to be wiped out, both on startup and on
00208           // reconfigure.
00209           this->wipeout_logfile_ = 1;
00210           break;
00211         default:
00212           break;
00213         }
00214     }
00215   return 0;
00216 }
00217 
00218 ACE_Logging_Strategy::ACE_Logging_Strategy (void)
00219   : log_msg_ (ACE_Log_Msg::instance ())
00220 {
00221 #if defined (ACE_DEFAULT_LOGFILE)
00222   this->filename_ = ACE::strnew (ACE_DEFAULT_LOGFILE);
00223 #else /* ACE_DEFAULT_LOGFILE */
00224   ACE_NEW (this->filename_,
00225            ACE_TCHAR[MAXPATHLEN + 1]);
00226 
00227   // Get the temporary directory
00228   if (ACE_Lib_Find::get_temp_dir 
00229       (this->filename_,
00230        MAXPATHLEN - 7) == -1) // 7 for "logfile"
00231     {
00232       ACE_ERROR ((LM_ERROR,
00233                   ACE_LIB_TEXT ("Temporary path too long, ")
00234                   ACE_LIB_TEXT ("defaulting to current directory\n")));
00235       this->filename_[0] = 0;
00236     }
00237 
00238   // Add the filename to the end
00239   ACE_OS::strcat (this->filename_,
00240                   ACE_LIB_TEXT ("logfile"));
00241 #endif /* ACE_DEFAULT_LOGFILE */
00242   this->logger_key_ = 0;
00243   this->program_name_ = 0;
00244 }
00245 
00246 int
00247 ACE_Logging_Strategy::fini (void)
00248 {
00249   delete [] this->filename_;
00250   delete [] this->logger_key_;
00251   delete [] this->program_name_;
00252 
00253   if (this->interval_ > 0 && this->max_size_ > 0)
00254     this->reactor ()->cancel_timer (this);
00255 
00256   return 0;
00257 }
00258 
00259 int
00260 ACE_Logging_Strategy::init (int argc, ACE_TCHAR *argv[])
00261 {
00262   ACE_TRACE ("ACE_Logging_Strategy::init");
00263 
00264   // Store current priority masks for changes in <parse_args>.
00265 
00266   this->process_priority_mask_ =
00267     this->log_msg_->priority_mask (ACE_Log_Msg::PROCESS);
00268 
00269   this->thread_priority_mask_ =
00270     this->log_msg_->priority_mask (ACE_Log_Msg::THREAD);
00271 
00272   // Use the options hook to parse the command line arguments.
00273   this->parse_args (argc, argv);
00274 
00275   // Setup priorities (to original if not specified on command line)
00276 
00277   this->log_msg_->priority_mask (thread_priority_mask_,
00278                                  ACE_Log_Msg::THREAD);
00279 
00280   this->log_msg_->priority_mask (process_priority_mask_,
00281                                  ACE_Log_Msg::PROCESS);
00282 
00283   // Check if any flags were specified. If none were specified, let
00284   // the default behavior take effect.
00285   if (this->flags_ != 0)
00286     {
00287       // Clear all flags
00288       this->log_msg_->clr_flags (ACE_Log_Msg::STDERR
00289                                 | ACE_Log_Msg::LOGGER
00290                                 | ACE_Log_Msg::OSTREAM
00291                                 | ACE_Log_Msg::VERBOSE
00292                                 | ACE_Log_Msg::VERBOSE_LITE
00293                                 | ACE_Log_Msg::SILENT
00294                                 | ACE_Log_Msg::SYSLOG);
00295       // Check if OSTREAM bit is set
00296       if (ACE_BIT_ENABLED (this->flags_,
00297                            ACE_Log_Msg::OSTREAM))
00298         {
00299 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
00300           FILE *output_file = 0;
00301           if (wipeout_logfile_)
00302             output_file = ACE_OS::fopen (this->filename_, ACE_LIB_TEXT ("wt"));
00303           else
00304             output_file = ACE_OS::fopen (this->filename_, ACE_LIB_TEXT ("at"));
00305           if (output_file == 0)
00306             return -1;
00307 #else
00308           ofstream *output_file = 0;
00309           // Create a new ofstream to direct output to the file.
00310           if (wipeout_logfile_)
00311             ACE_NEW_RETURN 
00312               (output_file,
00313                ofstream (ACE_TEXT_ALWAYS_CHAR (this->filename_)),
00314                -1);
00315           else
00316             ACE_NEW_RETURN 
00317               (output_file,
00318                ofstream (ACE_TEXT_ALWAYS_CHAR (this->filename_),
00319                          ios::app | ios::out),
00320                -1);
00321           if (output_file->rdstate () != ios::goodbit)
00322             {
00323               delete output_file;
00324               return -1;
00325             }
00326 #endif /* ACE_LACKS_IOSTREAM_TOTALLY */
00327           // Set the <output_file> that'll be used by the rest of the
00328           // code.
00329           this->log_msg_->msg_ostream (output_file);
00330 
00331           // Setup a timeout handler to perform the maximum file size
00332           // check (if required).
00333           if (this->interval_ > 0 && this->max_size_ > 0)
00334             {
00335               if (this->reactor () == 0)
00336                 // Use singleton.
00337                 this->reactor (ACE_Reactor::instance ());  
00338 
00339               this->reactor ()->schedule_timer 
00340                 (this, 0,
00341                  ACE_Time_Value (this->interval_),
00342                  ACE_Time_Value (this->interval_));
00343             }
00344         }
00345       // Now set the flags for Log_Msg
00346       this->log_msg_->set_flags (this->flags_);
00347     }
00348 
00349   return this->log_msg_->open (this->program_name_,
00350                                this->log_msg_->flags (),
00351                                this->logger_key_);
00352 }
00353 
00354 int
00355 ACE_Logging_Strategy::handle_timeout (const ACE_Time_Value &,
00356                                       const void *)
00357 {
00358 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
00359   if ((size_t) ACE_OS::fseek (this->log_msg_->msg_ostream (),
00360                               0,
00361                               SEEK_CUR) > this->max_size_)
00362 #else
00363   if ((size_t) this->log_msg_->msg_ostream ()->tellp () 
00364       > this->max_size_)
00365 #endif /* ACE_LACKS_IOSTREAM_TOTALLY */
00366     {
00367       // Lock out any other logging.
00368       if (this->log_msg_->acquire ())
00369         ACE_ERROR_RETURN ((LM_ERROR,
00370                            ACE_LIB_TEXT ("Cannot acquire lock!\n")),
00371                           -1);
00372 
00373       // Close the current ostream.
00374 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
00375       FILE *output_file = (FILE *) this->log_msg_->msg_ostream ();
00376       ACE_OS::fclose (output_file);
00377       // We'll call msg_ostream() modifier later.
00378 #else
00379       ofstream *output_file = 
00380         (ofstream *) this->log_msg_->msg_ostream ();
00381       output_file->close ();
00382 #endif /* ACE_LACKS_IOSTREAM_TOTALLY */
00383       // Save current logfile to logfile.old analyze if it was set any
00384       // fixed number for the log_files.
00385       if (fixed_number_)
00386         {
00387           if (max_file_number_ < 1) //we only want one file
00388             {
00389               // Just unlink the file.
00390               ACE_OS::unlink (this->filename_);
00391 
00392               // Open a new log file with the same name.
00393 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
00394               output_file = ACE_OS::fopen (this->filename_,
00395                                            ACE_LIB_TEXT ("wt"));
00396 
00397               if (output_file == 0)
00398                 return -1;
00399 
00400               this->log_msg_->msg_ostream (output_file);
00401 #else
00402               output_file->open (ACE_TEXT_ALWAYS_CHAR (this->filename_),
00403                                  ios::out);
00404 #endif /* ACE_LACKS_IOSTREAM_TOTALLY */
00405 
00406               // Release the lock previously acquired.
00407               this->log_msg_->release ();
00408               return 0;
00409             }
00410         }
00411       count_++;
00412 
00413       // Set the number of digits of the log_files labels.
00414       int digits = 1, res = count_;
00415       while((res = (res / 10))>0)
00416         digits++;
00417 
00418       if (ACE_OS::strlen (this->filename_) + digits <= MAXPATHLEN)
00419         {
00420           ACE_TCHAR backup[MAXPATHLEN+1];
00421 
00422           // analyse if it was chosen the mode which will order the
00423           // log_files
00424           if (order_files_)
00425             {
00426               ACE_TCHAR to_backup[MAXPATHLEN+1];
00427 
00428               // reorder the logs starting at the oldest (the biggest
00429               // number) watch if we reached max_file_number_.
00430               int max_num;
00431               if (fixed_number_ && count_ > max_file_number_)
00432                 // count_ will always be bigger than max_file_number_,
00433                 // so do nothing so to always reorder files from
00434                 // max_file_number_.
00435                 max_num = max_file_number_;
00436               else
00437                 max_num = count_;
00438 
00439               for (int i = max_num ; i > 1 ;i--)
00440                 {
00441                   ACE_OS::sprintf (backup,
00442                                    ACE_LIB_TEXT ("%s.%d"),
00443                                    this->filename_,
00444                                    i);
00445                   ACE_OS::sprintf (to_backup,
00446                                    ACE_LIB_TEXT ("%s.%d"),
00447                                    this->filename_,
00448                                    i - 1);
00449 
00450                   // Remove any existing old file; ignore error as
00451                   // file may not exist.
00452                   ACE_OS::unlink (backup);
00453 
00454                   // Rename the current log file to the name of the
00455                   // backup log file.
00456                   ACE_OS::rename (to_backup, backup);
00457                 }
00458               ACE_OS::sprintf (backup,
00459                                ACE_LIB_TEXT ("%s.1"),
00460                                this->filename_);
00461             }
00462           else
00463             {
00464               if (fixed_number_ && count_>max_file_number_) 
00465                 count_ = 1; // start over from 1
00466 
00467               ACE_OS::sprintf (backup,
00468                                ACE_LIB_TEXT ("%s.%d"),
00469                                this->filename_,
00470                                count_);
00471             }
00472 
00473           // Remove any existing old file; ignore error as file may
00474           // not exist.
00475           ACE_OS::unlink (backup);
00476 
00477           // Rename the current log file to the name of the backup log
00478           // file.
00479           ACE_OS::rename (this->filename_, backup);
00480         }
00481       else
00482         ACE_ERROR ((LM_ERROR,
00483                     ACE_LIB_TEXT ("Backup file name too long; ")
00484                     ACE_LIB_TEXT ("backup logfile not saved.\n")));
00485 
00486       // Open a new log file by the same name
00487 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
00488       output_file = ACE_OS::fopen (this->filename_, ACE_LIB_TEXT ("wt"));
00489 
00490       if (output_file == 0)
00491         return -1;
00492 
00493       this->log_msg_->msg_ostream (output_file);
00494 #else
00495       output_file->open (ACE_TEXT_ALWAYS_CHAR (this->filename_),
00496                          ios::out);
00497 #endif /* ACE_LACKS_IOSTREAM_TOTALLY */
00498 
00499       // Release the lock previously acquired.
00500       this->log_msg_->release ();
00501     }
00502 
00503   return 0;
00504 }
00505 
00506 void 
00507 ACE_Logging_Strategy::log_msg (ACE_Log_Msg *log_msg)
00508 {
00509   this->log_msg_  = log_msg;
00510 }
00511 
00512 // The following is a "Factory" used by the ACE_Service_Config and
00513 // svc.conf file to dynamically initialize the state of the
00514 // Logging_Strategy.
00515 
00516 ACE_FACTORY_DEFINE (ACE, ACE_Logging_Strategy)
00517 

Generated on Mon Jun 16 11:20:01 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002