quorum_set/quorum/
both_quorums.rs1use std::collections::BTreeSet;
2use std::collections::btree_set;
3
4use crate::quorum::QuorumSet;
5#[cfg(doc)]
6use crate::verify_intersection;
7
8#[derive(Clone, Debug)]
17pub struct BothQuorums<R, W> {
18 read: R,
19 write: W,
20}
21
22impl<R, W> BothQuorums<R, W> {
23 pub fn new(read: R, write: W) -> Self {
25 Self { read, write }
26 }
27}
28
29impl<R, W> QuorumSet for BothQuorums<R, W>
30where
31 R: QuorumSet,
32 W: QuorumSet<Id = R::Id>,
33 R::Id: Ord,
34{
35 type Id = R::Id;
36 type Iter = btree_set::IntoIter<R::Id>;
37
38 fn is_quorum<'a, I>(&self, ids: I) -> bool
39 where
40 Self::Id: 'a,
41 I: Iterator<Item = &'a Self::Id> + Clone,
42 {
43 let is_read_quorum = self.read.is_quorum(ids.clone());
44 is_read_quorum && self.write.is_quorum(ids)
45 }
46
47 fn ids(&self) -> Self::Iter {
48 let mut ids = BTreeSet::new();
49 ids.extend(self.read.ids());
50 ids.extend(self.write.ids());
51 ids.into_iter()
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use std::collections::BTreeSet;
58
59 use maplit::btreeset;
60
61 use super::BothQuorums;
62 use crate::Node;
63 use crate::QuorumTree;
64 use crate::quorum::QuorumSet;
65 use crate::quorum::verify_intersection;
66
67 #[test]
70 fn test_grid_rows_and_columns() -> anyhow::Result<()> {
71 let read = QuorumTree::new(1, [
72 Node::Subtree(QuorumTree::new(2, [Node::Id(1), Node::Id(2)])?),
73 Node::Subtree(QuorumTree::new(2, [Node::Id(3), Node::Id(4)])?),
74 ])?;
75 let write = QuorumTree::new(1, [
76 Node::Subtree(QuorumTree::new(2, [Node::Id(1), Node::Id(3)])?),
77 Node::Subtree(QuorumTree::new(2, [Node::Id(2), Node::Id(4)])?),
78 ])?;
79 assert!(!verify_intersection(&read, &read));
80 assert!(verify_intersection(&read, &write));
81
82 let both = BothQuorums::new(read, write);
83
84 let mut accepted = vec![];
85 for mask in 0..16_u64 {
86 let ids = (1..=4).filter(|id| mask & (1 << (id - 1)) != 0);
87 let ids = ids.collect::<BTreeSet<u64>>();
88 let is_quorum = both.is_quorum(ids.iter());
89 if is_quorum {
90 accepted.push(ids);
91 }
92 }
93 let want = vec![
94 btreeset! {1,2,3},
95 btreeset! {1,2,4},
96 btreeset! {1,3,4},
97 btreeset! {2,3,4},
98 btreeset! {1,2,3,4},
99 ];
100 assert_eq!(want, accepted);
101
102 assert!(verify_intersection(&both, &both));
103
104 Ok(())
105 }
106
107 #[test]
109 fn test_ids_are_union_of_read_and_write_ids() -> anyhow::Result<()> {
110 let read = btreeset! {1u64, 2, 3};
111 let write = QuorumTree::new(2, [Node::Id(3), Node::Id(4), Node::Id(5)])?;
112 let both = BothQuorums::new(read, write);
113
114 let ids = both.ids().collect::<Vec<_>>();
115 assert_eq!(vec![1, 2, 3, 4, 5], ids);
116
117 Ok(())
118 }
119}