blob: c1e8b6b7396ffac32df2628428b75554a42b9fd7 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "dirtraverse.h"
#include <vespa/vespalib/util/size_literals.h>
#include <filesystem>
#include <system_error>
namespace search {
namespace fs = std::filesystem;
namespace {
uint64_t
try_get_tree_size(const std::string& base_dir)
{
fs::path path(base_dir);
std::error_code ec;
fs::recursive_directory_iterator dir_itr(path, fs::directory_options::skip_permission_denied, ec);
if (ec) {
return 0;
}
uint64_t total_size = 0;
constexpr uint64_t block_size = 4_Ki;
for (const auto &elem : dir_itr) {
if (fs::is_regular_file(elem.path()) && !fs::is_symlink(elem.path())) {
const auto size = elem.file_size(ec);
if (!ec) {
// round up size to file system block size (assumed to be 4 KiB)
auto adj_size = ((size + block_size - 1) / block_size) * block_size;
total_size += adj_size;
}
}
}
return total_size;
}
}
uint64_t
DirectoryTraverse::GetTreeSize()
{
// Since try_get_tree_size may throw on concurrent directory
// modifications, immediately retry a bounded number of times if this
// happens. Number of retries chosen randomly by counting fingers.
for (int i = 0; i < 10; ++i) {
try {
return try_get_tree_size(_base_dir);
} catch (const fs::filesystem_error&) {
// Go around for another spin that hopefully won't race.
}
}
return 0;
}
DirectoryTraverse::DirectoryTraverse(const std::string& base_dir)
: _base_dir(base_dir)
{
}
DirectoryTraverse::~DirectoryTraverse() = default;
} // namespace search
|