ignite_rs/
lib.rs

1use crate::api::cache_config::{
2    CacheCreateWithConfigReq, CacheCreateWithNameReq, CacheDestroyReq, CacheGetConfigReq,
3    CacheGetConfigResp, CacheGetNamesReq, CacheGetNamesResp, CacheGetOrCreateWithConfigReq,
4    CacheGetOrCreateWithNameReq,
5};
6use crate::api::OpCode;
7
8use crate::cache::{Cache, CacheConfiguration};
9use crate::connection::Connection;
10use crate::error::IgniteResult;
11use crate::protocol::{read_wrapped_data, TypeCode};
12use crate::utils::string_to_java_hashcode;
13
14use std::io;
15use std::io::{Read, Write};
16use std::sync::Arc;
17
18#[cfg(feature = "ssl")]
19use rustls;
20use std::time::Duration;
21
22mod api;
23pub mod cache;
24mod connection;
25pub mod error;
26mod handshake;
27pub mod protocol;
28pub mod utils;
29
30/// Implementations of this trait could be serialized into Ignite byte sequence
31/// It is indented to be implemented by structs which represents requests
32pub(crate) trait WriteableReq {
33    fn write(&self, writer: &mut dyn Write) -> io::Result<()>;
34    fn size(&self) -> usize;
35}
36/// Implementations of this trait could be deserialized from Ignite byte sequence
37/// It is indented to be implemented by structs which represents requests. Acts as a closure
38/// for response handling
39pub(crate) trait ReadableReq: Sized {
40    fn read(reader: &mut impl Read) -> IgniteResult<Self>;
41}
42/// Indicates that a type could be used as cache key/value.
43/// Used alongside ReadableType
44pub trait WritableType {
45    fn write(&self, writer: &mut dyn Write) -> io::Result<()>;
46    fn size(&self) -> usize;
47}
48
49/// Indicates that a type could be used as cache key/value.
50/// Used alongside WritableType
51pub trait ReadableType: Sized {
52    fn read_unwrapped(type_code: TypeCode, reader: &mut impl Read) -> IgniteResult<Option<Self>>;
53    fn read(reader: &mut impl Read) -> IgniteResult<Option<Self>> {
54        read_wrapped_data(reader)
55    }
56}
57
58/// Combines the WritableType and ReadableType crates.
59/// Intended to be used in the #[derive(IgniteObj)] attribute to automatically generate
60/// serialization/deserialization for the user-defined structs
61///
62/// use ignite_rs_derive::IgniteObj;
63/// #[derive(IgniteObj)]
64/// struct MyType {
65///     bar: String,
66///     foo: i32,
67/// }
68pub trait IgniteObj: WritableType + ReadableType {}
69
70/// Ignite Client configuration.
71/// Allows the configuration of user's credentials, tcp configuration
72/// and SSL/TLS, if "ssl" feature is enabled
73#[derive(Clone)]
74pub struct ClientConfig {
75    pub addr: String,
76    pub username: Option<String>,
77    pub password: Option<String>,
78    pub tcp_nodelay: Option<bool>,
79    pub tcp_nonblocking: Option<bool>,
80    pub tcp_read_timeout: Option<Duration>,
81    pub tcp_write_timeout: Option<Duration>,
82    pub tcp_ttl: Option<u32>,
83    pub tcp_read_buff_size: Option<usize>,
84    pub tcp_write_buff_size: Option<usize>,
85    #[cfg(feature = "ssl")]
86    pub tls_conf: (rustls::ClientConfig, String),
87}
88
89impl ClientConfig {
90    #[cfg(not(feature = "ssl"))]
91    pub fn new(addr: &str) -> ClientConfig {
92        ClientConfig {
93            addr: addr.into(),
94            username: None,
95            password: None,
96            tcp_nodelay: None,
97            tcp_nonblocking: None,
98            tcp_read_timeout: None,
99            tcp_write_timeout: None,
100            tcp_ttl: None,
101            tcp_read_buff_size: None,
102            tcp_write_buff_size: None,
103        }
104    }
105
106    #[cfg(feature = "ssl")]
107    pub fn new(addr: &str, client_conf: rustls::ClientConfig, hostname: String) -> ClientConfig {
108        ClientConfig {
109            addr: addr.into(),
110            username: None,
111            password: None,
112            tcp_nodelay: None,
113            tcp_nonblocking: None,
114            tcp_read_timeout: None,
115            tcp_write_timeout: None,
116            tcp_ttl: None,
117            tcp_read_buff_size: None,
118            tcp_write_buff_size: None,
119            tls_conf: (client_conf, hostname),
120        }
121    }
122}
123
124/// Create new Ignite client using provided configuration
125/// Returned client has only one TCP connection with cluster
126pub fn new_client(conf: ClientConfig) -> IgniteResult<Client> {
127    Client::new(conf)
128}
129
130pub trait Ignite {
131    /// Returns names of caches currently available in cluster
132    fn get_cache_names(&mut self) -> IgniteResult<Vec<String>>;
133    /// Creates a new cache with provided name and default configuration.
134    /// Fails if cache with this name already exists
135    fn create_cache<K: WritableType + ReadableType, V: WritableType + ReadableType>(
136        &mut self,
137        name: &str,
138    ) -> IgniteResult<Cache<K, V>>;
139    /// Returns or creates a new cache with provided name and default configuration.
140    fn get_or_create_cache<K: WritableType + ReadableType, V: WritableType + ReadableType>(
141        &mut self,
142        name: &str,
143    ) -> IgniteResult<Cache<K, V>>;
144    /// Creates a new cache with provided configuration.
145    /// Fails if cache with this name already exists
146    fn create_cache_with_config<K: WritableType + ReadableType, V: WritableType + ReadableType>(
147        &mut self,
148        config: &CacheConfiguration,
149    ) -> IgniteResult<Cache<K, V>>;
150    /// Creates a new cache with provided configuration.
151    fn get_or_create_cache_with_config<
152        K: WritableType + ReadableType,
153        V: WritableType + ReadableType,
154    >(
155        &mut self,
156        config: &CacheConfiguration,
157    ) -> IgniteResult<Cache<K, V>>;
158    /// Returns a configuration of the requested cache.
159    /// Fails if there is no such cache
160    fn get_cache_config(&mut self, name: &str) -> IgniteResult<CacheConfiguration>;
161    /// Destroys the cache. All the data is removed.
162    fn destroy_cache(&mut self, name: &str) -> IgniteResult<()>;
163}
164
165/// Basic Ignite Client
166/// Uses single blocking TCP connection
167pub struct Client {
168    _conf: ClientConfig,
169    conn: Arc<Connection>,
170}
171
172impl Client {
173    fn new(conf: ClientConfig) -> IgniteResult<Client> {
174        // make connection
175        match Connection::new(&conf) {
176            Ok(conn) => {
177                let client = Client {
178                    _conf: conf,
179                    conn: Arc::new(conn),
180                };
181                Ok(client)
182            }
183            Err(err) => Err(err),
184        }
185    }
186}
187
188impl Ignite for Client {
189    fn get_cache_names(&mut self) -> IgniteResult<Vec<String>> {
190        let resp: CacheGetNamesResp = self
191            .conn
192            .send_and_read(OpCode::CacheGetNames, CacheGetNamesReq {})?;
193        Ok(resp.names)
194    }
195
196    fn create_cache<K: WritableType + ReadableType, V: WritableType + ReadableType>(
197        &mut self,
198        name: &str,
199    ) -> IgniteResult<Cache<K, V>> {
200        self.conn
201            .send(
202                OpCode::CacheCreateWithName,
203                CacheCreateWithNameReq::from(name),
204            )
205            .map(|_| {
206                Cache::new(
207                    string_to_java_hashcode(name),
208                    name.to_owned(),
209                    self.conn.clone(),
210                )
211            })
212    }
213
214    fn get_or_create_cache<K: WritableType + ReadableType, V: WritableType + ReadableType>(
215        &mut self,
216        name: &str,
217    ) -> IgniteResult<Cache<K, V>> {
218        self.conn
219            .send(
220                OpCode::CacheGetOrCreateWithName,
221                CacheGetOrCreateWithNameReq::from(name),
222            )
223            .map(|_| {
224                Cache::new(
225                    string_to_java_hashcode(name),
226                    name.to_owned(),
227                    self.conn.clone(),
228                )
229            })
230    }
231
232    fn create_cache_with_config<K: WritableType + ReadableType, V: WritableType + ReadableType>(
233        &mut self,
234        config: &CacheConfiguration,
235    ) -> IgniteResult<Cache<K, V>> {
236        self.conn
237            .send(
238                OpCode::CacheCreateWithConfiguration,
239                CacheCreateWithConfigReq { config },
240            )
241            .map(|_| {
242                Cache::new(
243                    string_to_java_hashcode(config.name.as_str()),
244                    config.name.clone(),
245                    self.conn.clone(),
246                )
247            })
248    }
249
250    fn get_or_create_cache_with_config<
251        K: WritableType + ReadableType,
252        V: WritableType + ReadableType,
253    >(
254        &mut self,
255        config: &CacheConfiguration,
256    ) -> IgniteResult<Cache<K, V>> {
257        self.conn
258            .send(
259                OpCode::CacheGetOrCreateWithConfiguration,
260                CacheGetOrCreateWithConfigReq { config },
261            )
262            .map(|_| {
263                Cache::new(
264                    string_to_java_hashcode(config.name.as_str()),
265                    config.name.clone(),
266                    self.conn.clone(),
267                )
268            })
269    }
270
271    fn get_cache_config(&mut self, name: &str) -> IgniteResult<CacheConfiguration> {
272        let resp: CacheGetConfigResp = self
273            .conn
274            .send_and_read(OpCode::CacheGetConfiguration, CacheGetConfigReq::from(name))?;
275        Ok(resp.config)
276    }
277
278    fn destroy_cache(&mut self, name: &str) -> IgniteResult<()> {
279        self.conn
280            .send(OpCode::CacheDestroy, CacheDestroyReq::from(name))
281    }
282}
283
284#[derive(Debug, Copy, Clone)]
285#[allow(dead_code)]
286///Value of an enumerable type. For such types defined only a finite number of named values.
287pub struct Enum {
288    /// Type id.
289    pub type_id: i32,
290    /// Enumeration value ordinal.
291    pub ordinal: i32,
292}