소스 검색

Define the storage interface.

Jing Yang 2 년 전
부모
커밋
b80f04d31a
2개의 변경된 파일105개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      src/lib.rs
  2. 104 0
      src/storage/mod.rs

+ 1 - 0
src/lib.rs

@@ -37,6 +37,7 @@ mod remote_peer;
 mod remote_raft;
 mod replicable_command;
 mod snapshot;
+pub mod storage;
 mod sync_log_entries;
 mod term_marker;
 pub mod utils;

+ 104 - 0
src/storage/mod.rs

@@ -0,0 +1,104 @@
+use crate::{Index, Term};
+
+/// A reference type that points to a Raft log entry. Used as input parameters
+/// in the storage interface `RaftStoragePersisterTrait`.
+/// This is to keep the implementation details of Raft log array separated from
+/// the public storage interface.
+pub trait RaftLogEntryRef {
+    fn index(&self) -> Index;
+    fn term(&self) -> Term;
+    fn command_bytes(&self) -> Vec<u8>;
+}
+
+/// An object that writes data to the underlying storage. A typical disk-based
+/// implementation can be implemented as follows:
+/// 1. A file large enough to store a few integers: term, ID of voted for peer,
+/// and a pair of disk offsets of valid log entries.
+/// 2. A list of continuous disk blocks used to store an array of
+/// `RaftStoredLogEntry` bytes.
+/// 3. Another list of continuous disk blocks that stores the application
+/// snapshot.
+///
+/// TODO: Add default index range check implementation to `append_one_entry()`
+/// and `append_entries()`.
+pub trait RaftStoragePersisterTrait<LogEntry: RaftLogEntryRef>:
+    Send + Sync + 'static
+{
+    /// Save the term and vote to storage.
+    fn save_term_vote(&self, term: Term, voted_for: String);
+
+    /// Append one entry to the saved log, overriding the existing entry at the
+    /// same index if it is previously appended. Any existing entries after the
+    /// give index are discarded.
+    fn append_one_entry(&self, entry: &LogEntry);
+
+    /// Append a list of entries to the saved log, overriding existing entries
+    /// at the same indexes if they are previously appended. The indexes
+    /// specified in the input list must be in order and consecutive. Existing
+    /// entries at indexes after the input index range are discarded.
+    fn append_entries<'a, LogEntryList>(&self, entries: LogEntryList)
+    where
+        LogEntry: 'a,
+        LogEntryList: IntoIterator<Item = &'a LogEntry>;
+
+    /// Store the application snapshot. The snapshot is computed from all log
+    /// entries at and before `index`. After the snapshot is saved, any log
+    /// entry on or before index can be discarded.
+    fn update_snapshot(&self, index: Index, snapshot: &[u8]);
+}
+
+/// An object that watches the underlying storage system and help Raft decide
+/// if a log compaction, i.e. taking a snapshot, is needed.
+pub trait RaftStorageMonitorTrait: Send + 'static {
+    /// Returns true when the storage system requires a log compaction.
+    fn should_compact_log_now(&self) -> bool;
+}
+
+/// A concrete type that holds one log entry read from the storage.
+#[derive(Clone)]
+pub struct RaftStoredLogEntry {
+    pub index: Index,
+    pub term: Term,
+    pub command: Vec<u8>,
+}
+
+/// A concrete type that holds all information that is needed to restore the
+/// Raft log array and application state right after the instance starts.
+#[derive(Clone)]
+pub struct RaftStoredState {
+    pub current_term: Term,
+    pub voted_for: String,
+    pub log: Vec<RaftStoredLogEntry>,
+    pub snapshot_index: Index,
+    pub snapshot: Vec<u8>,
+}
+
+/// An object that has everything Raft needs from a storage system.
+pub trait RaftStorageTrait {
+    type RaftStoragePersister<LogEntry: RaftLogEntryRef>: RaftStoragePersisterTrait<LogEntry>;
+    type RaftStorageMonitor: RaftStorageMonitorTrait;
+
+    /// Returns a persister that writes data to the underlying storage.
+    ///
+    /// `LogEntry` is not a trait generic parameter, but a method generic parameter,
+    /// because the implementation of this trait must accept any `RaftLogEntryRef`,
+    /// even though it is guaranteed that at runtime only one concrete subtype of
+    /// `RaftLogEntryRef` will be passed to the implementation.
+    fn persister<LogEntry: RaftLogEntryRef>(
+        self,
+    ) -> std::sync::Arc<Self::RaftStoragePersister<LogEntry>>;
+
+    /// Reads out the entire saved state, including term, vote, Raft logs and
+    /// the application snapshot.
+    fn read_state(&self) -> std::io::Result<RaftStoredState>;
+
+    /// Whether or not this storage system requires log compaction. Any
+    /// non-experimental storage must require log compaction.
+    fn log_compaction_required(&self) -> bool {
+        return true;
+    }
+
+    /// Returns a monitor that helps Raft decide when a compaction should happen
+    /// during the lifetime of the application.
+    fn monitor(&self) -> Self::RaftStorageMonitor;
+}