sibyl/env.rs
1//! OCI environment
2
3#[cfg(feature="blocking")]
4#[cfg_attr(docsrs, doc(cfg(feature="blocking")))]
5mod blocking;
6
7#[cfg(feature="nonblocking")]
8#[cfg_attr(docsrs, doc(cfg(feature="nonblocking")))]
9mod nonblocking;
10
11use std::{ptr, sync::Arc};
12use crate::{Error, Result, oci::*, types::Ctx};
13
14/// Represents an OCI environment.
15pub struct Environment {
16 err: Handle<OCIError>,
17 // `OCIEnv` handle must be behind Arc as it needs to survive the Environment drop,
18 // so that `OCIEnv` is still available to async-drop used, for example, in `Session`.
19 env: Arc<Handle<OCIEnv>>,
20}
21
22impl AsRef<OCIEnv> for Environment {
23 fn as_ref(&self) -> &OCIEnv {
24 &*self.env
25 }
26}
27
28impl AsRef<OCIError> for Environment {
29 fn as_ref(&self) -> &OCIError {
30 &*self.err
31 }
32}
33
34impl Ctx for Environment {
35 fn try_as_session(&self) -> Option<&OCISession> {
36 None
37 }
38}
39
40impl Environment {
41 /**
42 Returns a new environment handle, which is then used by the OCI functions.
43
44 # Example
45
46 ```
47 use sibyl::Environment;
48
49 let oracle = Environment::new()?;
50
51 # Ok::<(),sibyl::Error>(())
52 ```
53 */
54 pub fn new() -> Result<Self> {
55 let mut env = Ptr::<OCIEnv>::null();
56 let res = unsafe {
57 OCIEnvNlsCreate(
58 env.as_mut_ptr(), OCI_OBJECT | OCI_THREADED,
59 ptr::null(), ptr::null(), ptr::null(), ptr::null(), 0, ptr::null(),
60 AL32UTF8, UTF8
61 )
62 };
63 if res != OCI_SUCCESS {
64 return Err( Error::new("Cannot create OCI environment") );
65 }
66 let env = Handle::from(env);
67 let err = Handle::<OCIError>::new(&env)?;
68 let env = Arc::new(env);
69 Ok(Self { env, err })
70 }
71
72 pub(crate) fn get_env(&self) -> Arc<Handle<OCIEnv>> {
73 self.env.clone()
74 }
75
76 fn get_attr<V: attr::AttrGet>(&self, attr_type: u32) -> Result<V> {
77 self.env.get_attr(attr_type, self.as_ref())
78 }
79
80 fn get_attr_into<V: attr::AttrGetInto>(&self, attr_type: u32, into: &mut V) -> Result<()> {
81 self.env.get_attr_into(attr_type, into, self.as_ref())
82 }
83
84 fn set_attr<V: attr::AttrSet>(&self, attr_type: u32, attr_val: V) -> Result<()> {
85 self.env.set_attr(attr_type, attr_val, self.as_ref())
86 }
87
88 /**
89 Returns the maximum size (high watermark) for the client-side object cache
90 as a percentage of the optimal size.
91
92 # Example
93
94 ```
95 let oracle = sibyl::env()?;
96
97 let max_size_percentage = oracle.max_cache_size()?;
98
99 assert_eq!(max_size_percentage, 10);
100 # Ok::<(),Box<dyn std::error::Error>>(())
101 ```
102 */
103 pub fn max_cache_size(&self) -> Result<u32> {
104 self.get_attr(OCI_ATTR_CACHE_MAX_SIZE)
105 }
106
107 /**
108 Sets the maximum size (high watermark) for the client-side object cache as a percentage
109 of the optimal size. Usually, you can set this value at 10%, the default, of the optimal size.
110 Setting this attribute to 0 results in a value of 10 being used. The object cache uses the
111 maximum and optimal values for freeing unused memory in the object cache.
112
113 If the memory occupied by the objects currently in the cache reaches or exceeds the maximum
114 cache size, the cache automatically begins to free (or ages out) unmarked objects that have
115 a pin count of zero. The cache continues freeing such objects until memory usage in the cache
116 reaches the optimal size, or until it runs out of objects eligible for freeing. Note that the
117 cache can grow beyond the specified maximum cache size.
118
119 The maximum object cache size (in bytes) is computed by incrementing `optimal_size` by the
120 `max_size_percentage`, using the following algorithm:
121
122 ```
123 # fn example(optimal_size: u32, max_size_percentage: u32) -> u32 {
124 let maximum_cache_size = optimal_size + optimal_size * max_size_percentage / 100;
125 # maximum_cache_size }
126 ```
127
128 # Parameters
129
130 * `size` - The maximum size for the client-side object cache as a oercentage of the cache optimal size.
131
132 # Example
133
134 ```
135 let oracle = sibyl::env()?;
136
137 oracle.set_cache_max_size(30)?;
138
139 let max_size_percentage = oracle.max_cache_size()?;
140 assert_eq!(max_size_percentage, 30);
141 # Ok::<(),Box<dyn std::error::Error>>(())
142 ```
143 */
144 pub fn set_cache_max_size(&self, size: u32) -> Result<()> {
145 self.set_attr(OCI_ATTR_CACHE_MAX_SIZE, size)
146 }
147
148 /**
149 Returns the optimal size for the client-side object cache in bytes.
150
151 # Example
152
153 ```
154 let oracle = sibyl::env()?;
155
156 let optimal_size = oracle.optimal_cache_size()?;
157
158 assert_eq!(optimal_size, 8*1024*1024);
159 # Ok::<(),Box<dyn std::error::Error>>(())
160 ```
161 */
162 pub fn optimal_cache_size(&self) -> Result<u32> {
163 self.get_attr(OCI_ATTR_CACHE_OPT_SIZE)
164 }
165
166 /**
167 Sets the optimal size for the client-side object cache in bytes. The default value is 8 megabytes (MB).
168 Setting this attribute to 0 results in a value of 8 MB being used.
169
170 # Parameters
171
172 * `size` - The optimal size of the client-side object cache in bytes
173
174 # Example
175
176 ```
177 let oracle = sibyl::env()?;
178
179 oracle.set_cache_opt_size(64*1024*1024)?;
180
181 let optimal_size = oracle.optimal_cache_size()?;
182 assert_eq!(optimal_size, 64*1024*1024);
183 # Ok::<(),Box<dyn std::error::Error>>(())
184 ```
185 */
186 pub fn set_cache_opt_size(&self, size: u32) -> Result<()> {
187 self.set_attr(OCI_ATTR_CACHE_OPT_SIZE, size)
188 }
189
190 /**
191 Returns the name of the language used for the database sessions created in the current environment.
192
193 See [Database Globalization Support Guide / Locale Data / Languages][1]
194
195 [1]: https://docs.oracle.com/en/database/oracle/oracle-database/19/nlspg/appendix-A-locale-data.html#GUID-D2FCFD55-EDC3-473F-9832-AAB564457830
196
197 # Example
198
199 ```
200 let oracle = sibyl::env()?;
201
202 let lang = oracle.nls_language()?;
203
204 assert_eq!(lang, "AMERICAN");
205 # Ok::<(),Box<dyn std::error::Error>>(())
206 ```
207 */
208 pub fn nls_language(&self) -> Result<String> {
209 let mut lang = String::with_capacity(32);
210 self.get_attr_into(OCI_ATTR_ENV_NLS_LANGUAGE, &mut lang)?;
211 Ok(lang)
212 }
213
214 /**
215 Sets the language used for the database sessions created in the current environment.
216
217 # Parameters
218
219 * `lang` - The name of the language used for the database sessions
220
221 # Example
222
223 ```
224 let oracle = sibyl::env()?;
225
226 oracle.set_nls_language("ENGLISH")?;
227
228 let lang = oracle.nls_language()?;
229 assert_eq!(lang, "ENGLISH");
230 # Ok::<(),Box<dyn std::error::Error>>(())
231 */
232 pub fn set_nls_language(&self, lang: &str) -> Result<()> {
233 self.set_attr(OCI_ATTR_ENV_NLS_LANGUAGE, lang)
234 }
235
236 /**
237 Returns the name of the territory used for the database sessions created in the current environment.
238
239 See [Database Globalization Support Guide / Locale Data / Territories][1]
240
241 [1]: https://docs.oracle.com/en/database/oracle/oracle-database/19/nlspg/appendix-A-locale-data.html#GUID-550D6A25-DB53-4911-9419-8065A73FFB06
242
243 # Example
244
245 ```
246 let oracle = sibyl::env()?;
247
248 let territory = oracle.nls_territory()?;
249
250 assert_eq!(territory, "AMERICA");
251 # Ok::<(),Box<dyn std::error::Error>>(())
252 ```
253 */
254 pub fn nls_territory(&self) -> Result<String> {
255 let mut territory = String::with_capacity(24);
256 self.get_attr_into(OCI_ATTR_ENV_NLS_TERRITORY, &mut territory)?;
257 Ok(territory)
258 }
259
260 /**
261 Sets the name of the territory used for the database sessions created in the current environment.
262
263 # Parameters
264
265 * `territory` - The name of the territory used for the database sessions
266
267 # Example
268
269 ```
270 let oracle = sibyl::env()?;
271 oracle.set_nls_territory("CANADA")?;
272 let territory = oracle.nls_territory()?;
273
274 assert_eq!(territory, "CANADA");
275 # Ok::<(),Box<dyn std::error::Error>>(())
276 ```
277 */
278 pub fn set_nls_territory(&self, territory: &str) -> Result<()> {
279 self.set_attr(OCI_ATTR_ENV_NLS_TERRITORY, territory)
280 }
281}