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
139#[derive(Copy, Clone)]
141pub struct Handle {
142 quorum_handle: u64,
143 model_data: ModelData,
144}
145
146pub fn initialize(model_data: &ModelData, context: u64) -> Result<(Handle, QuorumType)> {
150 let mut handle: ffi::quorum_handle_t = 0;
151 let mut quorum_type: u32 = 0;
152
153 let mut m = match model_data {
154 ModelData::ModelV1(_v1) => ffi::quorum_model_v1_data_t {
155 model: ffi::QUORUM_MODEL_V1,
156 quorum_notify_fn: Some(rust_quorum_notification_fn),
157 nodelist_notify_fn: Some(rust_nodelist_notification_fn),
158 },
159 _ => return Err(CsError::CsErrInvalidParam),
161 };
162
163 handle = unsafe {
164 let c_context: *mut c_void = &mut &context as *mut _ as *mut c_void;
165 let c_model: *mut ffi::quorum_model_data_t =
166 &mut m as *mut _ as *mut ffi::quorum_model_data_t;
167 let res = ffi::quorum_model_initialize(
168 &mut handle,
169 m.model,
170 c_model,
171 &mut quorum_type,
172 c_context,
173 );
174
175 if res == ffi::CS_OK {
176 handle
177 } else {
178 return Err(CsError::from_c(res));
179 }
180 };
181
182 let quorum_type = match quorum_type {
183 0 => QuorumType::Free,
184 1 => QuorumType::Set,
185 _ => QuorumType::Set,
186 };
187 let rhandle = Handle {
188 quorum_handle: handle,
189 model_data: *model_data,
190 };
191 HANDLE_HASH.lock().unwrap().insert(handle, rhandle);
192 Ok((rhandle, quorum_type))
193}
194
195pub fn finalize(handle: Handle) -> Result<()> {
197 let res = unsafe { ffi::quorum_finalize(handle.quorum_handle) };
198 if res == ffi::CS_OK {
199 HANDLE_HASH.lock().unwrap().remove(&handle.quorum_handle);
200 Ok(())
201 } else {
202 Err(CsError::from_c(res))
203 }
204}
205
206pub fn fd_get(handle: Handle) -> Result<i32> {
209 let c_fd: *mut c_int = &mut 0 as *mut _ as *mut c_int;
210 let res = unsafe { ffi::quorum_fd_get(handle.quorum_handle, c_fd) };
211 if res == ffi::CS_OK {
212 Ok(c_fd as i32)
213 } else {
214 Err(CsError::from_c(res))
215 }
216}
217
218pub fn dispatch(handle: Handle, flags: DispatchFlags) -> Result<()> {
220 let res = unsafe { ffi::quorum_dispatch(handle.quorum_handle, flags as u32) };
221 if res == ffi::CS_OK {
222 Ok(())
223 } else {
224 Err(CsError::from_c(res))
225 }
226}
227
228pub fn getquorate(handle: Handle) -> Result<bool> {
230 let c_quorate: *mut c_int = &mut 0 as *mut _ as *mut c_int;
231 let (res, r_quorate) = unsafe {
232 let res = ffi::quorum_getquorate(handle.quorum_handle, c_quorate);
233 let r_quorate: i32 = *c_quorate;
234 (res, r_quorate)
235 };
236 if res == ffi::CS_OK {
237 match r_quorate {
238 0 => Ok(false),
239 1 => Ok(true),
240 _ => Err(CsError::CsErrLibrary),
241 }
242 } else {
243 Err(CsError::from_c(res))
244 }
245}
246
247pub fn trackstart(handle: Handle, flags: TrackFlags) -> Result<()> {
249 let res = unsafe { ffi::quorum_trackstart(handle.quorum_handle, flags as u32) };
250 if res == ffi::CS_OK {
251 Ok(())
252 } else {
253 Err(CsError::from_c(res))
254 }
255}
256
257pub fn trackstop(handle: Handle) -> Result<()> {
259 let res = unsafe { ffi::quorum_trackstop(handle.quorum_handle) };
260 if res == ffi::CS_OK {
261 Ok(())
262 } else {
263 Err(CsError::from_c(res))
264 }
265}
266
267pub fn context_get(handle: Handle) -> Result<u64> {
271 let (res, context) = unsafe {
272 let mut context: u64 = 0;
273 let c_context: *mut c_void = &mut context as *mut _ as *mut c_void;
274 let r = ffi::quorum_context_get(handle.quorum_handle, c_context as *mut *const c_void);
275 (r, context)
276 };
277 if res == ffi::CS_OK {
278 Ok(context)
279 } else {
280 Err(CsError::from_c(res))
281 }
282}
283
284pub fn context_set(handle: Handle, context: u64) -> Result<()> {
289 let res = unsafe {
290 let c_context = context as *mut c_void;
291 ffi::quorum_context_set(handle.quorum_handle, c_context)
292 };
293 if res == ffi::CS_OK {
294 Ok(())
295 } else {
296 Err(CsError::from_c(res))
297 }
298}