1#[cfg(feature = "statistics")]
2mod inner {
3 use std::sync::atomic::{AtomicU64, Ordering};
4 use std::fmt;
5
6 static OPEN_CONNECTIONS: AtomicU64 = AtomicU64::new(0);
8 static QUERIES_PREPARING: AtomicU64 = AtomicU64::new(0);
9 static QUERIES_EXECUTING: AtomicU64 = AtomicU64::new(0);
10 static QUERIES_FETCHING: AtomicU64 = AtomicU64::new(0);
11 static QUERIES_DONE: AtomicU64 = AtomicU64::new(0);
12 static QUERIES_FAILED: AtomicU64 = AtomicU64::new(0);
13
14 pub(super) fn open_connections_inc () {
15 OPEN_CONNECTIONS.fetch_add(1, Ordering::Relaxed);
16 }
17
18 pub(super) fn open_connections_dec() {
19 assert!(OPEN_CONNECTIONS.fetch_sub(1, Ordering::Relaxed) > 0);
20 }
21
22 pub(super) fn queries_preparing_inc() {
23 QUERIES_PREPARING.fetch_add(1, Ordering::Relaxed);
24 }
25
26 pub(super) fn queries_preparing_dec() {
27 assert!(QUERIES_PREPARING.fetch_sub(1, Ordering::Relaxed) > 0);
28 }
29
30 pub(super) fn queries_executing_inc() {
31 QUERIES_EXECUTING.fetch_add(1, Ordering::Relaxed);
32 }
33
34 pub(super) fn queries_executing_dec() {
35 assert!(QUERIES_EXECUTING.fetch_sub(1, Ordering::Relaxed) > 0);
36 }
37
38 pub(super) fn queries_fetching_inc() {
39 QUERIES_FETCHING.fetch_add(1, Ordering::Relaxed);
40 }
41
42 pub(super) fn queries_fetching_dec() {
43 assert!(QUERIES_FETCHING.fetch_sub(1, Ordering::Relaxed) > 0);
44 }
45
46 pub(super) fn queries_done_inc() {
47 QUERIES_DONE.fetch_add(1, Ordering::Relaxed);
48 }
49
50 pub(super) fn queries_failed_inc() {
51 QUERIES_FAILED.fetch_add(1, Ordering::Relaxed);
52 }
53
54 #[derive(Debug)]
55 pub struct Statistics {
56 pub open_connections: u64,
57 pub queries_preparing: u64,
58 pub queries_executing: u64,
59 pub queries_fetching: u64,
60 pub queries_done: u64,
61 pub queries_failed: u64,
62 }
63
64 impl fmt::Display for Statistics {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 write!(f, "ODBC statistics: connections: open: {open_connections}, queries: preparing: {queries_preparing}, executing: {queries_executing}, fetching: {queries_fetching}, done: {queries_done}, failed: {queries_failed}",
67 open_connections = self.open_connections,
68 queries_preparing = self.queries_preparing,
69 queries_executing = self.queries_executing,
70 queries_fetching = self.queries_fetching,
71 queries_done = self.queries_done,
72 queries_failed = self.queries_failed,
73 )
74 }
75 }
76
77 pub fn statistics() -> Statistics {
78 Statistics {
79 open_connections: OPEN_CONNECTIONS.load(Ordering::Relaxed),
80 queries_preparing: QUERIES_PREPARING.load(Ordering::Relaxed),
81 queries_executing: QUERIES_EXECUTING.load(Ordering::Relaxed),
82 queries_fetching: QUERIES_FETCHING.load(Ordering::Relaxed),
83 queries_done: QUERIES_DONE.load(Ordering::Relaxed),
84 queries_failed: QUERIES_FAILED.load(Ordering::Relaxed),
85 }
86 }
87}
88
89#[cfg(feature = "statistics")]
90pub use inner::statistics;
91
92pub(crate) struct ConnectionOpenGuard;
93
94impl ConnectionOpenGuard {
95 pub(crate) fn new() -> ConnectionOpenGuard {
96 #[cfg(feature = "statistics")]
97 inner::open_connections_inc();
98 ConnectionOpenGuard
99 }
100}
101
102impl Drop for ConnectionOpenGuard {
103 fn drop(&mut self) {
104 #[cfg(feature = "statistics")]
105 inner::open_connections_dec();
106 }
107}
108
109pub(crate) struct QueryPreparingGuard;
110
111impl QueryPreparingGuard {
112 pub(crate) fn new() -> QueryPreparingGuard {
113 #[cfg(feature = "statistics")]
114 inner::queries_preparing_inc();
115 QueryPreparingGuard
116 }
117}
118
119impl Drop for QueryPreparingGuard {
120 fn drop(&mut self) {
121 #[cfg(feature = "statistics")]
122 inner::queries_preparing_dec();
123 }
124}
125
126
127struct QueryExecutingGuard;
128
129impl QueryExecutingGuard {
130 fn new() -> QueryExecutingGuard {
131 #[cfg(feature = "statistics")]
132 inner::queries_executing_inc();
133 QueryExecutingGuard
134 }
135
136 fn failed(self) {
137 #[cfg(feature = "statistics")]
138 inner::queries_failed_inc();
139 }
140
141 fn fetching(self) -> QueryFetchingGuard {
142 QueryFetchingGuard::new()
143 }
144}
145
146#[cfg(feature = "statistics")]
147impl Drop for QueryExecutingGuard {
148 fn drop(&mut self) {
149 #[cfg(feature = "statistics")]
150 inner::queries_executing_dec();
151 }
152}
153
154pub(crate) struct QueryFetchingGuard;
155
156impl QueryFetchingGuard {
157 fn new() -> QueryFetchingGuard {
158 #[cfg(feature = "statistics")]
159 inner::queries_fetching_inc();
160 QueryFetchingGuard
161 }
162}
163
164#[cfg(feature = "statistics")]
165impl Drop for QueryFetchingGuard {
166 fn drop(&mut self) {
167 inner::queries_fetching_dec();
168 inner::queries_done_inc();
169 }
170}
171
172pub(crate) fn query_preparing<O, F>(f: F) -> O where F: FnOnce() -> O {
173 let bind = QueryPreparingGuard::new();
174 let ret = f();
175 drop(bind);
176 ret
177}
178
179pub(crate) fn query_execution<O, E, F>(f: F) -> Result<(O, QueryFetchingGuard), E> where F: FnOnce() -> Result<O, E> {
180 let exec = QueryExecutingGuard::new();
181 match f() {
182 Ok(o) => {
183
184 Ok((o, exec.fetching()))
185 }
186 Err(e) => {
187 exec.failed();
188 Err(e)
189 }
190 }
191}