impl( const config& c) : cfg( c ) { if( cfg.rotate ) { FC_ASSERT( cfg.rotation_interval >= seconds( 1 ) ); FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval ); _rotation_task = async( [this]() { rotate_files( true ); }, "rotate_files(1)" ); } }
void rotate_files( bool initializing = false ) { FC_ASSERT( cfg.rotate ); fc::time_point now = time_point::now(); fc::time_point_sec start_time = get_file_start_time( now, cfg.rotation_interval ); string timestamp_string = start_time.to_non_delimited_iso_string(); fc::path link_filename = cfg.filename; fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string); { fc::scoped_lock<boost::mutex> lock( slock ); if( !initializing ) { if( start_time <= _current_file_start_time ) { _rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(2)" ); return; } out.flush(); out.close(); } remove_all(link_filename); // on windows, you can't delete the link while the underlying file is opened for writing if( fc::exists( log_filename ) ) out.open( log_filename, std::ios_base::out | std::ios_base::app ); else out.open( log_filename, std::ios_base::out | std::ios_base::app); create_hard_link(log_filename, link_filename); } /* Delete old log files */ fc::time_point limit_time = now - cfg.rotation_limit; string link_filename_string = link_filename.filename().string(); directory_iterator itr(link_filename.parent_path()); for( ; itr != directory_iterator(); itr++ ) { try { string current_filename = itr->filename().string(); if (current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 || current_filename.size() <= link_filename_string.size() + 1) continue; string current_timestamp_str = current_filename.substr(link_filename_string.size() + 1, timestamp_string.size()); fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str ); if( current_timestamp < start_time ) { if( current_timestamp < limit_time || file_size( current_filename ) <= 0 ) { remove_all( *itr ); continue; } } } catch (const fc::canceled_exception&) { throw; } catch( ... ) { } } _current_file_start_time = start_time; _rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(3)" ); }