1#![allow(clippy::type_complexity)]
10#![allow(clippy::needless_range_loop)]
11#![allow(clippy::single_match)]
12
13use crate::sys::quorum as ffi;
15
16use crate::{CsError, DispatchFlags, NodeId, Result, TrackFlags};
17use std::collections::HashMap;
18use std::os::raw::{c_int, c_void};
19use std::slice;
20use std::sync::Mutex;
21
22#[derive(Copy, Clone)]
24pub enum ModelData {
25 ModelNone,
26 ModelV1(Model1Data),
27}
28
29pub enum QuorumType {
31 Free,
32 Set,
33}
34
35#[derive(Copy, Clone)]
37pub enum Model1Flags {
38 None,
39}
40
41pub struct RingId {
43 pub nodeid: NodeId,
44 pub seq: u64,
45}
46
47lazy_static! {
49 static ref HANDLE_HASH: Mutex<HashMap<u64, Handle>> = Mutex::new(HashMap::new());
50}
51
52fn list_to_vec(list_entries: u32, list: *const u32) -> Vec<NodeId> {
53 let mut r_member_list = Vec::<NodeId>::new();
54 let temp_members: &[u32] = unsafe { slice::from_raw_parts(list, list_entries as usize) };
55 for i in 0..list_entries as usize {
56 r_member_list.push(NodeId::from(temp_members[i]));
57 }
58 r_member_list
59}
60
61extern "C" fn rust_quorum_notification_fn(
63 handle: ffi::quorum_handle_t,
64 quorate: u32,
65 ring_id: ffi::quorum_ring_id,
66 member_list_entries: u32,
67 member_list: *const u32,
68) {
69 if let Some(h) = HANDLE_HASH.lock().unwrap().get(&handle) {
70 let r_ring_id = RingId {
71 nodeid: NodeId::from(ring_id.nodeid),
72 seq: ring_id.seq,
73 };
74 let r_member_list = list_to_vec(member_list_entries, member_list);
75 let r_quorate = match quorate {
76 0 => false,
77 1 => true,
78 _ => false,
79 };
80 match &h.model_data {
81 ModelData::ModelV1(md) => {
82 if let Some(cb) = md.quorum_notification_fn {
83 (cb)(h, r_quorate, r_ring_id, r_member_list);
84 }
85 }
86 _ => {}
87 }
88 }
89}
90
91extern "C" fn rust_nodelist_notification_fn(
92 handle: ffi::quorum_handle_t,
93 ring_id: ffi::quorum_ring_id,
94 member_list_entries: u32,
95 member_list: *const u32,
96 joined_list_entries: u32,
97 joined_list: *const u32,
98 left_list_entries: u32,
99 left_list: *const u32,
100) {
101 if let Some(h) = HANDLE_HASH.lock().unwrap().get(&handle) {
102 let r_ring_id = RingId {
103 nodeid: NodeId::from(ring_id.nodeid),
104 seq: ring_id.seq,
105 };
106
107 let r_member_list = list_to_vec(member_list_entries, member_list);
108 let r_joined_list = list_to_vec(joined_list_entries, joined_list);
109 let r_left_list = list_to_vec(left_list_entries, left_list);
110
111 match &h.model_data {
112 ModelData::ModelV1(md) => {
113 if let Some(cb) = md.nodelist_notification_fn {
114 (cb)(h, r_ring_id, r_member_list, r_joined_list, r_left_list);
115 }
116 }
117 _ => {}
118 }
119 }
120}
121
122#[derive(Copy, Clone)]
123pub struct Model1Data {
125 pub flags: Model1Flags,
126 pub quorum_notification_fn:
127 Option<fn(hande: &Handle, quorate: bool, ring_id: RingId, member_list: Vec<NodeId>)>,
128 pub nodelist_notification_fn: Option<
129 fn(
130 hande: &Handle,
131 ring_id: RingId,
132 member_list: Vec<NodeId>,
133 joined_list: Vec<NodeId>,
134 left_list: Vec<NodeId>,
135 ),
136 >,
137}
138
139pub struct Handle {
141 quorum_handle: u64,
142 model_data: ModelData,
143 clone: bool,
144}
145
146impl Clone for Handle {
147 fn clone(&self) -> Handle {
148 Handle {
149 quorum_handle: self.quorum_handle,
150 model_data: self.model_data,
151 clone: true,
152 }
153 }
154}
155
156impl Drop for Handle {
157 fn drop(self: &mut Handle) {
158 if !self.clone {
159 let _e = finalize(self);
160 }
161 }
162}
163
164impl PartialEq for Handle {
166 fn eq(&self, other: &Handle) -> bool {
167 self.quorum_handle == other.quorum_handle
168 }
169}
170
171pub fn initialize(model_data: &ModelData, context: u64) -> Result<(Handle, QuorumType)> {
175 let mut handle: ffi::quorum_handle_t = 0;
176 let mut quorum_type: u32 = 0;
177
178 let mut m = match model_data {
179 ModelData::ModelV1(_v1) => ffi::quorum_model_v1_data_t {
180 model: ffi::QUORUM_MODEL_V1,
181 quorum_notify_fn: Some(rust_quorum_notification_fn),
182 nodelist_notify_fn: Some(rust_nodelist_notification_fn),
183 },
184 _ => return Err(CsError::CsErrInvalidParam),
186 };
187
188 handle = unsafe {
189 let c_context: *mut c_void = &mut &context as *mut _ as *mut c_void;
190 let c_model: *mut ffi::quorum_model_data_t =
191 &mut m as *mut _ as *mut ffi::quorum_model_data_t;
192 let res = ffi::quorum_model_initialize(
193 &mut handle,
194 m.model,
195 c_model,
196 &mut quorum_type,
197 c_context,
198 );
199
200 if res == ffi::CS_OK {
201 handle
202 } else {
203 return Err(CsError::from_c(res));
204 }
205 };
206
207 let quorum_type = match quorum_type {
208 0 => QuorumType::Free,
209 1 => QuorumType::Set,
210 _ => QuorumType::Set,
211 };
212 let rhandle = Handle {
213 quorum_handle: handle,
214 model_data: *model_data,
215 clone: false,
216 };
217 HANDLE_HASH.lock().unwrap().insert(handle, rhandle.clone());
218 Ok((rhandle, quorum_type))
219}
220
221pub fn finalize(handle: &Handle) -> Result<()> {
223 let res = unsafe { ffi::quorum_finalize(handle.quorum_handle) };
224 if res == ffi::CS_OK {
225 HANDLE_HASH.lock().unwrap().remove(&handle.quorum_handle);
226 Ok(())
227 } else {
228 Err(CsError::from_c(res))
229 }
230}
231
232pub fn fd_get(handle: &Handle) -> Result<i32> {
235 let c_fd: *mut c_int = &mut 0 as *mut _ as *mut c_int;
236 let res = unsafe { ffi::quorum_fd_get(handle.quorum_handle, c_fd) };
237 if res == ffi::CS_OK {
238 Ok(unsafe { *c_fd })
239 } else {
240 Err(CsError::from_c(res))
241 }
242}
243
244pub fn dispatch(handle: &Handle, flags: DispatchFlags) -> Result<()> {
246 let res = unsafe { ffi::quorum_dispatch(handle.quorum_handle, flags as u32) };
247 if res == ffi::CS_OK {
248 Ok(())
249 } else {
250 Err(CsError::from_c(res))
251 }
252}
253
254pub fn getquorate(handle: &Handle) -> Result<bool> {
256 let c_quorate: *mut c_int = &mut 0 as *mut _ as *mut c_int;
257 let (res, r_quorate) = unsafe {
258 let res = ffi::quorum_getquorate(handle.quorum_handle, c_quorate);
259 let r_quorate: i32 = *c_quorate;
260 (res, r_quorate)
261 };
262 if res == ffi::CS_OK {
263 match r_quorate {
264 0 => Ok(false),
265 1 => Ok(true),
266 _ => Err(CsError::CsErrLibrary),
267 }
268 } else {
269 Err(CsError::from_c(res))
270 }
271}
272
273pub fn trackstart(handle: &Handle, flags: TrackFlags) -> Result<()> {
275 let res = unsafe { ffi::quorum_trackstart(handle.quorum_handle, flags as u32) };
276 if res == ffi::CS_OK {
277 Ok(())
278 } else {
279 Err(CsError::from_c(res))
280 }
281}
282
283pub fn trackstop(handle: &Handle) -> Result<()> {
285 let res = unsafe { ffi::quorum_trackstop(handle.quorum_handle) };
286 if res == ffi::CS_OK {
287 Ok(())
288 } else {
289 Err(CsError::from_c(res))
290 }
291}
292
293pub fn context_get(handle: &Handle) -> Result<u64> {
297 let (res, context) = unsafe {
298 let mut context: u64 = 0;
299 let c_context: *mut c_void = &mut context as *mut _ as *mut c_void;
300 let r = ffi::quorum_context_get(handle.quorum_handle, c_context as *mut *const c_void);
301 (r, context)
302 };
303 if res == ffi::CS_OK {
304 Ok(context)
305 } else {
306 Err(CsError::from_c(res))
307 }
308}
309
310pub fn context_set(handle: &Handle, context: u64) -> Result<()> {
315 let res = unsafe {
316 let c_context = context as *mut c_void;
317 ffi::quorum_context_set(handle.quorum_handle, c_context)
318 };
319 if res == ffi::CS_OK {
320 Ok(())
321 } else {
322 Err(CsError::from_c(res))
323 }
324}