Merge 'Make use of enum_set in directory lister' from Pavel Emelyanov

The lister accepts sort of a filter -- what kind of entries to list, regular, directories or both. It currently uses unordered_set, but enum_set is shorter and better describes the intent.

Closes #12017

* github.com:scylladb/scylladb:
  lister: Make lister::dir_entry_types an enum_set
  database: Avoid useless local variable
This commit is contained in:
Botond Dénes
2022-11-18 12:15:26 +02:00
11 changed files with 40 additions and 40 deletions

View File

@@ -96,7 +96,7 @@ void manager::register_metrics(const sstring& group_name) {
future<> manager::start(shared_ptr<service::storage_proxy> proxy_ptr, shared_ptr<gms::gossiper> gossiper_ptr) {
_proxy_anchor = std::move(proxy_ptr);
_gossiper_anchor = std::move(gossiper_ptr);
return lister::scan_dir(_hints_dir, { directory_entry_type::directory }, [this] (fs::path datadir, directory_entry de) {
return lister::scan_dir(_hints_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), [this] (fs::path datadir, directory_entry de) {
ep_key_type ep = ep_key_type(de.name);
if (!check_dc_for(ep)) {
return make_ready_future<>();
@@ -656,7 +656,7 @@ future<> manager::change_host_filter(host_filter filter) {
// Iterate over existing hint directories and see if we can enable an endpoint manager
// for some of them
return lister::scan_dir(_hints_dir, { directory_entry_type::directory }, [this] (fs::path datadir, directory_entry de) {
return lister::scan_dir(_hints_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), [this] (fs::path datadir, directory_entry de) {
const ep_key_type ep = ep_key_type(de.name);
if (_ep_managers.contains(ep) || !_host_filter.can_hint_for(_proxy_anchor->get_token_metadata_ptr()->get_topology(), ep)) {
return make_ready_future<>();
@@ -1168,7 +1168,7 @@ void manager::end_point_hints_manager::sender::send_hints_maybe() noexcept {
}
static future<> scan_for_hints_dirs(const sstring& hints_directory, std::function<future<> (fs::path dir, directory_entry de, unsigned shard_id)> f) {
return lister::scan_dir(hints_directory, { directory_entry_type::directory }, [f = std::move(f)] (fs::path dir, directory_entry de) mutable {
return lister::scan_dir(hints_directory, lister::dir_entry_types::of<directory_entry_type::directory>(), [f = std::move(f)] (fs::path dir, directory_entry de) mutable {
unsigned shard_id;
try {
shard_id = std::stoi(de.name.c_str());
@@ -1188,10 +1188,10 @@ manager::hints_segments_map manager::get_current_hints_segments(const sstring& h
scan_for_hints_dirs(hints_directory, [&current_hints_segments] (fs::path dir, directory_entry de, unsigned shard_id) {
manager_logger.trace("shard_id = {}", shard_id);
// IPs level
return lister::scan_dir(dir / de.name.c_str(), { directory_entry_type::directory }, [&current_hints_segments, shard_id] (fs::path dir, directory_entry de) {
return lister::scan_dir(dir / de.name.c_str(), lister::dir_entry_types::of<directory_entry_type::directory>(), [&current_hints_segments, shard_id] (fs::path dir, directory_entry de) {
manager_logger.trace("\tIP: {}", de.name);
// hints files
return lister::scan_dir(dir / de.name.c_str(), { directory_entry_type::regular }, [&current_hints_segments, shard_id, ep_addr = de.name] (fs::path dir, directory_entry de) {
return lister::scan_dir(dir / de.name.c_str(), lister::dir_entry_types::of<directory_entry_type::regular>(), [&current_hints_segments, shard_id, ep_addr = de.name] (fs::path dir, directory_entry de) {
manager_logger.trace("\t\tfile: {}", de.name);
current_hints_segments[ep_addr][shard_id].emplace_back(dir / de.name.c_str());
return make_ready_future<>();
@@ -1305,7 +1305,7 @@ void manager::remove_irrelevant_shards_directories(const sstring& hints_director
scan_for_hints_dirs(hints_directory, [] (fs::path dir, directory_entry de, unsigned shard_id) {
if (shard_id >= smp::count) {
// IPs level
return lister::scan_dir(dir / de.name.c_str(), { directory_entry_type::directory, directory_entry_type::regular }, lister::show_hidden::yes, [] (fs::path dir, directory_entry de) {
return lister::scan_dir(dir / de.name.c_str(), lister::dir_entry_types::full(), lister::show_hidden::yes, [] (fs::path dir, directory_entry de) {
return io_check(remove_file, (dir / de.name.c_str()).native());
}).then([shard_base_dir = dir, shard_entry = de] {
return io_check(remove_file, (shard_base_dir / shard_entry.name.c_str()).native());

View File

@@ -99,7 +99,7 @@ future<> space_watchdog::scan_one_ep_dir(fs::path path, manager& shard_manager,
if (!exists) {
return make_ready_future<>();
} else {
return lister::scan_dir(path, { directory_entry_type::regular }, [this, ep_key, &shard_manager] (fs::path dir, directory_entry de) {
return lister::scan_dir(path, lister::dir_entry_types::of<directory_entry_type::regular>(), [this, ep_key, &shard_manager] (fs::path dir, directory_entry de) {
// Put the current end point ID to state.eps_with_pending_hints when we see the second hints file in its directory
if (_files_count == 1) {
shard_manager.add_ep_with_pending_hints(ep_key);
@@ -138,7 +138,7 @@ void space_watchdog::on_timer() {
_total_size = 0;
for (manager& shard_manager : per_device_limits.managers) {
shard_manager.clear_eps_with_pending_hints();
lister::scan_dir(shard_manager.hints_dir(), {directory_entry_type::directory}, [this, &shard_manager] (fs::path dir, directory_entry de) {
lister::scan_dir(shard_manager.hints_dir(), lister::dir_entry_types::of<directory_entry_type::directory>(), [this, &shard_manager] (fs::path dir, directory_entry de) {
_files_count = 0;
// Let's scan per-end-point directories and enumerate hints files...
//

View File

@@ -2542,15 +2542,14 @@ static std::pair<sstring, table_id> extract_cf_name_and_uuid(const sstring& dire
future<std::vector<database::snapshot_details_result>> database::get_snapshot_details() {
std::vector<sstring> data_dirs = _cfg.data_file_directories();
auto dirs_only_entries = lister::dir_entry_types{directory_entry_type::directory};
std::vector<database::snapshot_details_result> details;
for (auto& datadir : data_dirs) {
co_await lister::scan_dir(datadir, dirs_only_entries, [this, &dirs_only_entries, &details] (fs::path parent_dir, directory_entry de) -> future<> {
co_await lister::scan_dir(datadir, lister::dir_entry_types::of<directory_entry_type::directory>(), [this, &details] (fs::path parent_dir, directory_entry de) -> future<> {
// KS directory
sstring ks_name = de.name;
co_return co_await lister::scan_dir(parent_dir / de.name, dirs_only_entries, [this, &dirs_only_entries, &details, ks_name = std::move(ks_name)] (fs::path parent_dir, directory_entry de) -> future<> {
co_return co_await lister::scan_dir(parent_dir / de.name, lister::dir_entry_types::of<directory_entry_type::directory>(), [this, &details, ks_name = std::move(ks_name)] (fs::path parent_dir, directory_entry de) -> future<> {
// CF directory
auto cf_dir = parent_dir / de.name;
@@ -2562,13 +2561,13 @@ future<std::vector<database::snapshot_details_result>> database::get_snapshot_de
}
auto cf_name_and_uuid = extract_cf_name_and_uuid(de.name);
co_return co_await lister::scan_dir(cf_dir / sstables::snapshots_dir, dirs_only_entries, [this, &details, &ks_name, &cf_name = cf_name_and_uuid.first, &cf_dir] (fs::path parent_dir, directory_entry de) -> future<> {
co_return co_await lister::scan_dir(cf_dir / sstables::snapshots_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), [this, &details, &ks_name, &cf_name = cf_name_and_uuid.first, &cf_dir] (fs::path parent_dir, directory_entry de) -> future<> {
database::snapshot_details_result snapshot_result = {
.snapshot_name = de.name,
.details = {0, 0, cf_name, ks_name}
};
co_await lister::scan_dir(parent_dir / de.name, { directory_entry_type::regular }, [this, cf_dir, &snapshot_result] (fs::path snapshot_dir, directory_entry de) -> future<> {
co_await lister::scan_dir(parent_dir / de.name, lister::dir_entry_types::of<directory_entry_type::regular>(), [this, cf_dir, &snapshot_result] (fs::path snapshot_dir, directory_entry de) -> future<> {
auto sd = co_await io_check(file_stat, (snapshot_dir / de.name).native(), follow_symlink::no);
auto size = sd.allocated_size;
@@ -2651,13 +2650,13 @@ future<> database::clear_snapshot(sstring tag, std::vector<sstring> keyspace_nam
// |- ...
//
auto data_dir = fs::path(parent_dir);
auto data_dir_lister = directory_lister(data_dir, {directory_entry_type::directory}, filter);
auto data_dir_lister = directory_lister(data_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), filter);
auto close_data_dir_lister = deferred_close(data_dir_lister);
dblog.debug("clear_snapshot: listing data dir {} with filter={}", data_dir, ks_names_set.empty() ? "none" : fmt::format("{}", ks_names_set));
while (auto ks_ent = data_dir_lister.get().get0()) {
auto ks_name = ks_ent->name;
auto ks_dir = data_dir / ks_name;
auto ks_dir_lister = directory_lister(ks_dir, {directory_entry_type::directory}, table_filter);
auto ks_dir_lister = directory_lister(ks_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), table_filter);
auto close_ks_dir_lister = deferred_close(ks_dir_lister);
dblog.debug("clear_snapshot: listing keyspace dir {} with filter={}", ks_dir, table_name_param.empty() ? "none" : fmt::format("{}", table_name_param));
while (auto table_ent = ks_dir_lister.get().get0()) {
@@ -2671,7 +2670,7 @@ future<> database::clear_snapshot(sstring tag, std::vector<sstring> keyspace_nam
has_snapshots = false;
} else {
// if specific snapshots tags were given - filter only these snapshot directories
auto snapshots_dir_lister = directory_lister(snapshots_dir, {directory_entry_type::directory});
auto snapshots_dir_lister = directory_lister(snapshots_dir, lister::dir_entry_types::of<directory_entry_type::directory>());
auto close_snapshots_dir_lister = deferred_close(snapshots_dir_lister);
dblog.debug("clear_snapshot: listing snapshots dir {} with filter={}", snapshots_dir, tag);
has_snapshots = false; // unless other snapshots are found

View File

@@ -406,7 +406,7 @@ distributed_loader::get_sstables_from_upload_dir(distributed<replica::database>&
future<> distributed_loader::cleanup_column_family_temp_sst_dirs(sstring sstdir) {
std::vector<future<>> futures;
co_await lister::scan_dir(sstdir, { directory_entry_type::directory }, [&] (fs::path sstdir, directory_entry de) {
co_await lister::scan_dir(sstdir, lister::dir_entry_types::of<directory_entry_type::directory>(), [&] (fs::path sstdir, directory_entry de) {
// push futures that remove files/directories into an array of futures,
// so that the supplied callback will not block scan_dir() from
// reading the next entry in the directory.
@@ -424,7 +424,7 @@ future<> distributed_loader::cleanup_column_family_temp_sst_dirs(sstring sstdir)
future<> distributed_loader::handle_sstables_pending_delete(sstring pending_delete_dir) {
std::vector<future<>> futures;
co_await lister::scan_dir(pending_delete_dir, { directory_entry_type::regular }, [&futures] (fs::path dir, directory_entry de) {
co_await lister::scan_dir(pending_delete_dir, lister::dir_entry_types::of<directory_entry_type::regular>(), [&futures] (fs::path dir, directory_entry de) {
// push nested futures that remove files/directories into an array of futures,
// so that the supplied callback will not block scan_dir() from
// reading the next entry in the directory.
@@ -744,7 +744,7 @@ future<> distributed_loader::init_non_system_keyspaces(distributed<replica::data
parallel_for_each(cfg.data_file_directories(), [&db, &dirs] (sstring directory) {
// we want to collect the directories first, so we can get a full set of potential dirs
return lister::scan_dir(directory, { directory_entry_type::directory }, [&dirs] (fs::path datadir, directory_entry de) {
return lister::scan_dir(directory, lister::dir_entry_types::of<directory_entry_type::directory>(), [&dirs] (fs::path datadir, directory_entry de) {
if (!is_system_keyspace(de.name)) {
dirs.emplace(de.name, datadir.native());
}

View File

@@ -1560,10 +1560,10 @@ future<std::unordered_map<sstring, table::snapshot_details>> table::get_snapshot
continue;
}
lister::scan_dir(snapshots_dir, { directory_entry_type::directory }, [this, datadir, &all_snapshots] (fs::path snapshots_dir, directory_entry de) {
lister::scan_dir(snapshots_dir, lister::dir_entry_types::of<directory_entry_type::directory>(), [this, datadir, &all_snapshots] (fs::path snapshots_dir, directory_entry de) {
auto snapshot_name = de.name;
all_snapshots.emplace(snapshot_name, snapshot_details());
return lister::scan_dir(snapshots_dir / fs::path(snapshot_name), { directory_entry_type::regular }, [this, datadir, &all_snapshots, snapshot_name] (fs::path snapshot_dir, directory_entry de) {
return lister::scan_dir(snapshots_dir / fs::path(snapshot_name), lister::dir_entry_types::of<directory_entry_type::regular>(), [this, datadir, &all_snapshots, snapshot_name] (fs::path snapshot_dir, directory_entry de) {
return io_check(file_stat, (snapshot_dir / de.name).native(), follow_symlink::no).then([this, datadir, &all_snapshots, snapshot_name, snapshot_dir, name = de.name] (stat_data sd) {
auto size = sd.allocated_size;

View File

@@ -172,7 +172,7 @@ sstable_directory::process_sstable_dir(bool sort_sstables_according_to_owner) {
scan_state state;
directory_lister sstable_dir_lister(_sstable_dir, { directory_entry_type::regular }, &manifest_json_filter);
directory_lister sstable_dir_lister(_sstable_dir, lister::dir_entry_types::of<directory_entry_type::regular>(), &manifest_json_filter);
std::exception_ptr ex;
try {
while (auto de = co_await sstable_dir_lister.get()) {

View File

@@ -506,7 +506,7 @@ SEASTAR_TEST_CASE(snapshot_works) {
};
auto& cf = e.local_db().find_column_family("ks", "cf");
lister::scan_dir(fs::path(cf.dir()), { directory_entry_type::regular }, [&expected] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(fs::path(cf.dir()), lister::dir_entry_types::of<directory_entry_type::regular>(), [&expected] (fs::path parent_dir, directory_entry de) {
expected.insert(de.name);
return make_ready_future<>();
}).get();
@@ -514,7 +514,7 @@ SEASTAR_TEST_CASE(snapshot_works) {
BOOST_REQUIRE_GT(expected.size(), 1);
// all files were copied and manifest was generated
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), { directory_entry_type::regular }, [&expected] (fs::path parent_dir, directory_entry de) {
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), lister::dir_entry_types::of<directory_entry_type::regular>(), [&expected] (fs::path parent_dir, directory_entry de) {
expected.erase(de.name);
return make_ready_future<>();
}).get();
@@ -533,7 +533,7 @@ SEASTAR_TEST_CASE(snapshot_skip_flush_works) {
};
auto& cf = e.local_db().find_column_family("ks", "cf");
lister::scan_dir(fs::path(cf.dir()), { directory_entry_type::regular }, [&expected] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(fs::path(cf.dir()), lister::dir_entry_types::of<directory_entry_type::regular>(), [&expected] (fs::path parent_dir, directory_entry de) {
expected.insert(de.name);
return make_ready_future<>();
}).get();
@@ -542,7 +542,7 @@ SEASTAR_TEST_CASE(snapshot_skip_flush_works) {
BOOST_REQUIRE_EQUAL(expected.size(), 1);
// all files were copied and manifest was generated
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), { directory_entry_type::regular }, [&expected] (fs::path parent_dir, directory_entry de) {
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), lister::dir_entry_types::of<directory_entry_type::regular>(), [&expected] (fs::path parent_dir, directory_entry de) {
expected.erase(de.name);
return make_ready_future<>();
}).get();
@@ -564,7 +564,7 @@ SEASTAR_TEST_CASE(snapshot_list_okay) {
BOOST_REQUIRE_EQUAL(sd.live, 0);
BOOST_REQUIRE_GT(sd.total, 0);
lister::scan_dir(fs::path(cf.dir()), { directory_entry_type::regular }, [] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(fs::path(cf.dir()), lister::dir_entry_types::of<directory_entry_type::regular>(), [] (fs::path parent_dir, directory_entry de) {
fs::remove(parent_dir / de.name);
return make_ready_future<>();
}).get();
@@ -632,7 +632,7 @@ SEASTAR_TEST_CASE(clear_snapshot) {
auto& cf = e.local_db().find_column_family("ks", "cf");
unsigned count = 0;
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), { directory_entry_type::regular }, [&count] (fs::path parent_dir, directory_entry de) {
lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), lister::dir_entry_types::of<directory_entry_type::regular>(), [&count] (fs::path parent_dir, directory_entry de) {
count++;
return make_ready_future<>();
}).get();
@@ -668,7 +668,7 @@ SEASTAR_TEST_CASE(clear_multiple_snapshots) {
for (auto i = 0; i < num_snapshots; i++) {
unsigned count = 0;
testlog.debug("Verifying {}", snapshots_dir / snapshot_name(i));
lister::scan_dir(snapshots_dir / snapshot_name(i), { directory_entry_type::regular }, [&count] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(snapshots_dir / snapshot_name(i), lister::dir_entry_types::of<directory_entry_type::regular>(), [&count] (fs::path parent_dir, directory_entry de) {
count++;
return make_ready_future<>();
}).get();
@@ -754,7 +754,7 @@ SEASTAR_TEST_CASE(test_snapshot_ctl_details) {
BOOST_REQUIRE_EQUAL(sc_sd.live, sd.live);
BOOST_REQUIRE_EQUAL(sc_sd.total, sd.total);
lister::scan_dir(fs::path(cf.dir()), { directory_entry_type::regular }, [] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(fs::path(cf.dir()), lister::dir_entry_types::of<directory_entry_type::regular>(), [] (fs::path parent_dir, directory_entry de) {
fs::remove(parent_dir / de.name);
return make_ready_future<>();
}).get();
@@ -796,7 +796,7 @@ SEASTAR_TEST_CASE(test_snapshot_ctl_true_snapshots_size) {
auto sc_live_size = sc.local().true_snapshots_size().get0();
BOOST_REQUIRE_EQUAL(sc_live_size, sd.live);
lister::scan_dir(fs::path(cf.dir()), { directory_entry_type::regular }, [] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(fs::path(cf.dir()), lister::dir_entry_types::of<directory_entry_type::regular>(), [] (fs::path parent_dir, directory_entry de) {
fs::remove(parent_dir / de.name);
return make_ready_future<>();
}).get();
@@ -1185,7 +1185,7 @@ SEASTAR_TEST_CASE(snapshot_with_quarantine_works) {
auto& cf = db.local().find_column_family("ks", "cf");
// all files were copied and manifest was generated
co_await lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), { directory_entry_type::regular }, [&expected] (fs::path parent_dir, directory_entry de) {
co_await lister::scan_dir((fs::path(cf.dir()) / sstables::snapshots_dir / "test"), lister::dir_entry_types::of<directory_entry_type::regular>(), [&expected] (fs::path parent_dir, directory_entry de) {
testlog.debug("Found in snapshots: {}", de.name);
expected.erase(de.name);
return make_ready_future<>();

View File

@@ -32,7 +32,7 @@ public:
SEASTAR_TEST_CASE(test_empty_lister) {
auto tmp = tmpdir();
size_t count = 0;
co_await lister::scan_dir(tmp.path(), { directory_entry_type::directory, directory_entry_type::regular }, [&count] (fs::path dir, directory_entry de) {
co_await lister::scan_dir(tmp.path(), lister::dir_entry_types::full(), [&count] (fs::path dir, directory_entry de) {
++count;
return make_ready_future<>();
});
@@ -99,7 +99,7 @@ SEASTAR_TEST_CASE(test_lister_abort) {
// aborts the lister and that the exception is propagated
// to the scan_dir resulting future.
size_t walked = 0;
auto f = lister::scan_dir(tmp.path(), { directory_entry_type::directory, directory_entry_type::regular }, [&walked, initial] (fs::path dir, directory_entry de) {
auto f = lister::scan_dir(tmp.path(), lister::dir_entry_types::full(), [&walked, initial] (fs::path dir, directory_entry de) {
if (++walked == initial) {
throw expected_exception();
}
@@ -111,7 +111,7 @@ SEASTAR_TEST_CASE(test_lister_abort) {
// similar to the above, just return an exceptional future
// rather than throwing the exception.
walked = 0;
f = lister::scan_dir(tmp.path(), { directory_entry_type::directory, directory_entry_type::regular }, [&walked, initial] (fs::path dir, directory_entry de) {
f = lister::scan_dir(tmp.path(), lister::dir_entry_types::full(), [&walked, initial] (fs::path dir, directory_entry de) {
if (++walked == initial) {
return make_exception_future<>(expected_exception());
}

View File

@@ -328,7 +328,7 @@ SEASTAR_THREAD_TEST_CASE(sstable_directory_test_temporary_statistics) {
[&dir, &tempstat] (sharded<sstables::sstable_directory>& sstdir_ok) {
auto expect_ok = distributed_loader_for_tests::process_sstable_dir(sstdir_ok);
BOOST_REQUIRE_NO_THROW(expect_ok.get());
lister::scan_dir(dir.path(), { directory_entry_type::regular }, [tempstat] (fs::path parent_dir, directory_entry de) {
lister::scan_dir(dir.path(), lister::dir_entry_types::of<directory_entry_type::regular>(), [tempstat] (fs::path parent_dir, directory_entry de) {
BOOST_REQUIRE(fs::canonical(parent_dir / fs::path(de.name)) != tempstat);
return make_ready_future<>();
}).get();

View File

@@ -19,7 +19,7 @@ lister::lister(file f, dir_entry_types type, walker_type walker, filter_type fil
future<> lister::visit(directory_entry de) {
return guarantee_type(std::move(de)).then([this] (directory_entry de) {
// Hide all synthetic directories and hidden files if not requested to show them.
if ((!_expected_type.empty() && !_expected_type.contains(*(de.type))) || (!_show_hidden && de.name[0] == '.')) {
if ((_expected_type && !_expected_type.contains(*(de.type))) || (!_show_hidden && de.name[0] == '.')) {
return make_ready_future<>();
}

View File

@@ -16,7 +16,7 @@
#include <seastar/core/queue.hh>
#include <seastar/core/pipe.hh>
#include <seastar/util/bool_class.hh>
#include "enum_set.hh"
#include "seastarx.hh"
namespace fs = std::filesystem;
@@ -27,7 +27,8 @@ public:
* 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>>;
using listable_entry_types = super_enum<directory_entry_type, directory_entry_type::regular, directory_entry_type::directory>;
using dir_entry_types = enum_set<listable_entry_types>;
/**
* This callback is going to be called for each entry in the given directory
* that has the corresponding type and meets the filter demands.
@@ -165,7 +166,7 @@ class directory_lister {
std::optional<future<>> _opt_done_fut;
public:
directory_lister(fs::path dir,
lister::dir_entry_types type = {directory_entry_type::regular, directory_entry_type::directory},
lister::dir_entry_types type = lister::dir_entry_types::full(),
lister::filter_type filter = [] (const fs::path& parent_dir, const directory_entry& entry) { return true; },
lister::show_hidden do_show_hidden = lister::show_hidden::yes) noexcept
: _dir(std::move(dir))