@@ -77,17 +77,21 @@ const std::string kFolderSuffixTmp = ".tmp";
77
77
78
78
namespace {
79
79
80
- bool get_expiration_seconds_by_last_write_time (const std::string &path,
81
- uint64_t delay_seconds,
82
- uint64_t &expiration_seconds)
80
+ // TODO(wangdan): we could study later whether ctime (i.e. `st_ctime` within `struct stat`,
81
+ // the time of last status change) could be used instead of mtime (i.e. `st_ctime` within
82
+ // `struct stat`, the last write time), since ctime of the new directory would be updated
83
+ // to the current time once rename() is called, while mtime would not be updated.
84
+ bool get_expiration_timestamp_by_last_write_time (const std::string &path,
85
+ uint64_t delay_seconds,
86
+ uint64_t &expiration_timestamp_s)
83
87
{
84
- time_t last_write_seconds ;
85
- if (!dsn::utils::filesystem::last_write_time (path, last_write_seconds )) {
88
+ time_t last_write_time_s ;
89
+ if (!dsn::utils::filesystem::last_write_time (path, last_write_time_s )) {
86
90
LOG_WARNING (" gc_disk: failed to get last write time of {}" , path);
87
91
return false ;
88
92
}
89
93
90
- expiration_seconds = static_cast <uint64_t >(last_write_seconds ) + delay_seconds;
94
+ expiration_timestamp_s = static_cast <uint64_t >(last_write_time_s ) + delay_seconds;
91
95
return true ;
92
96
}
93
97
@@ -97,12 +101,24 @@ bool get_expiration_seconds_by_last_write_time(const std::string &path,
97
101
#define MIN_TIMESTAMP_US 1262275200000000
98
102
#define MIN_TIMESTAMP_US_LENGTH (sizeof (STRINGIFY(MIN_TIMESTAMP_US)) - 1 )
99
103
104
+ // Parse timestamp from the directory name.
105
+ //
106
+ // There are only 2 kinds of directory names that could include timestamp: one is the faulty
107
+ // replicas whose name has suffix ".err"; another is the dropped replicas whose name has
108
+ // suffix ".gar". The examples for both kinds of directory names:
109
+ // 1.1.pegasus.1698843209235962.err
110
+ // 1.2.pegasus.1698843214240709.gar
111
+ //
112
+ // Specify the size of suffix by `suffix_size`. For both kinds of names (.err and .gar),
113
+ // `suffix_size` is 4.
114
+ //
115
+ // The timestamp is the number the number just before the suffix, between the 2 dots. For
116
+ // example, in 1.1.pegasus.1698843209235962.err, 1698843209235962 is the timestamp, in
117
+ // microseconds, generated by dsn_now_us().
118
+ //
119
+ // `timestamp_us` is parsed result while returning true; otherwise, it would never be assigned.
100
120
bool parse_timestamp_us (const std::string &name, size_t suffix_size, uint64_t ×tamp_us)
101
121
{
102
- // Examples of the directory names of faulty or dropped replicas could be:
103
- // 1.1.pegasus.1698843209235962.err
104
- // 2.1.pegasus.1698843214240709.gar
105
-
106
122
CHECK_GE (name.size (), suffix_size);
107
123
108
124
if (suffix_size == name.size ()) {
@@ -137,11 +153,11 @@ bool parse_timestamp_us(const std::string &name, size_t suffix_size, uint64_t &t
137
153
return ok ? timestamp_us > MIN_TIMESTAMP_US : false ;
138
154
}
139
155
140
- bool get_expiration_seconds_by_timestamp (const std::string &name,
141
- const std::string &path,
142
- size_t suffix_size,
143
- uint64_t delay_seconds,
144
- uint64_t &expiration_seconds )
156
+ bool get_expiration_timestamp (const std::string &name,
157
+ const std::string &path,
158
+ size_t suffix_size,
159
+ uint64_t delay_seconds,
160
+ uint64_t &expiration_timestamp_s )
145
161
{
146
162
uint64_t timestamp_us = 0 ;
147
163
if (!parse_timestamp_us (name, suffix_size, timestamp_us)) {
@@ -151,10 +167,11 @@ bool get_expiration_seconds_by_timestamp(const std::string &name,
151
167
" the last write time for {}" ,
152
168
name,
153
169
path);
154
- return get_expiration_seconds_by_last_write_time (path, delay_seconds, expiration_seconds);
170
+ return get_expiration_timestamp_by_last_write_time (
171
+ path, delay_seconds, expiration_timestamp_s);
155
172
}
156
173
157
- expiration_seconds = timestamp_us / 1000000 + delay_seconds;
174
+ expiration_timestamp_s = timestamp_us / 1000000 + delay_seconds;
158
175
return true ;
159
176
}
160
177
@@ -179,50 +196,50 @@ error_s disk_remove_useless_dirs(const std::vector<std::shared_ptr<dir_node>> &d
179
196
}
180
197
181
198
for (const auto &path : sub_list) {
182
- uint64_t expiration_seconds = 0 ;
199
+ uint64_t expiration_timestamp_s = 0 ;
183
200
184
201
// Note: don't delete ".bak" directory since it could be did by administrator.
185
202
const auto name = dsn::utils::filesystem::get_file_name (path);
186
203
if (boost::algorithm::ends_with (name, kFolderSuffixErr )) {
187
204
report.error_replica_count ++;
188
- if (!get_expiration_seconds_by_timestamp (name,
189
- path,
190
- kFolderSuffixErr .size (),
191
- FLAGS_gc_disk_error_replica_interval_seconds,
192
- expiration_seconds )) {
205
+ if (!get_expiration_timestamp (name,
206
+ path,
207
+ kFolderSuffixErr .size (),
208
+ FLAGS_gc_disk_error_replica_interval_seconds,
209
+ expiration_timestamp_s )) {
193
210
continue ;
194
211
}
195
212
} else if (boost::algorithm::ends_with (name, kFolderSuffixGar )) {
196
213
report.garbage_replica_count ++;
197
- if (!get_expiration_seconds_by_timestamp (name,
198
- path,
199
- kFolderSuffixGar .size (),
200
- FLAGS_gc_disk_garbage_replica_interval_seconds,
201
- expiration_seconds )) {
214
+ if (!get_expiration_timestamp (name,
215
+ path,
216
+ kFolderSuffixGar .size (),
217
+ FLAGS_gc_disk_garbage_replica_interval_seconds,
218
+ expiration_timestamp_s )) {
202
219
continue ;
203
220
}
204
221
} else if (boost::algorithm::ends_with (name, kFolderSuffixTmp )) {
205
222
report.disk_migrate_tmp_count ++;
206
- if (!get_expiration_seconds_by_last_write_time (
223
+ if (!get_expiration_timestamp_by_last_write_time (
207
224
path,
208
225
FLAGS_gc_disk_migration_tmp_replica_interval_seconds,
209
- expiration_seconds )) {
226
+ expiration_timestamp_s )) {
210
227
continue ;
211
228
}
212
229
} else if (boost::algorithm::ends_with (name, kFolderSuffixOri )) {
213
230
report.disk_migrate_origin_count ++;
214
- if (!get_expiration_seconds_by_last_write_time (
231
+ if (!get_expiration_timestamp_by_last_write_time (
215
232
path,
216
233
FLAGS_gc_disk_migration_origin_replica_interval_seconds,
217
- expiration_seconds )) {
234
+ expiration_timestamp_s )) {
218
235
continue ;
219
236
}
220
237
} else {
221
238
continue ;
222
239
}
223
240
224
241
const auto current_time_ms = dsn_now_ms ();
225
- if (expiration_seconds <= current_time_ms / 1000 ) {
242
+ if (expiration_timestamp_s <= current_time_ms / 1000 ) {
226
243
if (dsn::utils::filesystem::remove_path (path)) {
227
244
LOG_WARNING (" gc_disk: replica_dir_op succeed to delete directory '{}'"
228
245
" , time_used_ms = {}" ,
@@ -237,7 +254,7 @@ error_s disk_remove_useless_dirs(const std::vector<std::shared_ptr<dir_node>> &d
237
254
} else {
238
255
LOG_INFO (" gc_disk: reserve directory '{}', wait_seconds = {}" ,
239
256
path,
240
- expiration_seconds - current_time_ms / 1000 );
257
+ expiration_timestamp_s - current_time_ms / 1000 );
241
258
}
242
259
}
243
260
return error_s::ok ();
0 commit comments