forked from scylladb/scylladb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlister.hh
163 lines (147 loc) · 7.18 KB
/
lister.hh
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* Copyright (C) 2017 ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <unordered_set>
#include <seastar/core/shared_ptr.hh>
#include <seastar/core/file.hh>
#include <seastar/core/enum.hh>
#include <boost/filesystem.hpp>
class lister final {
public:
using path = boost::filesystem::path;
/**
* Types of entries to list. If empty - list all present entries except for
* hidden if not requested to.
*/
using dir_entry_types = std::unordered_set<directory_entry_type, enum_hash<directory_entry_type>>;
/**
* This callback is going to be called for each entry in the given directory
* that has the corresponding type and meets the filter demands.
*
* First parameter is a boost::filesystem::path object for the base directory.
*
* Second parameter is a directory_entry object of the file for which this
* callback is being called.
*
* The first parameter of the callback represents a parent directory of
* each entry defined by the second parameter.
*/
using walker_type = std::function<future<> (path, directory_entry)>;
using filter_type = std::function<bool (const path&, const directory_entry&)>;
struct show_hidden_tag {};
using show_hidden = bool_class<show_hidden_tag>;
private:
file _f;
walker_type _walker;
filter_type _filter;
dir_entry_types _expected_type;
subscription<directory_entry> _listing;
path _dir;
show_hidden _show_hidden;
public:
/**
* Scans the directory calling a "walker" callback for each entry that satisfies the filtering.
*
* @param dir Directory to scan.
* @param type Type of entries to process. Entries of other types will be ignored.
* @param do_show_hidden if TRUE - the hidden entries are going to be processed as well.
* @param walker A callback to be called for each entry that satisfies the filtering rules.
* @param filter A filter callback that is called for each entry of the requested type: if returns FALSE - the entry will be skipped.
*
* @return A future that resolves when all entries processing is finished or an error occurs. In the later case an exceptional future is returened.
*/
static future<> scan_dir(path dir, dir_entry_types type, show_hidden do_show_hidden, walker_type walker, filter_type filter);
/**
* Overload of scan_dir() that uses a show_hidden::no when it's not given.
*/
static future<> scan_dir(path dir, dir_entry_types type, walker_type walker, filter_type filter) {
return scan_dir(std::move(dir), std::move(type), show_hidden::no, std::move(walker), std::move(filter));
}
/**
* Overload of scan_dir() that uses a show_hidden::no and a filter that returns TRUE for every entry when they are not given.
*/
static future<> scan_dir(path dir, dir_entry_types type, walker_type walker) {
return scan_dir(std::move(dir), std::move(type), show_hidden::no, std::move(walker), [] (const path& parent_dir, const directory_entry& entry) { return true; });
}
/**
* Overload of scan_dir() that uses a filter that returns TRUE for every entry when filter is not given.
*/
static future<> scan_dir(path dir, dir_entry_types type, show_hidden do_show_hidden, walker_type walker) {
return scan_dir(std::move(dir), std::move(type), do_show_hidden, std::move(walker), [] (const path& parent_dir, const directory_entry& entry) { return true; });
}
/** Overloads accepting sstring as the first parameter */
static future<> scan_dir(sstring dir, dir_entry_types type, show_hidden do_show_hidden, walker_type walker, filter_type filter) {
return scan_dir(path(std::move(dir)), std::move(type), do_show_hidden, std::move(walker), std::move(filter));
}
static future<> scan_dir(sstring dir, dir_entry_types type, walker_type walker, filter_type filter) {
return scan_dir(path(std::move(dir)), std::move(type), show_hidden::no, std::move(walker), std::move(filter));
}
static future<> scan_dir(sstring dir, dir_entry_types type, walker_type walker) {
return scan_dir(path(std::move(dir)), std::move(type), show_hidden::no, std::move(walker), [] (const path& parent_dir, const directory_entry& entry) { return true; });
}
static future<> scan_dir(sstring dir, dir_entry_types type, show_hidden do_show_hidden, walker_type walker) {
return scan_dir(path(std::move(dir)), std::move(type), do_show_hidden, std::move(walker), [] (const path& parent_dir, const directory_entry& entry) { return true; });
}
/**
* Removes the given directory with all its contents (like 'rm -rf <dir>' shell command).
*
* @param dir Directory to remove.
* @return A future that resolves when the operation is complete or an error occurs.
*/
static future<> rmdir(path dir);
/**
* Constructor
*
* @param f A file instance for the directory to scan.
* @param type Types of entries to scan.
* @param walker A callback to be called for each entry that satisfies the filtering rules.
* @param filter A filter callback that is called for each entry of the requested type: if returns FALSE - the entry will be skipped.
* @param dir A seastar::path object for the directory to scan.
* @param do_show_hidden if TRUE - scan hidden entries as well.
*/
lister(file f, dir_entry_types type, walker_type walker, filter_type filter, path dir, show_hidden do_show_hidden);
/**
* @return a future that resolves when the directory scanning is complete.
*/
future<> done();
private:
/**
* Handle a single entry.
*
* @param de Descriptor of the entry to handle.
* @return A future that resolves when the handling is over.
*/
future<> visit(directory_entry de);
/**
* Validates that the input parameter has its "type" optional field engaged.
*
* This helper method is called before further processing the @param de in order
* to ensure that its "type" field is engaged.
*
* If it is engaged - returns the input value as is.
* If "type" isn't engaged - calls the engine().file_type() for file represented by @param de and sets
* "type" field of @param de to the returned value and then returns @param de.
*
* @param de entry to check and return
* @return a future that resolves with the @param de with the engaged de.type field or an
* exceptional future with std::system_error exception if type of the file represented by @param de may not be retrieved.
*/
future<directory_entry> guarantee_type(directory_entry de);
};