@@ -21,18 +21,13 @@ namespace fc {
21
21
boost::mutex slock;
22
22
23
23
private:
24
- future<void > _rotation_task;
25
- time_point_sec _current_file_start_time;
26
-
27
- time_point_sec get_file_start_time ( const time_point_sec& timestamp, const microseconds& interval )
28
- {
29
- int64_t interval_seconds = interval.to_seconds ();
30
- int64_t file_number = timestamp.sec_since_epoch () / interval_seconds;
31
- return time_point_sec ( (uint32_t )(file_number * interval_seconds) );
32
- }
24
+ future<void > _deletion_task;
25
+ boost::atomic<int64_t > _current_file_number;
26
+ const int64_t _interval_seconds;
27
+ time_point _next_file_time;
33
28
34
29
public:
35
- impl ( const config& c) : cfg( c )
30
+ impl ( const config& c) : cfg( c ), _interval_seconds( cfg.rotation_interval.to_seconds() )
36
31
{
37
32
try
38
33
{
@@ -44,6 +39,7 @@ namespace fc {
44
39
FC_ASSERT ( cfg.rotation_limit >= cfg.rotation_interval );
45
40
46
41
rotate_files ( true );
42
+ delete_files ();
47
43
} else {
48
44
out.open ( cfg.filename , std::ios_base::out | std::ios_base::app);
49
45
}
@@ -58,7 +54,7 @@ namespace fc {
58
54
{
59
55
try
60
56
{
61
- _rotation_task .cancel_and_wait (" file_appender is destructing" );
57
+ _deletion_task .cancel_and_wait (" file_appender is destructing" );
62
58
}
63
59
catch ( ... )
64
60
{
@@ -67,9 +63,22 @@ namespace fc {
67
63
68
64
void rotate_files ( bool initializing = false )
69
65
{
70
- FC_ASSERT ( cfg.rotate );
66
+ if ( !cfg.rotate ) return ;
67
+
71
68
fc::time_point now = time_point::now ();
72
- fc::time_point_sec start_time = get_file_start_time ( now, cfg.rotation_interval );
69
+ if ( now < _next_file_time ) return ;
70
+
71
+ int64_t new_file_number = now.sec_since_epoch () / _interval_seconds;
72
+ if ( initializing )
73
+ _current_file_number.store ( new_file_number );
74
+ else
75
+ {
76
+ int64_t prev_file_number = _current_file_number.load ();
77
+ if ( prev_file_number >= new_file_number ) return ;
78
+ if ( !_current_file_number.compare_exchange_weak ( prev_file_number, new_file_number ) ) return ;
79
+ }
80
+ fc::time_point_sec start_time = time_point_sec ( (uint32_t )(new_file_number * _interval_seconds) );
81
+ _next_file_time = start_time + _interval_seconds;
73
82
string timestamp_string = start_time.to_non_delimited_iso_string ();
74
83
fc::path link_filename = cfg.filename ;
75
84
fc::path log_filename = link_filename.parent_path () / (link_filename.filename ().string () + " ." + timestamp_string);
@@ -79,44 +88,41 @@ namespace fc {
79
88
80
89
if ( !initializing )
81
90
{
82
- if ( start_time <= _current_file_start_time )
83
- {
84
- _rotation_task = schedule ( [this ]() { rotate_files (); },
85
- _current_file_start_time + cfg.rotation_interval .to_seconds (),
86
- " rotate_files(2)" );
87
- return ;
88
- }
89
-
90
91
out.flush ();
91
92
out.close ();
92
93
}
93
94
remove_all (link_filename); // on windows, you can't delete the link while the underlying file is opened for writing
94
95
out.open ( log_filename, std::ios_base::out | std::ios_base::app );
95
96
create_hard_link (log_filename, link_filename);
96
97
}
98
+ }
97
99
100
+ void delete_files ()
101
+ {
98
102
/* Delete old log files */
99
- fc::time_point limit_time = now - cfg.rotation_limit ;
103
+ auto current_file = _current_file_number.load ();
104
+ fc::time_point_sec start_time = time_point_sec ( (uint32_t )(current_file * _interval_seconds) );
105
+ fc::time_point limit_time = time_point::now () - cfg.rotation_limit ;
106
+ fc::path link_filename = cfg.filename ;
100
107
string link_filename_string = link_filename.filename ().string ();
101
108
directory_iterator itr (link_filename.parent_path ());
109
+ string timestamp_string = start_time.to_non_delimited_iso_string ();
102
110
for ( ; itr != directory_iterator (); itr++ )
103
111
{
104
112
try
105
113
{
106
114
string current_filename = itr->filename ().string ();
107
- if ( current_filename.compare (0 , link_filename_string.size (), link_filename_string) != 0 ||
108
- current_filename.size () <= link_filename_string.size () + 1 )
109
- continue ;
115
+ if ( current_filename.compare (0 , link_filename_string.size (), link_filename_string) != 0
116
+ || current_filename.size () <= link_filename_string.size () + 1 )
117
+ continue ;
110
118
string current_timestamp_str = current_filename.substr (link_filename_string.size () + 1 ,
111
119
timestamp_string.size ());
112
120
fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string ( current_timestamp_str );
113
- if ( current_timestamp < start_time )
121
+ if ( current_timestamp < start_time
122
+ && ( current_timestamp < limit_time || file_size ( current_filename ) <= 0 ) )
114
123
{
115
- if ( current_timestamp < limit_time || file_size ( current_filename ) <= 0 )
116
- {
117
- remove_all ( *itr );
118
- continue ;
119
- }
124
+ remove_all ( *itr );
125
+ continue ;
120
126
}
121
127
}
122
128
catch (const fc::canceled_exception&)
@@ -127,11 +133,8 @@ namespace fc {
127
133
{
128
134
}
129
135
}
130
-
131
- _current_file_start_time = start_time;
132
- _rotation_task = schedule ( [this ]() { rotate_files (); },
133
- _current_file_start_time + cfg.rotation_interval .to_seconds (),
134
- " rotate_files(3)" );
136
+ _deletion_task = schedule ( [this ]() { delete_files (); }, start_time + _interval_seconds,
137
+ " delete_files(3)" );
135
138
}
136
139
};
137
140
@@ -151,8 +154,9 @@ namespace fc {
151
154
// MS THREAD METHOD MESSAGE \t\t\t File:Line
152
155
void file_appender::log ( const log_message& m )
153
156
{
157
+ my->rotate_files ();
158
+
154
159
std::stringstream line;
155
- // line << (m.get_context().get_timestamp().time_since_epoch().count() % (1000ll*1000ll*60ll*60))/1000 <<"ms ";
156
160
line << string (m.get_context ().get_timestamp ()) << " " ;
157
161
line << std::setw ( 21 ) << (m.get_context ().get_thread_name ().substr (0 ,9 ) + string (" :" ) + m.get_context ().get_task_name ()).c_str () << " " ;
158
162
0 commit comments