mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
Merge 'Decouple sstables::storage::snapshot() and ::clone() functionality' from Pavel Emelyanov
The storage::snapshot() is used in two different modes -- one to save sstable as snapshot somewhere, and another one to create a copy of sstable. The latter use-case is "optimized" by snapshotting an sstable under new generation, but it's only true for local storage. Despite for S3 storage snapshot is not implemented, _cloning_ sstable stored on S3 is not necessarily going to be the same as doing a snapshot. Another sign of snapshot and clone being different is that calling snapshot() for snapshot itself and for clone use two very different sets of arguments -- snapshotting specifies relative name and omits new generation, while cloning doesn't need "name" and instead provides generation. Recently (#26528) cloning got extra "leave_unsealed" tag, that makes no sense for snapshotting. Having said that, this PR introduces sstables::storage::clone() method and modifies both, callers and implementations, according to the above features of each. As a result, code logic in both methods become much simpler and a bunch of bool classes and "_tag" helper structures goes away. Improving internal APIs, no need to backport Closes scylladb/scylladb#27871 * github.com:scylladb/scylladb: sstables, storage: Drop unused bool classes and tags sstables/storage: Drop create_links_common() overloads sstable: Simplify storage::snapshot() sstables: Introduce storage::clone()
This commit is contained in:
@@ -902,7 +902,7 @@ future<std::unordered_map<component_type, file>> sstable::readable_file_for_all_
|
||||
}
|
||||
|
||||
future<entry_descriptor> sstable::clone(generation_type new_generation, bool leave_unsealed) const {
|
||||
co_await _storage->snapshot(*this, _storage->prefix(), storage::absolute_path::yes, new_generation, storage::leave_unsealed(leave_unsealed));
|
||||
co_await _storage->clone(*this, new_generation, leave_unsealed);
|
||||
co_return entry_descriptor(new_generation, _version, _format, component_type::TOC, _state);
|
||||
}
|
||||
|
||||
@@ -2123,7 +2123,7 @@ future<> sstable::seal_sstable(bool backup)
|
||||
_marked_for_deletion = mark_for_deletion::none;
|
||||
}
|
||||
if (backup) {
|
||||
co_await _storage->snapshot(*this, "backups", storage::absolute_path::no);
|
||||
co_await _storage->snapshot(*this, "backups");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2491,7 +2491,7 @@ std::vector<std::pair<component_type, sstring>> sstable::all_components() const
|
||||
|
||||
future<> sstable::snapshot(const sstring& name) const {
|
||||
auto lock = co_await get_units(_mutate_sem, 1);
|
||||
co_await _storage->snapshot(*this, format("{}/{}", sstables::snapshots_dir, name), storage::absolute_path::no);
|
||||
co_await _storage->snapshot(*this, format("{}/{}", sstables::snapshots_dir, name));
|
||||
}
|
||||
|
||||
future<> sstable::change_state(sstable_state to, delayed_commit_changes* delay_commit) {
|
||||
|
||||
@@ -50,9 +50,6 @@ class filesystem_storage final : public sstables::storage {
|
||||
std::optional<std::filesystem::path> _temp_dir; // Valid while the sstable is being created, until sealed
|
||||
|
||||
private:
|
||||
struct mark_for_removal_tag {};
|
||||
struct leave_unsealed_tag {};
|
||||
|
||||
enum class link_mode {
|
||||
default_mode,
|
||||
mark_for_removal,
|
||||
@@ -69,9 +66,6 @@ private:
|
||||
future<> remove_temp_dir();
|
||||
virtual future<> create_links(const sstable& sst, const std::filesystem::path& dir) const override;
|
||||
future<> create_links_common(const sstable& sst, sstring dst_dir, generation_type dst_gen, link_mode mode) const;
|
||||
future<> create_links_common(const sstable& sst, sstring dst_dir, generation_type dst_gen, mark_for_removal_tag) const;
|
||||
future<> create_links_common(const sstable& sst, const std::filesystem::path& dir, std::optional<generation_type> gen, leave_unsealed_tag) const;
|
||||
future<> create_links_common(const sstable& sst, const std::filesystem::path& dir, std::optional<generation_type> dst_gen) const;
|
||||
future<> touch_temp_dir(const sstable& sst);
|
||||
future<> move(const sstable& sst, sstring new_dir, generation_type generation, delayed_commit_changes* delay) override;
|
||||
future<> rename_new_file(const sstable& sst, sstring from_name, sstring to_name) const;
|
||||
@@ -92,7 +86,8 @@ public:
|
||||
{}
|
||||
|
||||
virtual future<> seal(const sstable& sst) override;
|
||||
virtual future<> snapshot(const sstable& sst, sstring dir, absolute_path abs, std::optional<generation_type> gen, storage::leave_unsealed) const override;
|
||||
virtual future<> snapshot(const sstable& sst, sstring name) const override;
|
||||
virtual future<> clone(const sstable& sst, generation_type gen, bool leave_unsealed) const override;
|
||||
virtual future<> change_state(const sstable& sst, sstable_state state, generation_type generation, delayed_commit_changes* delay) override;
|
||||
// runs in async context
|
||||
virtual void open(sstable& sst) override;
|
||||
@@ -408,35 +403,17 @@ future<> filesystem_storage::create_links_common(const sstable& sst, sstring dst
|
||||
sstlog.trace("create_links: {} -> {} generation={}: done", sst.get_filename(), dst_dir, generation);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::create_links_common(const sstable& sst, sstring dst_dir, generation_type dst_gen, mark_for_removal_tag) const {
|
||||
return create_links_common(sst, dst_dir, dst_gen, link_mode::mark_for_removal);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::create_links_common(const sstable& sst, const std::filesystem::path& dir, std::optional<generation_type> gen, leave_unsealed_tag) const {
|
||||
return create_links_common(sst, dir.native(), gen.value_or(sst._generation), link_mode::leave_unsealed);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::create_links_common(const sstable& sst, const std::filesystem::path& dir, std::optional<generation_type> gen) const {
|
||||
return create_links_common(sst, dir.native(), gen.value_or(sst._generation), link_mode::default_mode);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::create_links(const sstable& sst, const std::filesystem::path& dir) const {
|
||||
return create_links_common(sst, dir.native(), sst._generation, link_mode::default_mode);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::snapshot(const sstable& sst, sstring dir, absolute_path abs, std::optional<generation_type> gen, storage::leave_unsealed leave_unsealed) const {
|
||||
std::filesystem::path snapshot_dir;
|
||||
if (abs) {
|
||||
snapshot_dir = dir;
|
||||
} else {
|
||||
snapshot_dir = _base_dir.path() / dir;
|
||||
}
|
||||
future<> filesystem_storage::snapshot(const sstable& sst, sstring name) const {
|
||||
std::filesystem::path snapshot_dir = _base_dir.path() / name;
|
||||
co_await sst.sstable_touch_directory_io_check(snapshot_dir);
|
||||
if (leave_unsealed) {
|
||||
co_await create_links_common(sst, snapshot_dir, std::move(gen), leave_unsealed_tag{});
|
||||
} else {
|
||||
co_await create_links_common(sst, snapshot_dir, std::move(gen));
|
||||
}
|
||||
co_await create_links_common(sst, snapshot_dir.native(), sst._generation, link_mode::default_mode);
|
||||
}
|
||||
future<> filesystem_storage::clone(const sstable& sst, generation_type gen, bool leave_unsealed) const {
|
||||
co_await create_links_common(sst, _dir.path().native(), std::move(gen), leave_unsealed ? link_mode::leave_unsealed : link_mode::default_mode);
|
||||
}
|
||||
|
||||
future<> filesystem_storage::move(const sstable& sst, sstring new_dir, generation_type new_generation, delayed_commit_changes* delay_commit) {
|
||||
@@ -444,7 +421,7 @@ future<> filesystem_storage::move(const sstable& sst, sstring new_dir, generatio
|
||||
sstring old_dir = _dir.native();
|
||||
sstlog.debug("Moving {} old_generation={} to {} new_generation={} do_sync_dirs={}",
|
||||
sst.get_filename(), sst._generation, new_dir, new_generation, delay_commit == nullptr);
|
||||
co_await create_links_common(sst, new_dir, new_generation, mark_for_removal_tag{});
|
||||
co_await create_links_common(sst, new_dir, new_generation, link_mode::mark_for_removal);
|
||||
co_await change_dir(new_dir);
|
||||
generation_type old_generation = sst._generation;
|
||||
co_await coroutine::parallel_for_each(sst.all_components(), [&sst, old_generation, old_dir] (auto p) {
|
||||
@@ -629,7 +606,8 @@ public:
|
||||
{}
|
||||
|
||||
future<> seal(const sstable& sst) override;
|
||||
future<> snapshot(const sstable& sst, sstring dir, absolute_path abs, std::optional<generation_type>, storage::leave_unsealed) const override;
|
||||
future<> snapshot(const sstable& sst, sstring name) const override;
|
||||
future<> clone(const sstable& sst, generation_type gen, bool leave_unsealed) const override;
|
||||
future<> change_state(const sstable& sst, sstable_state state, generation_type generation, delayed_commit_changes* delay) override;
|
||||
// runs in async context
|
||||
void open(sstable& sst) override;
|
||||
@@ -846,11 +824,16 @@ future<> object_storage_base::unlink_component(const sstable& sst, component_typ
|
||||
}
|
||||
}
|
||||
|
||||
future<> object_storage_base::snapshot(const sstable& sst, sstring dir, absolute_path abs, std::optional<generation_type> gen, storage::leave_unsealed) const {
|
||||
future<> object_storage_base::snapshot(const sstable& sst, sstring name) const {
|
||||
on_internal_error(sstlog, "Snapshotting S3 objects not implemented");
|
||||
co_return;
|
||||
}
|
||||
|
||||
future<> object_storage_base::clone(const sstable& sst, generation_type gen, bool leave_unsealed) const {
|
||||
on_internal_error(sstlog, "Cloning S3 objects not implemented");
|
||||
co_return;
|
||||
}
|
||||
|
||||
std::unique_ptr<sstables::storage> make_storage(sstables_manager& manager, const data_dictionary::storage_options& s_opts, sstable_state state) {
|
||||
return std::visit(overloaded_functor {
|
||||
[state] (const data_dictionary::storage_options::local& loc) mutable -> std::unique_ptr<sstables::storage> {
|
||||
|
||||
@@ -95,12 +95,11 @@ class storage {
|
||||
public:
|
||||
virtual ~storage() {}
|
||||
|
||||
using absolute_path = bool_class<class absolute_path_tag>; // FIXME -- should go away eventually
|
||||
using sync_dir = bool_class<struct sync_dir_tag>; // meaningful only to filesystem storage
|
||||
using leave_unsealed = bool_class<struct leave_unsealed_tag>;
|
||||
|
||||
virtual future<> seal(const sstable& sst) = 0;
|
||||
virtual future<> snapshot(const sstable& sst, sstring dir, absolute_path abs, std::optional<generation_type> gen = {}, leave_unsealed lu = leave_unsealed::no) const = 0;
|
||||
virtual future<> snapshot(const sstable& sst, sstring name) const = 0;
|
||||
virtual future<> clone(const sstable& sst, generation_type gen, bool leave_unsealed) const = 0;
|
||||
virtual future<> change_state(const sstable& sst, sstable_state to, generation_type generation, delayed_commit_changes* delay) = 0;
|
||||
// runs in async context
|
||||
virtual void open(sstable& sst) = 0;
|
||||
|
||||
Reference in New Issue
Block a user