Skip to content

Commit 3433126

Browse files
committed
Fix: compat07::SnapshotMeta should decode v08 SnapshotMeta
1 parent 04e4060 commit 3433126

File tree

13 files changed

+303
-196
lines changed

13 files changed

+303
-196
lines changed

.github/workflows/ci.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ jobs:
100100

101101
# - A store with defensive checks returns error when unexpected accesses are sent to RaftStore.
102102
# - Raft should not depend on defensive error to work correctly.
103-
- name: Unit Tests, with and without defensive store
103+
- name: Unit Tests
104104
uses: actions-rs/cargo@v1
105105
with:
106106
command: test

openraft/src/compat/compat07.rs

+53-183
Original file line numberDiff line numberDiff line change
@@ -68,189 +68,21 @@
6868
//! }
6969
//! ```
7070
71-
use std::collections::BTreeMap;
72-
use std::collections::BTreeSet;
73-
use std::fmt::Debug;
74-
75-
use crate::compat::Compat;
76-
use crate::compat::Upgrade;
77-
78-
impl Upgrade<crate::LogId<u64>> for or07::LogId {
79-
fn upgrade(self) -> crate::LogId<u64> {
80-
let committed_leader_id = crate::CommittedLeaderId::new(self.term, 0);
81-
crate::LogId::new(committed_leader_id, self.index)
82-
}
83-
}
84-
85-
impl Upgrade<crate::Membership<u64, crate::EmptyNode>> for or07::Membership {
86-
fn upgrade(self) -> crate::Membership<u64, crate::EmptyNode> {
87-
let configs = self.get_configs().clone();
88-
let nodes = self.all_nodes().iter().map(|nid| (*nid, crate::EmptyNode::new())).collect::<BTreeMap<_, _>>();
89-
crate::Membership::new(configs, nodes)
90-
}
91-
}
92-
93-
impl Upgrade<crate::StoredMembership<u64, crate::EmptyNode>> for or07::EffectiveMembership {
94-
fn upgrade(self) -> crate::StoredMembership<u64, crate::EmptyNode> {
95-
let membership = self.membership.upgrade();
96-
let log_id = self.log_id.upgrade();
97-
98-
crate::StoredMembership::new(Some(log_id), membership)
99-
}
100-
}
101-
102-
impl<C> Upgrade<crate::EntryPayload<C>> for or07::EntryPayload<C::D>
103-
where
104-
C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>,
105-
<C as crate::RaftTypeConfig>::D: or07::AppData + Debug,
106-
{
107-
fn upgrade(self) -> crate::EntryPayload<C> {
108-
match self {
109-
Self::Blank => crate::EntryPayload::Blank,
110-
Self::Membership(m) => crate::EntryPayload::Membership(m.upgrade()),
111-
Self::Normal(d) => crate::EntryPayload::Normal(d),
112-
}
113-
}
114-
}
115-
116-
impl<C> Upgrade<crate::Entry<C>> for or07::Entry<C::D>
117-
where
118-
C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>,
119-
<C as crate::RaftTypeConfig>::D: or07::AppData + Debug,
120-
{
121-
fn upgrade(self) -> crate::Entry<C> {
122-
let log_id = self.log_id.upgrade();
123-
let payload = self.payload.upgrade();
124-
crate::Entry { log_id, payload }
125-
}
126-
}
127-
128-
impl Upgrade<crate::Vote<u64>> for or07::HardState {
129-
fn upgrade(self) -> crate::Vote<u64> {
130-
// When it has not yet voted for any node, let it vote for any node won't break the consensus.
131-
crate::Vote::new(self.current_term, self.voted_for.unwrap_or_default())
132-
}
133-
}
134-
135-
impl Upgrade<crate::SnapshotMeta<u64, crate::EmptyNode>> for or07::SnapshotMeta {
136-
fn upgrade(self) -> crate::SnapshotMeta<u64, crate::EmptyNode> {
137-
unimplemented!("can not upgrade SnapshotMeta")
138-
}
139-
}
140-
141-
/// v0.7 compatible LogId.
142-
///
143-
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
144-
/// ```ignore
145-
/// let x:openraft::LogId = serde_json::from_slice::<compat07::LogId>(&serialized_bytes)?.upgrade()
146-
/// ```
147-
pub type LogId = Compat<or07::LogId, crate::LogId<u64>>;
148-
149-
/// v0.7 compatible Vote(in v0.7 the corresponding type is `HardState`).
150-
///
151-
/// To load from either v0.7 or the latest format data and upgrade it to latest type:
152-
/// ```ignore
153-
/// let x: openraft::Vote = serde_json::from_slice::<compat07::Vote>(&serialized_bytes)?.upgrade()
154-
/// ```
155-
pub type Vote = Compat<or07::HardState, crate::Vote<u64>>;
156-
157-
/// v0.7 compatible SnapshotMeta.
158-
///
159-
/// SnapshotMeta can not be upgraded, an old snapshot should be discarded and a new one should be
160-
/// re-built.
161-
pub type SnapshotMeta = Compat<or07::SnapshotMeta, crate::SnapshotMeta<u64, crate::EmptyNode>>;
162-
163-
/// v0.7 compatible Membership.
164-
///
165-
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
166-
/// ```ignore
167-
/// let x:openraft::Membership = serde_json::from_slice::<compat07::Membership>(&serialized_bytes)?.upgrade()
168-
/// ```
169-
#[derive(Debug, serde::Serialize, serde::Deserialize)]
170-
pub struct Membership {
171-
pub configs: Vec<BTreeSet<u64>>,
172-
pub nodes: Option<BTreeMap<u64, crate::EmptyNode>>,
173-
pub all_nodes: Option<BTreeSet<u64>>,
174-
}
175-
176-
impl Upgrade<crate::Membership<u64, crate::EmptyNode>> for Membership {
177-
fn upgrade(self) -> crate::Membership<u64, crate::EmptyNode> {
178-
if let Some(ns) = self.nodes {
179-
crate::Membership::new(self.configs, ns)
180-
} else {
181-
crate::Membership::new(self.configs, self.all_nodes.unwrap())
182-
}
183-
}
184-
}
185-
186-
/// v0.7 compatible StoredMembership.
187-
///
188-
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
189-
/// ```ignore
190-
/// let x:openraft::StoredMembership = serde_json::from_slice::<compat07::StoredMembership>(&serialized_bytes)?.upgrade()
191-
/// ```
192-
#[derive(Debug, serde::Serialize, serde::Deserialize)]
193-
pub struct StoredMembership {
194-
pub log_id: Option<LogId>,
195-
pub membership: Membership,
196-
#[serde(skip)]
197-
pub quorum_set: Option<()>,
198-
#[serde(skip)]
199-
pub voter_ids: Option<()>,
200-
}
201-
202-
impl Upgrade<crate::StoredMembership<u64, crate::EmptyNode>> for StoredMembership {
203-
fn upgrade(self) -> crate::StoredMembership<u64, crate::EmptyNode> {
204-
crate::StoredMembership::new(self.log_id.map(|lid| lid.upgrade()), self.membership.upgrade())
205-
}
206-
}
207-
208-
/// v0.7 compatible EntryPayload.
209-
///
210-
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
211-
/// ```ignore
212-
/// let x:openraft::EntryPayload = serde_json::from_slice::<compat07::EntryPayload>(&serialized_bytes)?.upgrade()
213-
/// ```
214-
#[derive(Debug, serde::Serialize, serde::Deserialize)]
215-
pub enum EntryPayload<C: crate::RaftTypeConfig> {
216-
Blank,
217-
Normal(C::D),
218-
Membership(Membership),
219-
}
220-
221-
impl<C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>> Upgrade<crate::EntryPayload<C>>
222-
for EntryPayload<C>
223-
{
224-
fn upgrade(self) -> crate::EntryPayload<C> {
225-
match self {
226-
EntryPayload::Blank => crate::EntryPayload::Blank,
227-
EntryPayload::Normal(d) => crate::EntryPayload::Normal(d),
228-
EntryPayload::Membership(m) => crate::EntryPayload::Membership(m.upgrade()),
229-
}
230-
}
231-
}
232-
233-
/// v0.7 compatible Entry.
234-
///
235-
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
236-
/// ```ignore
237-
/// let x:openraft::Entry = serde_json::from_slice::<compat07::Entry>(&serialized_bytes)?.upgrade()
238-
/// ```
239-
#[derive(serde::Serialize, serde::Deserialize)]
240-
#[serde(bound = "")]
241-
pub struct Entry<C: crate::RaftTypeConfig> {
242-
pub log_id: LogId,
243-
pub payload: EntryPayload<C>,
244-
}
245-
246-
impl<C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>> Upgrade<crate::Entry<C>> for Entry<C> {
247-
fn upgrade(self) -> crate::Entry<C> {
248-
crate::Entry {
249-
log_id: self.log_id.upgrade(),
250-
payload: self.payload.upgrade(),
251-
}
252-
}
253-
}
71+
mod entry;
72+
mod entry_payload;
73+
mod log_id;
74+
mod membership;
75+
mod snapshot_meta;
76+
mod stored_membership;
77+
mod vote;
78+
79+
pub use entry::Entry;
80+
pub use entry_payload::EntryPayload;
81+
pub use log_id::LogId;
82+
pub use membership::Membership;
83+
pub use snapshot_meta::SnapshotMeta;
84+
pub use stored_membership::StoredMembership;
85+
pub use vote::Vote;
25486

25587
pub mod testing {
25688
use std::path::Path;
@@ -818,4 +650,42 @@ mod tests {
818650
assert_eq!(serde_json::to_string(&want)?, serde_json::to_string(&c.upgrade())?);
819651
Ok(())
820652
}
653+
654+
#[test]
655+
fn test_serde_snapshot_meta() -> anyhow::Result<()> {
656+
use super::SnapshotMeta;
657+
658+
let m8 = || {
659+
crate::Membership::new(
660+
vec![btreeset! {1,2}],
661+
btreemap! {1=>crate::EmptyNode{}, 2=>crate::EmptyNode{}},
662+
)
663+
};
664+
let v7 = or07::SnapshotMeta {
665+
last_log_id: Some(or07::LogId::new(10, 5)),
666+
snapshot_id: "a".to_string(),
667+
};
668+
let want = crate::SnapshotMeta {
669+
last_log_id: Some(crate::LogId::new(crate::CommittedLeaderId::new(10, 0), 5)),
670+
last_membership: crate::StoredMembership::new(
671+
Some(crate::LogId::new(crate::CommittedLeaderId::new(10, 0), 5)),
672+
m8(),
673+
),
674+
snapshot_id: "a".to_string(),
675+
};
676+
677+
let s = serde_json::to_string(&v7)?;
678+
let c: SnapshotMeta = serde_json::from_str(&s)?;
679+
assert!(
680+
c.try_upgrade().is_err(),
681+
"snapshot_meta can not be upgrade because it has no membership"
682+
);
683+
684+
let s = serde_json::to_string(&want)?;
685+
let c: SnapshotMeta = serde_json::from_str(&s)?;
686+
let c = c.try_upgrade().unwrap();
687+
assert_eq!(serde_json::to_string(&want)?, serde_json::to_string(&c)?);
688+
689+
Ok(())
690+
}
821691
}

openraft/src/compat/compat07/entry.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use std::fmt::Debug;
2+
3+
use super::EntryPayload;
4+
use super::LogId;
5+
use crate::compat::Upgrade;
6+
7+
/// v0.7 compatible Entry.
8+
///
9+
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
10+
/// ```ignore
11+
/// let x:openraft::Entry = serde_json::from_slice::<compat07::Entry>(&serialized_bytes)?.upgrade()
12+
/// ```
13+
#[derive(serde::Serialize, serde::Deserialize)]
14+
#[serde(bound = "")]
15+
pub struct Entry<C: crate::RaftTypeConfig> {
16+
pub log_id: LogId,
17+
pub payload: EntryPayload<C>,
18+
}
19+
20+
impl<C> Upgrade<crate::Entry<C>> for or07::Entry<C::D>
21+
where
22+
C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>,
23+
<C as crate::RaftTypeConfig>::D: or07::AppData + Debug,
24+
{
25+
fn upgrade(self) -> crate::Entry<C> {
26+
let log_id = self.log_id.upgrade();
27+
let payload = self.payload.upgrade();
28+
crate::Entry { log_id, payload }
29+
}
30+
}
31+
32+
impl<C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>> Upgrade<crate::Entry<C>> for Entry<C> {
33+
fn upgrade(self) -> crate::Entry<C> {
34+
crate::Entry {
35+
log_id: self.log_id.upgrade(),
36+
payload: self.payload.upgrade(),
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use std::fmt::Debug;
2+
3+
use super::Membership;
4+
use crate::compat::Upgrade;
5+
6+
/// v0.7 compatible EntryPayload.
7+
///
8+
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
9+
/// ```ignore
10+
/// let x:openraft::EntryPayload = serde_json::from_slice::<compat07::EntryPayload>(&serialized_bytes)?.upgrade()
11+
/// ```
12+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
13+
pub enum EntryPayload<C: crate::RaftTypeConfig> {
14+
Blank,
15+
Normal(C::D),
16+
Membership(Membership),
17+
}
18+
19+
impl<C> Upgrade<crate::EntryPayload<C>> for or07::EntryPayload<C::D>
20+
where
21+
C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>,
22+
<C as crate::RaftTypeConfig>::D: or07::AppData + Debug,
23+
{
24+
fn upgrade(self) -> crate::EntryPayload<C> {
25+
match self {
26+
Self::Blank => crate::EntryPayload::Blank,
27+
Self::Membership(m) => crate::EntryPayload::Membership(m.upgrade()),
28+
Self::Normal(d) => crate::EntryPayload::Normal(d),
29+
}
30+
}
31+
}
32+
33+
impl<C: crate::RaftTypeConfig<NodeId = u64, Node = crate::EmptyNode>> Upgrade<crate::EntryPayload<C>>
34+
for EntryPayload<C>
35+
{
36+
fn upgrade(self) -> crate::EntryPayload<C> {
37+
match self {
38+
EntryPayload::Blank => crate::EntryPayload::Blank,
39+
EntryPayload::Normal(d) => crate::EntryPayload::Normal(d),
40+
EntryPayload::Membership(m) => crate::EntryPayload::Membership(m.upgrade()),
41+
}
42+
}
43+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use crate::compat::Compat;
2+
use crate::compat::Upgrade;
3+
4+
/// v0.7 compatible LogId.
5+
///
6+
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
7+
/// ```ignore
8+
/// let x:openraft::LogId = serde_json::from_slice::<compat07::LogId>(&serialized_bytes)?.upgrade()
9+
/// ```
10+
pub type LogId = Compat<or07::LogId, crate::LogId<u64>>;
11+
12+
impl Upgrade<crate::LogId<u64>> for or07::LogId {
13+
fn upgrade(self) -> crate::LogId<u64> {
14+
let committed_leader_id = crate::CommittedLeaderId::new(self.term, 0);
15+
crate::LogId::new(committed_leader_id, self.index)
16+
}
17+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::collections::BTreeMap;
2+
use std::collections::BTreeSet;
3+
use std::fmt::Debug;
4+
5+
use crate::compat::Upgrade;
6+
7+
/// v0.7 compatible Membership.
8+
///
9+
/// To load from either v0.7 or the latest format data and upgrade it to the latest type:
10+
/// ```ignore
11+
/// let x:openraft::Membership = serde_json::from_slice::<compat07::Membership>(&serialized_bytes)?.upgrade()
12+
/// ```
13+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
14+
pub struct Membership {
15+
pub configs: Vec<BTreeSet<u64>>,
16+
pub nodes: Option<BTreeMap<u64, crate::EmptyNode>>,
17+
pub all_nodes: Option<BTreeSet<u64>>,
18+
}
19+
20+
impl Upgrade<crate::Membership<u64, crate::EmptyNode>> for or07::Membership {
21+
fn upgrade(self) -> crate::Membership<u64, crate::EmptyNode> {
22+
let configs = self.get_configs().clone();
23+
let nodes = self.all_nodes().iter().map(|nid| (*nid, crate::EmptyNode::new())).collect::<BTreeMap<_, _>>();
24+
crate::Membership::new(configs, nodes)
25+
}
26+
}
27+
28+
impl Upgrade<crate::Membership<u64, crate::EmptyNode>> for Membership {
29+
fn upgrade(self) -> crate::Membership<u64, crate::EmptyNode> {
30+
if let Some(ns) = self.nodes {
31+
crate::Membership::new(self.configs, ns)
32+
} else {
33+
crate::Membership::new(self.configs, self.all_nodes.unwrap())
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)