/* * Copyright (C) 2019 ScyllaDB * * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #pragma once #include "compaction_strategy_impl.hh" class incremental_backlog_tracker; namespace sstables { class incremental_compaction_strategy_options { public: static constexpr uint64_t DEFAULT_MIN_SSTABLE_SIZE = 50L * 1024L * 1024L; static constexpr double DEFAULT_BUCKET_LOW = 0.5; static constexpr double DEFAULT_BUCKET_HIGH = 1.5; static constexpr auto MIN_SSTABLE_SIZE_KEY = "min_sstable_size"; static constexpr auto BUCKET_LOW_KEY = "bucket_low"; static constexpr auto BUCKET_HIGH_KEY = "bucket_high"; private: uint64_t min_sstable_size = DEFAULT_MIN_SSTABLE_SIZE; double bucket_low = DEFAULT_BUCKET_LOW; double bucket_high = DEFAULT_BUCKET_HIGH; public: incremental_compaction_strategy_options(const std::map& options); incremental_compaction_strategy_options() { min_sstable_size = DEFAULT_MIN_SSTABLE_SIZE; bucket_low = DEFAULT_BUCKET_LOW; bucket_high = DEFAULT_BUCKET_HIGH; } static void validate(const std::map& options, std::map& unchecked_options); friend class incremental_compaction_strategy; }; using sstable_run_and_length = std::pair; using sstable_run_bucket_and_length = std::pair, uint64_t>; class incremental_compaction_strategy : public compaction_strategy_impl { incremental_compaction_strategy_options _options; using size_bucket_t = std::vector; public: static constexpr int32_t DEFAULT_MAX_FRAGMENT_SIZE_IN_MB = 1000; static constexpr auto FRAGMENT_SIZE_OPTION = "sstable_size_in_mb"; static constexpr auto SPACE_AMPLIFICATION_GOAL_OPTION = "space_amplification_goal"; private: size_t _fragment_size = DEFAULT_MAX_FRAGMENT_SIZE_IN_MB*1024*1024; std::optional _space_amplification_goal; static std::vector create_run_and_length_pairs(const std::vector& runs); static std::vector> get_buckets(const std::vector& runs, const incremental_compaction_strategy_options& options); std::vector> get_buckets(const std::vector& runs) const { return get_buckets(runs, _options); } std::vector most_interesting_bucket(std::vector> buckets, size_t min_threshold, size_t max_threshold); uint64_t avg_size(std::vector& runs) const; static bool is_bucket_interesting(const std::vector& bucket, size_t min_threshold); bool is_any_bucket_interesting(const std::vector>& buckets, size_t min_threshold) const; compaction_descriptor find_garbage_collection_job(const table_state& t, std::vector& buckets); static std::vector runs_to_sstables(std::vector runs); static std::vector sstables_to_runs(std::vector sstables); static void sort_run_bucket_by_first_key(size_bucket_t& bucket, size_t max_elements, const schema_ptr& schema); public: incremental_compaction_strategy() = default; incremental_compaction_strategy(const std::map& options); static void validate_options(const std::map& options, std::map& unchecked_options); virtual compaction_descriptor get_sstables_for_compaction(table_state& t, strategy_control& control) override; virtual std::vector get_cleanup_compaction_jobs(table_state& t, std::vector candidates) const override; virtual compaction_descriptor get_major_compaction_job(table_state& t, std::vector candidates) override; virtual int64_t estimated_pending_compactions(table_state& t) const override; virtual compaction_strategy_type type() const override { return compaction_strategy_type::incremental; } virtual std::unique_ptr make_backlog_tracker() const override; virtual compaction_descriptor get_reshaping_job(std::vector input, schema_ptr schema, reshape_config cfg) const override; virtual std::unique_ptr make_sstable_set(const table_state& ts) const override; friend class ::incremental_backlog_tracker; }; }