diff --git a/alternator/server.cc b/alternator/server.cc index dfb00b50e8..05f1c70fba 100644 --- a/alternator/server.cc +++ b/alternator/server.cc @@ -708,8 +708,12 @@ future server::handle_api_request(std::unique_ptr // As long as the system_clients_entry object is alive, this request will // be visible in the "system.clients" virtual table. When requested, this // entry will be formatted by server::ongoing_request::make_client_data(). + auto user_agent_header = co_await _connection_options_keys_and_values.get_or_load(req->get_header("User-Agent"), [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); + auto system_clients_entry = _ongoing_requests.emplace( - req->get_client_address(), req->get_header("User-Agent"), + req->get_client_address(), std::move(user_agent_header), username, current_scheduling_group(), req->get_protocol_name() == "https"); diff --git a/alternator/server.hh b/alternator/server.hh index 15ff86e933..a98482985b 100644 --- a/alternator/server.hh +++ b/alternator/server.hh @@ -55,6 +55,7 @@ class server : public peering_sharded_service { // though it isn't really relevant for Alternator which defines its own // timeouts separately. We can create this object only once. updateable_timeout_config _timeout_config; + client_options_cache_type _connection_options_keys_and_values; alternator_callbacks_map _callbacks; @@ -88,7 +89,7 @@ class server : public peering_sharded_service { // is called when reading the "system.clients" virtual table. struct ongoing_request { socket_address _client_address; - sstring _user_agent; + client_options_cache_entry_type _user_agent; sstring _username; scheduling_group _scheduling_group; bool _is_https; diff --git a/client_data.hh b/client_data.hh index 73a0153cdf..cc13ddf5c8 100644 --- a/client_data.hh +++ b/client_data.hh @@ -53,8 +53,8 @@ struct client_data { client_connection_stage connection_stage = client_connection_stage::established; int32_t shard_id; /// ID of server-side shard which is processing the connection. - std::optional driver_name; - std::optional driver_version; + std::optional driver_name; + std::optional driver_version; std::optional hostname; std::optional protocol_version; std::optional ssl_cipher_suite; diff --git a/db/virtual_tables.cc b/db/virtual_tables.cc index d5d07bbf4a..6e9a592db1 100644 --- a/db/virtual_tables.cc +++ b/db/virtual_tables.cc @@ -835,10 +835,10 @@ class clients_table : public streaming_virtual_table { set_cell(cr.cells(), "shard_id", cd->shard_id); set_cell(cr.cells(), "connection_stage", cd->stage_str()); if (cd->driver_name) { - set_cell(cr.cells(), "driver_name", *cd->driver_name); + set_cell(cr.cells(), "driver_name", cd->driver_name->key()); } if (cd->driver_version) { - set_cell(cr.cells(), "driver_version", *cd->driver_version); + set_cell(cr.cells(), "driver_version", cd->driver_version->key()); } if (cd->hostname) { set_cell(cr.cells(), "hostname", *cd->hostname); diff --git a/service/client_state.hh b/service/client_state.hh index 95415779ab..a5c1ab9f0b 100644 --- a/service/client_state.hh +++ b/service/client_state.hh @@ -103,8 +103,8 @@ private: private volatile String keyspace; #endif std::optional _user; - std::optional _driver_name, _driver_version; - std::list _client_options; + std::optional _driver_name, _driver_version; + std::list _client_options; auth_state _auth_state = auth_state::UNINITIALIZED; bool _control_connection = false; @@ -153,11 +153,13 @@ public: return _control_connection = true; } - std::optional get_driver_name() const { + std::optional get_driver_name() const { return _driver_name; } - void set_driver_name(sstring driver_name) { - _driver_name = std::move(driver_name); + future<> set_driver_name(client_options_cache_type& keys_and_values_cache, const sstring& driver_name) { + _driver_name = co_await keys_and_values_cache.get_or_load(driver_name, [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); } const auto& get_client_options() const { @@ -168,11 +170,16 @@ public: client_options_cache_type& keys_and_values_cache, const std::unordered_map& client_options); - std::optional get_driver_version() const { + std::optional get_driver_version() const { return _driver_version; } - void set_driver_version(sstring driver_version) { - _driver_version = std::move(driver_version); + future<> set_driver_version( + client_options_cache_type& keys_and_values_cache, + const sstring& driver_version) + { + _driver_version = co_await keys_and_values_cache.get_or_load(driver_version, [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); } client_state(external_tag, diff --git a/transport/server.cc b/transport/server.cc index abef5794be..89f70e6702 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -959,10 +959,10 @@ future> cql_server::connection::process_st } if (auto driver_ver_opt = options.find("DRIVER_VERSION"); driver_ver_opt != options.end()) { - _client_state.set_driver_version(driver_ver_opt->second); + co_await _client_state.set_driver_version(_server._connection_options_keys_and_values, driver_ver_opt->second); } if (auto driver_name_opt = options.find("DRIVER_NAME"); driver_name_opt != options.end()) { - _client_state.set_driver_name(driver_name_opt->second); + co_await _client_state.set_driver_name(_server._connection_options_keys_and_values, driver_name_opt->second); } // Store all received client options for later exposure in the system.clients 'client_options' column