openraft/quorum/
joint.rs

1use std::marker::PhantomData;
2
3use maplit::btreeset;
4
5use crate::quorum::QuorumSet;
6
7/// Use another data as a joint quorum set.
8///
9/// The ids has to be a quorum in every sub-config to constitute a joint-quorum.
10pub(crate) trait AsJoint<'d, ID, QS, D>
11where
12    ID: 'static,
13    QS: QuorumSet<ID>,
14{
15    fn as_joint(&'d self) -> Joint<ID, QS, D>
16    where D: 'd;
17}
18
19/// A wrapper that uses other data to define a joint quorum set.
20///
21/// The input ids has to be a quorum in every sub-config to constitute a joint-quorum.
22#[derive(Clone, Debug, Default)]
23#[derive(PartialEq, Eq)]
24#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
25pub(crate) struct Joint<ID, QS, D>
26where
27    ID: 'static,
28    QS: QuorumSet<ID>,
29{
30    data: D,
31    _p: PhantomData<(ID, QS)>,
32}
33
34impl<ID, QS, D> Joint<ID, QS, D>
35where
36    ID: 'static,
37    QS: QuorumSet<ID>,
38{
39    pub(crate) fn new(data: D) -> Self {
40        Self { data, _p: PhantomData }
41    }
42
43    pub(crate) fn children(&self) -> &D {
44        &self.data
45    }
46}
47
48/// Implement QuorumSet for `Joint<.., &[QS]>`
49impl<ID, QS> QuorumSet<ID> for Joint<ID, QS, &[QS]>
50where
51    ID: PartialOrd + Ord + 'static,
52    QS: QuorumSet<ID>,
53{
54    type Iter = std::collections::btree_set::IntoIter<ID>;
55
56    fn is_quorum<'a, I: Iterator<Item = &'a ID> + Clone>(&self, ids: I) -> bool {
57        for child in self.data.iter() {
58            if !child.is_quorum(ids.clone()) {
59                return false;
60            }
61        }
62        true
63    }
64
65    fn ids(&self) -> Self::Iter {
66        let mut ids = btreeset! {};
67        for child in self.data.iter() {
68            ids.extend(child.ids())
69        }
70        ids.into_iter()
71    }
72}
73
74/// Implement QuorumSet for `Joint<.., Vec<QS>>`
75impl<ID, QS> QuorumSet<ID> for Joint<ID, QS, Vec<QS>>
76where
77    ID: PartialOrd + Ord + 'static,
78    QS: QuorumSet<ID>,
79{
80    type Iter = std::collections::btree_set::IntoIter<ID>;
81
82    fn is_quorum<'a, I: Iterator<Item = &'a ID> + Clone>(&self, ids: I) -> bool {
83        for child in self.data.iter() {
84            if !child.is_quorum(ids.clone()) {
85                return false;
86            }
87        }
88        true
89    }
90
91    fn ids(&self) -> Self::Iter {
92        let mut ids = btreeset! {};
93        for child in self.data.iter() {
94            ids.extend(child.ids())
95        }
96        ids.into_iter()
97    }
98}