forked from ClickHouse/ClickHouse
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCommandDiskUsage.cpp
More file actions
94 lines (80 loc) · 3.08 KB
/
Copy pathCommandDiskUsage.cpp
File metadata and controls
94 lines (80 loc) · 3.08 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <ICommand.h>
#include <Common/formatReadable.h>
#include <Common/logger_useful.h>
#include <stack>
namespace DB
{
namespace ErrorCodes
{
extern const int BAD_ARGUMENTS;
extern const int FILE_DOESNT_EXIST;
}
class CommandDiskUsage final : public ICommand
{
public:
CommandDiskUsage()
: ICommand("CommandDiskUsage")
{
command_name = "du";
description = "Print the total size in bytes for a file or directory.";
options_description.add_options()("path", po::value<String>(), "File or directory to report the size of.")(
"human-readable,h", "Print sizes in a human-readable format");
positional_options_description.add("path", 1);
}
void executeImpl(const CommandLineOptions & options, DisksClient & client) override
{
const auto & disk = client.getCurrentDiskWithPath();
String path = getValueFromCommandLineOptionsWithDefault<String>(options, "path", ".");
bool human_readable = options.contains("human-readable");
const String relative = disk.getRelativeFromRoot(path);
if (!disk.getDisk()->existsFile(relative) && !disk.isDirectory(path))
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Path {} on disk {} doesn't exist", path, disk.getDisk()->getName());
LOG_INFO(log, "Computing disk usage of '{}' at disk '{}'", path, disk.getDisk()->getName());
UInt64 size = computeSize(disk, path);
if (human_readable)
std::cout << formatReadableSizeWithBinarySuffix(size) << "\n";
else
std::cout << size << "\n";
}
private:
/// Returns the size of a file, or the total size of all files contained in a directory recursively.
UInt64 computeSize(const DiskWithPath & disk, const String & path) const
{
UInt64 total = 0;
std::stack<String> stack;
stack.push(path);
while (!stack.empty())
{
const String current = std::move(stack.top());
stack.pop();
const String relative = disk.getRelativeFromRoot(current);
if (disk.getDisk()->existsDirectory(relative))
{
for (const auto & file_name : disk.listAllFilesByPath(current))
stack.push(current.ends_with("/") ? current + file_name : current + "/" + file_name);
}
else
{
// Wrap getFileSize in try/catch, in case file disappears while traversing.
try
{
total += disk.getDisk()->getFileSize(relative);
}
catch (const Exception & e)
{
/// Throw for failures related to object storage, metadata, permissions.
if (e.code() != ErrorCodes::FILE_DOESNT_EXIST)
throw;
LOG_WARNING(log, "File '{}' disappeared while traversing, skipping", current);
continue;
}
}
}
return total;
}
};
CommandPtr makeCommandDiskUsage()
{
return std::make_shared<DB::CommandDiskUsage>();
}
}