/src/rocksdb/file/filename.cc
Line | Count | Source |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // |
6 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
7 | | // Use of this source code is governed by a BSD-style license that can be |
8 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
9 | | #include "file/filename.h" |
10 | | |
11 | | #include <cctype> |
12 | | #include <cinttypes> |
13 | | #include <cstdio> |
14 | | #include <vector> |
15 | | |
16 | | #include "file/file_util.h" |
17 | | #include "file/writable_file_writer.h" |
18 | | #include "rocksdb/env.h" |
19 | | #include "rocksdb/file_system.h" |
20 | | #include "test_util/sync_point.h" |
21 | | #include "util/stop_watch.h" |
22 | | #include "util/string_util.h" |
23 | | |
24 | | namespace ROCKSDB_NAMESPACE { |
25 | | |
26 | | const std::string kCurrentFileName = "CURRENT"; |
27 | | const std::string kOptionsFileNamePrefix = "OPTIONS-"; |
28 | | const std::string kCompactionProgressFileNamePrefix = "COMPACTION_PROGRESS-"; |
29 | | const std::string kTempFileNameSuffix = "dbtmp"; |
30 | | |
31 | | static const std::string kRocksDbTFileExt = "sst"; |
32 | | static const std::string kLevelDbTFileExt = "ldb"; |
33 | | static const std::string kRocksDBBlobFileExt = "blob"; |
34 | | static const std::string kArchivalDirName = "archive"; |
35 | | |
36 | | // Given a path, flatten the path name by replacing all chars not in |
37 | | // {[0-9,a-z,A-Z,-,_,.]} with _. And append '_LOG\0' at the end. |
38 | | // Return the number of chars stored in dest not including the trailing '\0'. |
39 | 0 | static size_t GetInfoLogPrefix(const std::string& path, char* dest, int len) { |
40 | 0 | const char suffix[] = "_LOG"; |
41 | |
|
42 | 0 | size_t write_idx = 0; |
43 | 0 | size_t i = 0; |
44 | 0 | size_t src_len = path.size(); |
45 | |
|
46 | 0 | while (i < src_len && write_idx < len - sizeof(suffix)) { |
47 | 0 | if ((path[i] >= 'a' && path[i] <= 'z') || |
48 | 0 | (path[i] >= '0' && path[i] <= '9') || |
49 | 0 | (path[i] >= 'A' && path[i] <= 'Z') || path[i] == '-' || |
50 | 0 | path[i] == '.' || path[i] == '_') { |
51 | 0 | dest[write_idx++] = path[i]; |
52 | 0 | } else { |
53 | 0 | if (i > 0) { |
54 | 0 | dest[write_idx++] = '_'; |
55 | 0 | } |
56 | 0 | } |
57 | 0 | i++; |
58 | 0 | } |
59 | 0 | assert(sizeof(suffix) <= len - write_idx); |
60 | | // "\0" is automatically added by snprintf |
61 | 0 | snprintf(dest + write_idx, len - write_idx, suffix); |
62 | 0 | write_idx += sizeof(suffix) - 1; |
63 | 0 | return write_idx; |
64 | 0 | } |
65 | | |
66 | 541k | static std::string MakeFileName(uint64_t number, const char* suffix) { |
67 | 541k | char buf[100]; |
68 | 541k | snprintf(buf, sizeof(buf), "%06llu.%s", |
69 | 541k | static_cast<unsigned long long>(number), suffix); |
70 | 541k | return buf; |
71 | 541k | } |
72 | | |
73 | | static std::string MakeFileName(const std::string& name, uint64_t number, |
74 | 531k | const char* suffix) { |
75 | 531k | return name + "/" + MakeFileName(number, suffix); |
76 | 531k | } |
77 | | |
78 | 178k | std::string LogFileName(const std::string& name, uint64_t number) { |
79 | 178k | assert(number > 0); |
80 | 178k | return MakeFileName(name, number, "log"); |
81 | 178k | } |
82 | | |
83 | 2.09k | std::string LogFileName(uint64_t number) { |
84 | 2.09k | assert(number > 0); |
85 | 2.09k | return MakeFileName(number, "log"); |
86 | 2.09k | } |
87 | | |
88 | 0 | std::string BlobFileName(uint64_t number) { |
89 | 0 | assert(number > 0); |
90 | 0 | return MakeFileName(number, kRocksDBBlobFileExt.c_str()); |
91 | 0 | } |
92 | | |
93 | 0 | std::string BlobFileName(const std::string& blobdirname, uint64_t number) { |
94 | 0 | assert(number > 0); |
95 | 0 | return MakeFileName(blobdirname, number, kRocksDBBlobFileExt.c_str()); |
96 | 0 | } |
97 | | |
98 | | std::string BlobFileName(const std::string& dbname, const std::string& blob_dir, |
99 | 0 | uint64_t number) { |
100 | 0 | assert(number > 0); |
101 | 0 | return MakeFileName(dbname + "/" + blob_dir, number, |
102 | 0 | kRocksDBBlobFileExt.c_str()); |
103 | 0 | } |
104 | | |
105 | 7.64k | std::string ArchivalDirectory(const std::string& dir) { |
106 | 7.64k | return dir + "/" + kArchivalDirName; |
107 | 7.64k | } |
108 | 0 | std::string ArchivedLogFileName(const std::string& name, uint64_t number) { |
109 | 0 | assert(number > 0); |
110 | 0 | return MakeFileName(name + "/" + kArchivalDirName, number, "log"); |
111 | 0 | } |
112 | | |
113 | 288k | std::string MakeTableFileName(const std::string& path, uint64_t number) { |
114 | 288k | return MakeFileName(path, number, kRocksDbTFileExt.c_str()); |
115 | 288k | } |
116 | | |
117 | 7.63k | std::string MakeTableFileName(uint64_t number) { |
118 | 7.63k | return MakeFileName(number, kRocksDbTFileExt.c_str()); |
119 | 7.63k | } |
120 | | |
121 | 0 | std::string Rocks2LevelTableFileName(const std::string& fullname) { |
122 | 0 | assert(fullname.size() > kRocksDbTFileExt.size() + 1); |
123 | 0 | if (fullname.size() <= kRocksDbTFileExt.size() + 1) { |
124 | 0 | return ""; |
125 | 0 | } |
126 | 0 | return fullname.substr(0, fullname.size() - kRocksDbTFileExt.size()) + |
127 | 0 | kLevelDbTFileExt; |
128 | 0 | } |
129 | | |
130 | 0 | uint64_t TableFileNameToNumber(const std::string& name) { |
131 | 0 | uint64_t number = 0; |
132 | 0 | uint64_t base = 1; |
133 | 0 | int pos = static_cast<int>(name.find_last_of('.')); |
134 | 0 | while (--pos >= 0 && name[pos] >= '0' && name[pos] <= '9') { |
135 | 0 | number += (name[pos] - '0') * base; |
136 | 0 | base *= 10; |
137 | 0 | } |
138 | 0 | return number; |
139 | 0 | } |
140 | | |
141 | | std::string TableFileName(const std::vector<DbPath>& db_paths, uint64_t number, |
142 | 163k | uint32_t path_id) { |
143 | 163k | assert(number > 0); |
144 | 163k | std::string path; |
145 | 163k | if (path_id >= db_paths.size()) { |
146 | 0 | path = db_paths.back().path; |
147 | 163k | } else { |
148 | 163k | path = db_paths[path_id].path; |
149 | 163k | } |
150 | 163k | return MakeTableFileName(path, number); |
151 | 163k | } |
152 | | |
153 | | void FormatFileNumber(uint64_t number, uint32_t path_id, char* out_buf, |
154 | 0 | size_t out_buf_size) { |
155 | 0 | if (path_id == 0) { |
156 | 0 | snprintf(out_buf, out_buf_size, "%" PRIu64, number); |
157 | 0 | } else { |
158 | 0 | snprintf(out_buf, out_buf_size, |
159 | 0 | "%" PRIu64 |
160 | 0 | "(path " |
161 | 0 | "%" PRIu32 ")", |
162 | 0 | number, path_id); |
163 | 0 | } |
164 | 0 | } |
165 | | |
166 | 214k | std::string DescriptorFileName(uint64_t number) { |
167 | 214k | assert(number > 0); |
168 | 214k | char buf[100]; |
169 | 214k | snprintf(buf, sizeof(buf), "MANIFEST-%06llu", |
170 | 214k | static_cast<unsigned long long>(number)); |
171 | 214k | return buf; |
172 | 214k | } |
173 | | |
174 | 214k | std::string DescriptorFileName(const std::string& dbname, uint64_t number) { |
175 | 214k | return dbname + "/" + DescriptorFileName(number); |
176 | 214k | } |
177 | | |
178 | 214k | std::string CurrentFileName(const std::string& dbname) { |
179 | 214k | return dbname + "/" + kCurrentFileName; |
180 | 214k | } |
181 | | |
182 | 57.3k | std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; } |
183 | | |
184 | 65.0k | std::string TempFileName(const std::string& dbname, uint64_t number) { |
185 | 65.0k | return MakeFileName(dbname, number, kTempFileNameSuffix.c_str()); |
186 | 65.0k | } |
187 | | |
188 | | InfoLogPrefix::InfoLogPrefix(bool has_log_dir, |
189 | 214k | const std::string& db_absolute_path) { |
190 | 214k | if (!has_log_dir) { |
191 | 214k | const char kInfoLogPrefix[] = "LOG"; |
192 | | // "\0" is automatically added to the end |
193 | 214k | snprintf(buf, sizeof(buf), kInfoLogPrefix); |
194 | 214k | prefix = Slice(buf, sizeof(kInfoLogPrefix) - 1); |
195 | 214k | } else { |
196 | 0 | size_t len = |
197 | 0 | GetInfoLogPrefix(NormalizePath(db_absolute_path), buf, sizeof(buf)); |
198 | 0 | prefix = Slice(buf, len); |
199 | 0 | } |
200 | 214k | } |
201 | | |
202 | | std::string InfoLogFileName(const std::string& dbname, |
203 | | const std::string& db_path, |
204 | 57.3k | const std::string& log_dir) { |
205 | 57.3k | if (log_dir.empty()) { |
206 | 57.3k | return dbname + "/LOG"; |
207 | 57.3k | } |
208 | | |
209 | 0 | InfoLogPrefix info_log_prefix(true, db_path); |
210 | 0 | return log_dir + "/" + info_log_prefix.buf; |
211 | 57.3k | } |
212 | | |
213 | | // Return the name of the old info log file for "dbname". |
214 | | std::string OldInfoLogFileName(const std::string& dbname, uint64_t ts, |
215 | | const std::string& db_path, |
216 | 49.7k | const std::string& log_dir) { |
217 | 49.7k | char buf[50]; |
218 | 49.7k | snprintf(buf, sizeof(buf), "%llu", static_cast<unsigned long long>(ts)); |
219 | | |
220 | 49.7k | if (log_dir.empty()) { |
221 | 49.7k | return dbname + "/LOG.old." + buf; |
222 | 49.7k | } |
223 | | |
224 | 0 | InfoLogPrefix info_log_prefix(true, db_path); |
225 | 0 | return log_dir + "/" + info_log_prefix.buf + ".old." + buf; |
226 | 49.7k | } |
227 | | |
228 | 86.7k | std::string OptionsFileName(uint64_t file_num) { |
229 | 86.7k | char buffer[256]; |
230 | 86.7k | snprintf(buffer, sizeof(buffer), "%s%06" PRIu64, |
231 | 86.7k | kOptionsFileNamePrefix.c_str(), file_num); |
232 | 86.7k | return buffer; |
233 | 86.7k | } |
234 | 86.7k | std::string OptionsFileName(const std::string& dbname, uint64_t file_num) { |
235 | 86.7k | return dbname + "/" + OptionsFileName(file_num); |
236 | 86.7k | } |
237 | | |
238 | 86.7k | std::string TempOptionsFileName(const std::string& dbname, uint64_t file_num) { |
239 | 86.7k | char buffer[256]; |
240 | 86.7k | snprintf(buffer, sizeof(buffer), "%s%06" PRIu64 ".%s", |
241 | 86.7k | kOptionsFileNamePrefix.c_str(), file_num, |
242 | 86.7k | kTempFileNameSuffix.c_str()); |
243 | 86.7k | return dbname + "/" + buffer; |
244 | 86.7k | } |
245 | | |
246 | | std::string CompactionProgressFileName(const std::string& dbname, |
247 | 0 | uint64_t timestamp) { |
248 | 0 | char buffer[256]; |
249 | 0 | snprintf(buffer, sizeof(buffer), "%s%llu", |
250 | 0 | kCompactionProgressFileNamePrefix.c_str(), |
251 | 0 | static_cast<unsigned long long>(timestamp)); |
252 | 0 | return dbname + "/" + buffer; |
253 | 0 | } |
254 | | |
255 | | std::string TempCompactionProgressFileName(const std::string& dbname, |
256 | 0 | uint64_t timestamp) { |
257 | 0 | char buffer[256]; |
258 | 0 | snprintf(buffer, sizeof(buffer), "%s%llu.%s", |
259 | 0 | kCompactionProgressFileNamePrefix.c_str(), |
260 | 0 | static_cast<unsigned long long>(timestamp), |
261 | 0 | kTempFileNameSuffix.c_str()); |
262 | 0 | return dbname + "/" + buffer; |
263 | 0 | } |
264 | | |
265 | 0 | std::string MetaDatabaseName(const std::string& dbname, uint64_t number) { |
266 | 0 | char buf[100]; |
267 | 0 | snprintf(buf, sizeof(buf), "/METADB-%llu", |
268 | 0 | static_cast<unsigned long long>(number)); |
269 | 0 | return dbname + buf; |
270 | 0 | } |
271 | | |
272 | 91.8k | std::string IdentityFileName(const std::string& dbname) { |
273 | 91.8k | return dbname + "/IDENTITY"; |
274 | 91.8k | } |
275 | | |
276 | | // Owned filenames have the form: |
277 | | // dbname/IDENTITY |
278 | | // dbname/CURRENT |
279 | | // dbname/LOCK |
280 | | // dbname/<info_log_name_prefix> |
281 | | // dbname/<info_log_name_prefix>.old.[0-9]+ |
282 | | // dbname/MANIFEST-[0-9]+ |
283 | | // dbname/[0-9]+.(log|sst|blob) |
284 | | // dbname/METADB-[0-9]+ |
285 | | // dbname/OPTIONS-[0-9]+ |
286 | | // dbname/OPTIONS-[0-9]+.dbtmp |
287 | | // dbname/COMPACTION_PROGRESS-[timestamp] |
288 | | // dbname/COMPACTION_PROGRESS-[timestamp].dbtmp |
289 | | // Disregards / at the beginning |
290 | | bool ParseFileName(const std::string& fname, uint64_t* number, FileType* type, |
291 | 4.94M | WalFileType* log_type) { |
292 | 4.94M | return ParseFileName(fname, number, "", type, log_type); |
293 | 4.94M | } |
294 | | |
295 | | bool ParseFileName(const std::string& fname, uint64_t* number, |
296 | | const Slice& info_log_name_prefix, FileType* type, |
297 | 11.3M | WalFileType* log_type) { |
298 | 11.3M | Slice rest(fname); |
299 | 11.3M | if (fname.length() > 1 && fname[0] == '/') { |
300 | 4.15M | rest.remove_prefix(1); |
301 | 4.15M | } |
302 | 11.3M | if (rest == "IDENTITY") { |
303 | 534k | *number = 0; |
304 | 534k | *type = kIdentityFile; |
305 | 10.7M | } else if (rest == "CURRENT") { |
306 | 534k | *number = 0; |
307 | 534k | *type = kCurrentFile; |
308 | 10.2M | } else if (rest == "LOCK") { |
309 | 534k | *number = 0; |
310 | 534k | *type = kDBLockFile; |
311 | 9.72M | } else if (info_log_name_prefix.size() > 0 && |
312 | 5.46M | rest.starts_with(info_log_name_prefix)) { |
313 | 3.32M | rest.remove_prefix(info_log_name_prefix.size()); |
314 | 3.32M | if (rest == "" || rest == ".old") { |
315 | 306k | *number = 0; |
316 | 306k | *type = kInfoLogFile; |
317 | 3.02M | } else if (rest.starts_with(".old.")) { |
318 | 3.02M | uint64_t ts_suffix; |
319 | | // sizeof also counts the trailing '\0'. |
320 | 3.02M | rest.remove_prefix(sizeof(".old.") - 1); |
321 | 3.02M | if (!ConsumeDecimalNumber(&rest, &ts_suffix)) { |
322 | 0 | return false; |
323 | 0 | } |
324 | 3.02M | *number = ts_suffix; |
325 | 3.02M | *type = kInfoLogFile; |
326 | 3.02M | } |
327 | 6.39M | } else if (rest.starts_with("MANIFEST-")) { |
328 | 783k | rest.remove_prefix(strlen("MANIFEST-")); |
329 | 783k | uint64_t num; |
330 | 783k | if (!ConsumeDecimalNumber(&rest, &num)) { |
331 | 0 | return false; |
332 | 0 | } |
333 | 783k | if (!rest.empty()) { |
334 | 0 | return false; |
335 | 0 | } |
336 | 783k | *type = kDescriptorFile; |
337 | 783k | *number = num; |
338 | 5.61M | } else if (rest.starts_with("METADB-")) { |
339 | 0 | rest.remove_prefix(strlen("METADB-")); |
340 | 0 | uint64_t num; |
341 | 0 | if (!ConsumeDecimalNumber(&rest, &num)) { |
342 | 0 | return false; |
343 | 0 | } |
344 | 0 | if (!rest.empty()) { |
345 | 0 | return false; |
346 | 0 | } |
347 | 0 | *type = kMetaDatabase; |
348 | 0 | *number = num; |
349 | 5.61M | } else if (rest.starts_with(kOptionsFileNamePrefix)) { |
350 | 1.04M | uint64_t ts_suffix; |
351 | 1.04M | bool is_temp_file = false; |
352 | 1.04M | rest.remove_prefix(kOptionsFileNamePrefix.size()); |
353 | 1.04M | const std::string kTempFileNameSuffixWithDot = |
354 | 1.04M | std::string(".") + kTempFileNameSuffix; |
355 | 1.04M | if (rest.ends_with(kTempFileNameSuffixWithDot)) { |
356 | 0 | rest.remove_suffix(kTempFileNameSuffixWithDot.size()); |
357 | 0 | is_temp_file = true; |
358 | 0 | } |
359 | 1.04M | if (!ConsumeDecimalNumber(&rest, &ts_suffix)) { |
360 | 0 | return false; |
361 | 0 | } |
362 | 1.04M | *number = ts_suffix; |
363 | 1.04M | *type = is_temp_file ? kTempFile : kOptionsFile; |
364 | 4.57M | } else if (rest.starts_with(kCompactionProgressFileNamePrefix)) { |
365 | 0 | uint64_t timestamp; |
366 | 0 | bool is_temp_file = false; |
367 | 0 | rest.remove_prefix(kCompactionProgressFileNamePrefix.size()); |
368 | 0 | const std::string kTempFileNameSuffixWithDot = |
369 | 0 | std::string(".") + kTempFileNameSuffix; |
370 | 0 | if (rest.ends_with(kTempFileNameSuffixWithDot)) { |
371 | 0 | rest.remove_suffix(kTempFileNameSuffixWithDot.size()); |
372 | 0 | is_temp_file = true; |
373 | 0 | } |
374 | 0 | if (!ConsumeDecimalNumber(&rest, ×tamp)) { |
375 | 0 | return false; |
376 | 0 | } |
377 | 0 | if (!rest.empty()) { |
378 | 0 | return false; |
379 | 0 | } |
380 | 0 | *number = timestamp; |
381 | 0 | *type = is_temp_file ? kTempFile : kCompactionProgressFile; |
382 | 4.57M | } else { |
383 | | // Avoid strtoull() to keep filename format independent of the |
384 | | // current locale |
385 | 4.57M | bool archive_dir_found = false; |
386 | 4.57M | if (rest.starts_with(kArchivalDirName)) { |
387 | 0 | if (rest.size() <= kArchivalDirName.size()) { |
388 | 0 | return false; |
389 | 0 | } |
390 | 0 | rest.remove_prefix(kArchivalDirName.size() + |
391 | 0 | 1); // Add 1 to remove / also |
392 | 0 | if (log_type) { |
393 | 0 | *log_type = kArchivedLogFile; |
394 | 0 | } |
395 | 0 | archive_dir_found = true; |
396 | 0 | } |
397 | 4.57M | uint64_t num; |
398 | 4.57M | if (!ConsumeDecimalNumber(&rest, &num)) { |
399 | 2.73M | return false; |
400 | 2.73M | } |
401 | 1.84M | if (rest.size() <= 1 || rest[0] != '.') { |
402 | 0 | return false; |
403 | 0 | } |
404 | 1.84M | rest.remove_prefix(1); |
405 | | |
406 | 1.84M | Slice suffix = rest; |
407 | 1.84M | if (suffix == Slice("log")) { |
408 | 691k | *type = kWalFile; |
409 | 691k | if (log_type && !archive_dir_found) { |
410 | 0 | *log_type = kAliveLogFile; |
411 | 0 | } |
412 | 1.15M | } else if (archive_dir_found) { |
413 | 0 | return false; // Archive dir can contain only log files |
414 | 1.15M | } else if (suffix == Slice(kRocksDbTFileExt) || |
415 | 1.15M | suffix == Slice(kLevelDbTFileExt)) { |
416 | 1.15M | *type = kTableFile; |
417 | 1.15M | } else if (suffix == Slice(kRocksDBBlobFileExt)) { |
418 | 0 | *type = kBlobFile; |
419 | 1 | } else if (suffix == Slice(kTempFileNameSuffix)) { |
420 | 0 | *type = kTempFile; |
421 | 1 | } else { |
422 | 1 | return false; |
423 | 1 | } |
424 | 1.84M | *number = num; |
425 | 1.84M | } |
426 | 8.60M | return true; |
427 | 11.3M | } |
428 | | |
429 | | IOStatus SetCurrentFile(const WriteOptions& write_options, FileSystem* fs, |
430 | | const std::string& dbname, uint64_t descriptor_number, |
431 | | Temperature temp, |
432 | 57.3k | FSDirectory* dir_contains_current_file) { |
433 | | // Remove leading "dbname/" and add newline to manifest file name |
434 | 57.3k | std::string manifest = DescriptorFileName(dbname, descriptor_number); |
435 | 57.3k | Slice contents = manifest; |
436 | 57.3k | assert(contents.starts_with(dbname + "/")); |
437 | 57.3k | contents.remove_prefix(dbname.size() + 1); |
438 | 57.3k | std::string tmp = TempFileName(dbname, descriptor_number); |
439 | 57.3k | IOOptions opts; |
440 | 57.3k | IOStatus s = PrepareIOFromWriteOptions(write_options, opts); |
441 | 57.3k | FileOptions file_opts; |
442 | 57.3k | file_opts.temperature = temp; |
443 | 57.3k | if (s.ok()) { |
444 | 57.3k | s = WriteStringToFile(fs, contents.ToString() + "\n", tmp, true, opts, |
445 | 57.3k | file_opts); |
446 | 57.3k | } |
447 | 57.3k | TEST_SYNC_POINT_CALLBACK("SetCurrentFile:BeforeRename", &s); |
448 | 57.3k | if (s.ok()) { |
449 | 57.3k | TEST_KILL_RANDOM_WITH_WEIGHT("SetCurrentFile:0", REDUCE_ODDS2); |
450 | 57.3k | s = fs->RenameFile(tmp, CurrentFileName(dbname), opts, nullptr); |
451 | 57.3k | TEST_KILL_RANDOM_WITH_WEIGHT("SetCurrentFile:1", REDUCE_ODDS2); |
452 | 57.3k | TEST_SYNC_POINT_CALLBACK("SetCurrentFile:AfterRename", &s); |
453 | 57.3k | } |
454 | 57.3k | if (s.ok()) { |
455 | 57.3k | if (dir_contains_current_file != nullptr) { |
456 | 57.3k | s = dir_contains_current_file->FsyncWithDirOptions( |
457 | 57.3k | opts, nullptr, DirFsyncOptions(CurrentFileName(dbname))); |
458 | 57.3k | } |
459 | 57.3k | } else { |
460 | 0 | fs->DeleteFile(tmp, opts, nullptr) |
461 | 0 | .PermitUncheckedError(); // NOTE: PermitUncheckedError is acceptable |
462 | | // here as we are already handling an error |
463 | | // case, and this is just a best-attempt |
464 | | // effort at some cleanup |
465 | 0 | } |
466 | 57.3k | return s; |
467 | 57.3k | } |
468 | | |
469 | | Status SetIdentityFile(const WriteOptions& write_options, Env* env, |
470 | | const std::string& dbname, Temperature temp, |
471 | 7.64k | const std::string& db_id) { |
472 | 7.64k | std::string id; |
473 | 7.64k | if (db_id.empty()) { |
474 | 0 | id = env->GenerateUniqueId(); |
475 | 7.64k | } else { |
476 | 7.64k | id = db_id; |
477 | 7.64k | } |
478 | 7.64k | assert(!id.empty()); |
479 | | // Reserve the filename dbname/000000.dbtmp for the temporary identity file |
480 | 7.64k | std::string tmp = TempFileName(dbname, 0); |
481 | 7.64k | std::string identify_file_name = IdentityFileName(dbname); |
482 | 7.64k | Status s; |
483 | 7.64k | IOOptions opts; |
484 | 7.64k | s = PrepareIOFromWriteOptions(write_options, opts); |
485 | 7.64k | FileOptions file_opts; |
486 | 7.64k | file_opts.temperature = temp; |
487 | 7.64k | if (s.ok()) { |
488 | 7.64k | s = WriteStringToFile(env->GetFileSystem().get(), id, tmp, |
489 | 7.64k | /*should_sync=*/true, opts, file_opts); |
490 | 7.64k | } |
491 | 7.64k | if (s.ok()) { |
492 | 7.64k | s = env->RenameFile(tmp, identify_file_name); |
493 | 7.64k | } |
494 | 7.64k | std::unique_ptr<FSDirectory> dir_obj; |
495 | 7.64k | if (s.ok()) { |
496 | 7.64k | s = env->GetFileSystem()->NewDirectory(dbname, opts, &dir_obj, nullptr); |
497 | 7.64k | } |
498 | 7.64k | if (s.ok()) { |
499 | 7.64k | s = dir_obj->FsyncWithDirOptions(opts, nullptr, |
500 | 7.64k | DirFsyncOptions(identify_file_name)); |
501 | 7.64k | } |
502 | | |
503 | | // The default Close() could return "NotSupported" and we bypass it |
504 | | // if it is not impelmented. Detailed explanations can be found in |
505 | | // db/db_impl/db_impl.h |
506 | 7.64k | if (s.ok()) { |
507 | 7.64k | Status temp_s = dir_obj->Close(opts, nullptr); |
508 | 7.64k | if (!temp_s.ok()) { |
509 | 0 | if (temp_s.IsNotSupported()) { |
510 | 0 | temp_s.PermitUncheckedError(); |
511 | 0 | } else { |
512 | 0 | s = temp_s; |
513 | 0 | } |
514 | 0 | } |
515 | 7.64k | } |
516 | 7.64k | if (!s.ok()) { |
517 | 0 | env->DeleteFile(tmp).PermitUncheckedError(); |
518 | 0 | } |
519 | 7.64k | return s; |
520 | 7.64k | } |
521 | | |
522 | | IOStatus SyncManifest(const ImmutableDBOptions* db_options, |
523 | | const WriteOptions& write_options, |
524 | 102k | WritableFileWriter* file) { |
525 | 102k | TEST_KILL_RANDOM_WITH_WEIGHT("SyncManifest:0", REDUCE_ODDS2); |
526 | 102k | StopWatch sw(db_options->clock, db_options->stats, MANIFEST_FILE_SYNC_MICROS); |
527 | 102k | IOOptions io_options; |
528 | 102k | IOStatus s = PrepareIOFromWriteOptions(write_options, io_options); |
529 | 102k | if (!s.ok()) { |
530 | 0 | return s; |
531 | 0 | } |
532 | 102k | return file->Sync(io_options, db_options->use_fsync); |
533 | 102k | } |
534 | | |
535 | | Status GetInfoLogFiles(const std::shared_ptr<FileSystem>& fs, |
536 | | const std::string& db_log_dir, const std::string& dbname, |
537 | | std::string* parent_dir, |
538 | 0 | std::vector<std::string>* info_log_list) { |
539 | 0 | assert(parent_dir != nullptr); |
540 | 0 | assert(info_log_list != nullptr); |
541 | 0 | uint64_t number = 0; |
542 | 0 | FileType type = kWalFile; |
543 | |
|
544 | 0 | if (!db_log_dir.empty()) { |
545 | 0 | *parent_dir = db_log_dir; |
546 | 0 | } else { |
547 | 0 | *parent_dir = dbname; |
548 | 0 | } |
549 | |
|
550 | 0 | InfoLogPrefix info_log_prefix(!db_log_dir.empty(), dbname); |
551 | |
|
552 | 0 | std::vector<std::string> file_names; |
553 | 0 | Status s = fs->GetChildren(*parent_dir, IOOptions(), &file_names, nullptr); |
554 | |
|
555 | 0 | if (!s.ok()) { |
556 | 0 | return s; |
557 | 0 | } |
558 | | |
559 | 0 | for (auto& f : file_names) { |
560 | 0 | if (ParseFileName(f, &number, info_log_prefix.prefix, &type) && |
561 | 0 | (type == kInfoLogFile)) { |
562 | 0 | info_log_list->push_back(f); |
563 | 0 | } |
564 | 0 | } |
565 | 0 | return Status::OK(); |
566 | 0 | } |
567 | | |
568 | 670k | std::string NormalizePath(const std::string& path) { |
569 | 670k | std::string dst; |
570 | | |
571 | 670k | if (path.length() > 2 && path[0] == kFilePathSeparator && |
572 | 670k | path[1] == kFilePathSeparator) { // Handle UNC names |
573 | 0 | dst.append(2, kFilePathSeparator); |
574 | 0 | } |
575 | | |
576 | 8.49M | for (auto c : path) { |
577 | 8.49M | if (!dst.empty() && (c == kFilePathSeparator || c == '/') && |
578 | 670k | (dst.back() == kFilePathSeparator || dst.back() == '/')) { |
579 | 0 | continue; |
580 | 0 | } |
581 | 8.49M | dst.push_back(c); |
582 | 8.49M | } |
583 | 670k | return dst; |
584 | 670k | } |
585 | | |
586 | | } // namespace ROCKSDB_NAMESPACE |