1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use std::borrow::Cow;
/// Driver and application self-identifying information,
/// to be sent in STARTUP message.
#[derive(Debug, Clone, Default)]
pub struct SelfIdentity<'id> {
/// Custom driver identity can be set if a custom driver build is running,
/// or an entirely different driver is operating on top of Rust driver
/// (e.g. cpp-rust-driver).
custom_driver_name: Option<Cow<'id, str>>,
/// Custom driver identity can be set if a custom driver build is running,
/// or an entirely different driver is operating on top of Rust driver
/// (e.g. cpp-rust-driver).
custom_driver_version: Option<Cow<'id, str>>,
// ### Q: Where do APPLICATION_NAME, APPLICATION_VERSION and CLIENT_ID come from?
// - there are no columns in system.clients dedicated to those attributes,
// - APPLICATION_NAME / APPLICATION_VERSION are not present in Scylla's source code at all,
// - only 2 results in Cassandra source is some example in docs:
// <https://github.com/apache/cassandra/blob/d3cbf9c1f72057d2a5da9df8ed567d20cd272931/doc/modules/cassandra/pages/managing/operating/virtualtables.adoc?plain=1#L218>.
// APPLICATION_NAME and APPLICATION_VERSION appears in client_options which
// is an arbitrary dict where client can send any keys.
// - driver variables are mentioned in protocol v5
// (<https://github.com/apache/cassandra/blob/d3cbf9c1f72057d2a5da9df8ed567d20cd272931/doc/native_protocol_v5.spec#L480>),
// application variables are not.
//
// ### A:
// The following options are not exposed anywhere in ScyllaDB tables.
// They come directly from CPP driver, and they are supported in Cassandra
//
// See <https://github.com/scylladb/cpp-driver/blob/fa0f27069a625057984d1fa58f434ea99b86c83f/include/cassandra.h#L2916>.
// As we want to support as big subset of its API as possible in cpp-rust-driver, I decided to expose API for setting
// those particular key-value pairs, similarly to what cpp-driver does, and not an API to set arbitrary key-value pairs.
//
// Allowing users to set arbitrary options could break the driver by overwriting options that bear special meaning,
// e.g. the shard-aware port. Therefore, I'm against such liberal API. OTOH, we need to expose APPLICATION_NAME,
// APPLICATION_VERSION and CLIENT_ID for cpp-rust-driver.
/// Application identity can be set to distinguish different applications
/// connected to the same cluster.
application_name: Option<Cow<'id, str>>,
/// Application identity can be set to distinguish different applications
/// connected to the same cluster.
application_version: Option<Cow<'id, str>>,
/// A (unique) client ID can be set to distinguish different instances
/// of the same application connected to the same cluster.
client_id: Option<Cow<'id, str>>,
}
impl<'id> SelfIdentity<'id> {
/// Creates a new empty instance of [`SelfIdentity`], which has all fields
/// set to `None`.
pub fn new() -> Self {
Self::default()
}
/// Advertises a custom driver name, which can be used if a custom driver build is running,
/// or an entirely different driver is operating on top of Rust driver
/// (e.g. cpp-rust-driver).
pub fn set_custom_driver_name(&mut self, custom_driver_name: impl Into<Cow<'id, str>>) {
self.custom_driver_name = Some(custom_driver_name.into());
}
/// Advertises a custom driver name. See [Self::set_custom_driver_name] for use cases.
pub fn with_custom_driver_name(mut self, custom_driver_name: impl Into<Cow<'id, str>>) -> Self {
self.custom_driver_name = Some(custom_driver_name.into());
self
}
/// Custom driver name to be advertised. See [Self::set_custom_driver_name] for use cases.
pub fn get_custom_driver_name(&self) -> Option<&str> {
self.custom_driver_name.as_deref()
}
/// Advertises a custom driver version. See [Self::set_custom_driver_name] for use cases.
pub fn set_custom_driver_version(&mut self, custom_driver_version: impl Into<Cow<'id, str>>) {
self.custom_driver_version = Some(custom_driver_version.into());
}
/// Advertises a custom driver version. See [Self::set_custom_driver_name] for use cases.
pub fn with_custom_driver_version(
mut self,
custom_driver_version: impl Into<Cow<'id, str>>,
) -> Self {
self.custom_driver_version = Some(custom_driver_version.into());
self
}
/// Custom driver version to be advertised. See [Self::set_custom_driver_version] for use cases.
pub fn get_custom_driver_version(&self) -> Option<&str> {
self.custom_driver_version.as_deref()
}
/// Advertises an application name, which can be used to distinguish different applications
/// connected to the same cluster.
pub fn set_application_name(&mut self, application_name: impl Into<Cow<'id, str>>) {
self.application_name = Some(application_name.into());
}
/// Advertises an application name. See [Self::set_application_name] for use cases.
pub fn with_application_name(mut self, application_name: impl Into<Cow<'id, str>>) -> Self {
self.application_name = Some(application_name.into());
self
}
/// Application name to be advertised. See [Self::set_application_name] for use cases.
pub fn get_application_name(&self) -> Option<&str> {
self.application_name.as_deref()
}
/// Advertises an application version. See [Self::set_application_name] for use cases.
pub fn set_application_version(&mut self, application_version: impl Into<Cow<'id, str>>) {
self.application_version = Some(application_version.into());
}
/// Advertises an application version. See [Self::set_application_name] for use cases.
pub fn with_application_version(
mut self,
application_version: impl Into<Cow<'id, str>>,
) -> Self {
self.application_version = Some(application_version.into());
self
}
/// Application version to be advertised. See [Self::set_application_version] for use cases.
pub fn get_application_version(&self) -> Option<&str> {
self.application_version.as_deref()
}
/// Advertises a client ID, which can be set to distinguish different instances
/// of the same application connected to the same cluster.
pub fn set_client_id(&mut self, client_id: impl Into<Cow<'id, str>>) {
self.client_id = Some(client_id.into());
}
/// Advertises a client ID. See [Self::set_client_id] for use cases.
pub fn with_client_id(mut self, client_id: impl Into<Cow<'id, str>>) -> Self {
self.client_id = Some(client_id.into());
self
}
/// Client ID to be advertised. See [Self::set_client_id] for use cases.
pub fn get_client_id(&self) -> Option<&str> {
self.client_id.as_deref()
}
}