#pragma once #include #include #include #include #include #include namespace DB { class AccessControl; struct Quota; using QuotaPtr = std::shared_ptr; struct RolesOrUsersSet; /// Stores information how much amount of resources have been consumed and how much are left. class QuotaCache { public: explicit QuotaCache(const AccessControl & access_control_); ~QuotaCache(); std::shared_ptr getEnabledQuota( const UUID & user_id, const String & user_name, const boost::container::flat_set & enabled_roles, const Poco::Net::IPAddress & address, const String & forwarded_address, const String & client_key, bool throw_if_client_key_empty); std::vector getAllQuotasUsage() const; private: using Interval = EnabledQuota::Interval; using Intervals = EnabledQuota::Intervals; struct QuotaInfo { QuotaInfo(const QuotaPtr & quota_, const UUID & quota_id_) { setQuota(quota_, quota_id_); } void setQuota(const QuotaPtr & quota_, const UUID & quota_id_); String calculateKey(const EnabledQuota & enabled_quota, bool throw_if_client_key_empty) const; boost::shared_ptr getOrBuildIntervals(const String & key); boost::shared_ptr rebuildIntervals(const String & key, std::chrono::system_clock::time_point current_time); void rebuildAllIntervals(); QuotaPtr quota; UUID quota_id; const RolesOrUsersSet * roles = nullptr; std::unordered_map> key_to_intervals; }; void ensureAllQuotasRead(); void quotaAddedOrChanged(const UUID & quota_id, const std::shared_ptr & new_quota); void quotaRemoved(const UUID & quota_id); void chooseQuotaToConsume(); void chooseQuotaToConsumeFor(EnabledQuota & enabled_quota, bool throw_if_client_key_empty); const AccessControl & access_control; mutable std::mutex mutex; std::unordered_map all_quotas; bool all_quotas_read = false; scope_guard subscription; std::map> enabled_quotas; }; }