ACE的日志策略中没有按天分割的方法(有按文件大小的方法),我自己用reactor+实时器实现了一个:
在每天的零点, 定时器到期:
以下是handle_timeout方法:
int CXXXXTimer::handle_timeout(const ACE_Time_Value ¤t_time,
const void *act /* = 0 */)
{
int nRet = 0;
init_log_config();
return nRet;
}
int init_log_config()
{
if (ACE_LOG_MSG->acquire())
return -1;
ACE_LOG_MSG->clr_flags (ACE_Log_Msg::OSTREAM);
// 先保存先前的输出
ACE_OSTREAM_TYPE *old_output = ACE_LOG_MSG->msg_ostream();
// 日志文件名
std::string strLogFilePath;
CUtility::GetAppPath(strLogFilePath);
std::string strDay = CUtility::get_current_day(); // CUtility::get_current_day()返回类似于这样的字符串:2010-03-29
strLogFilePath += strDay;
strLogFilePath += ".log";
ACE_OSTREAM_TYPE *output = new std::ofstream (strLogFilePath.c_str(),std::ios_base::out | std::ios_base::app);
ACE_LOG_MSG->msg_ostream (output, 1);
ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
if (old_output)
{
#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
FILE *output_file = (FILE *)old_output;
ACE_OS::fclose (output_file);
#else
ofstream *output_file = (ofstream *)old_output;
output_file->close ();
#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
delete old_output;
old_output = 0;
}
ACE_LOG_MSG->release();
return 0;
}
现在的问题是: 第当定时器当期: handle_timeout方法执行后, 能生成一个正确的文件名,如今天的日志文件名为2010-02-29.log,到了2010-03-30的零点就会生成名称为2010-03-30.log的日志文件. 此后的一调用ACE_DEBUG就会crash掉.
堆栈如下:
(1) ACEd.dll!std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::_Sentry_base(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) 行81 + 0x28 字节 C++
(2) ACEd.dll!std::basic_ostream<char,std::char_traits<char> >::sentry::sentry(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) 行99 + 0x3a 字节 C++
(3) ACEd.dll!std::operator<<<std::char_traits<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const char * _Val=0x09f7ac38) 行751 + 0xc 字节 C++
(4) ACEd.dll!ACE_Log_Record::print(const char * host_name=0x00000000, unsigned long verbose_flag=5, std::basic_ostream<char,std::char_traits<char> > & s={...}) 行399 + 0xd 字节 C++
(5) ACEd.dll!ACE_Log_Msg::log(ACE_Log_Record & log_record={...}, int suppress_stderr=0) 行2220 C++
(6) ACEd.dll!ACE_Log_Msg::log(const char * format_str=0x004fe487, ACE_Log_Priority log_priority=LM_DEBUG, char * argp=0x0667d934) 行2069 + 0x11 字节 C++
(7) ACEd.dll!ACE_Log_Msg::log(ACE_Log_Priority log_priority=LM_DEBUG, const char * format_str=0x004fe440, ...) 行953 + 0x14 字节 C++
(8) XXX.exe!XXX_Progress(const char * package=0x0667dc88, std::basic_string<char,std::char_traits<char>,std::allocator<char> > & result="", HLL_COMM_TYPE::InterfaceType ift=IFT_CLIENT) 行37 + 0xea 字节 C++
.................
上面的(1)对应的源代码为:ostream中的(标记为红色)
__CLR_OR_THIS_CALL _Sentry_base(_Myt& _Ostr)
: _Myostr(_Ostr)
{ // lock the stream buffer, if there
if (_Myostr.rdbuf() != 0)
_Myostr.rdbuf()->_Lock(); // 这里是ostream中的81行
}
上面的(2)对应的源代码为:ostream中的(标记为红色)
explicit __CLR_OR_THIS_CALL sentry(_Myt& _Ostr)
: _Sentry_base(_Ostr) // 这里是ostream中的98行
{ // construct locking and testing stream
if (_Ostr.good() && _Ostr.tie() != 0)
_Ostr.tie()->flush();
_Ok = _Ostr.good(); // store test only after flushing tie
}
我想可能前后两个输出流死锁(具体什么原因我也搞不清). 不知道有没有遇过个这个问题. 另外ACE_DEBUG在多个线程中调用.
此外我也注意到另一个帖子:
http://www.acejoy.com/bbs/viewthread.php?tid=944&extra=page%3D1
以及:
http://www.cppblog.com/elva/archive/2008/07/31/57534.html
如果实现无法解决,只好换用其它方法来实现输出到日志了.
谢谢大家!!! |