diff --git a/Cargo.toml b/Cargo.toml index 2bcf7272..8e327026 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,13 +30,14 @@ fxhash = "0.2.1" fail = { version = "0.4", optional = true } getset = "0.1.1" protobuf = "2" -thiserror = "1.0" +thiserror = { version = "1.0", default-features = false } raft-proto = { path = "proto", version = "0.7.0", default-features = false } rand = "0.8" slog = "2.2" slog-envlogger = { version = "2.1.0", optional = true } slog-stdlog = { version = "4", optional = true } slog-term = { version = "2.4.0", optional = true } +spin = { version = "0.9.8" } [dev-dependencies] criterion = "0.3" diff --git a/src/confchange/changer.rs b/src/confchange/changer.rs index 32e23170..2609ea0e 100644 --- a/src/confchange/changer.rs +++ b/src/confchange/changer.rs @@ -1,5 +1,12 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. +extern crate alloc; + +use alloc::borrow::ToOwned; +use alloc::format; +use alloc::vec; +use alloc::vec::Vec; + use crate::eraftpb::{ConfChangeSingle, ConfChangeType}; use crate::tracker::{Configuration, ProgressMap, ProgressTracker}; use crate::{Error, Result}; @@ -114,7 +121,8 @@ impl Changer<'_> { cfg ))); } - cfg.learners.extend(cfg.learners_next.drain()); + cfg.learners.extend(cfg.learners_next.iter()); + cfg.learners_next.clear(); for id in &*cfg.voters.outgoing { if !cfg.voters.incoming.contains(id) && !cfg.learners.contains(id) { diff --git a/src/confchange/restore.rs b/src/confchange/restore.rs index 7dbb7f5d..de0fa3d0 100644 --- a/src/confchange/restore.rs +++ b/src/confchange/restore.rs @@ -3,6 +3,10 @@ // TODO: remove following line #![allow(dead_code)] +extern crate alloc; + +use alloc::vec::Vec; + use super::changer::Changer; use crate::eraftpb::{ConfChangeSingle, ConfChangeType, ConfState}; use crate::tracker::ProgressTracker; diff --git a/src/config.rs b/src/config.rs index 4d6aa73d..087f8dc5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,6 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +extern crate alloc; + +use alloc::borrow::ToOwned; +use alloc::format; + pub use super::read_only::{ReadOnlyOption, ReadState}; use super::util::NO_LIMIT; use super::{ diff --git a/src/errors.rs b/src/errors.rs index 599da8c1..4884cab0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,32 +1,28 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use thiserror::Error; +extern crate alloc; + +use alloc::string::String; +use core::fmt; /// The base error type for raft -#[derive(Debug, Error)] +#[derive(Debug)] pub enum Error { - /// An IO error occurred - #[error("{0}")] - Io(#[from] std::io::Error), + // /// An IO error occurred + // #[error("An io error occured")] + // Io(#[from] std::io::Error), /// A storage error occurred. - #[error("{0}")] - Store(#[from] StorageError), + Store(StorageError), /// Raft cannot step the local message. - #[error("raft: cannot step raft local message")] StepLocalMsg, /// The raft peer is not found and thus cannot step. - #[error("raft: cannot step as peer not found")] StepPeerNotFound, /// The proposal of changes was dropped. - #[error("raft: proposal dropped")] ProposalDropped, /// The configuration is invalid. - #[error("{0}")] ConfigInvalid(String), /// A protobuf message codec failed in some manner. - #[error("protobuf codec error {0:?}")] - CodecError(#[from] protobuf::ProtobufError), + CodecError(protobuf::ProtobufError), /// The node exists, but should not. - #[error("The node {id} already exists in the {set} set.")] Exists { /// The node id. id: u64, @@ -34,7 +30,6 @@ pub enum Error { set: &'static str, }, /// The node does not exist, but should. - #[error("The node {id} is not in the {set} set.")] NotExists { /// The node id. id: u64, @@ -42,13 +37,54 @@ pub enum Error { set: &'static str, }, /// ConfChange proposal is invalid. - #[error("{0}")] ConfChangeError(String), /// The request snapshot is dropped. - #[error("raft: request snapshot dropped")] RequestSnapshotDropped, } +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::Store(ref e) => write!(f, "{}", e), + Error::StepLocalMsg => write!(f, "raft: cannot step raft local message"), + Error::StepPeerNotFound => write!(f, "raft: cannot step as peer not found"), + Error::ProposalDropped => write!(f, "raft: proposal dropped"), + Error::ConfigInvalid(ref m) => write!(f, "{}", m), + Error::CodecError(ref e) => write!(f, "protobuf codec error {0:?}", e), + Error::Exists { id, set } => { + write!(f, "The node {id} already exists in the {set} set.") + } + Error::NotExists { id, set } => { + write!(f, "The node {id} is not in the {set} set.") + } + Error::ConfChangeError(ref m) => write!(f, "{}", m), + Error::RequestSnapshotDropped => write!(f, "raft: request snapshot dropped"), + } + } +} + +impl core::error::Error for Error { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + match *self { + Error::Store(ref e) => Some(e), + Error::CodecError(ref e) => Some(e), + _ => None, + } + } +} + +impl From for Error { + fn from(err: StorageError) -> Error { + Error::Store(err) + } +} + +impl From for Error { + fn from(err: protobuf::ProtobufError) -> Error { + Error::CodecError(err) + } +} + impl PartialEq for Error { #[cfg_attr(feature = "cargo-clippy", allow(clippy::match_same_arms))] fn eq(&self, other: &Error) -> bool { @@ -56,7 +92,7 @@ impl PartialEq for Error { (Error::StepPeerNotFound, Error::StepPeerNotFound) => true, (Error::ProposalDropped, Error::ProposalDropped) => true, (Error::Store(ref e1), Error::Store(ref e2)) => e1 == e2, - (Error::Io(ref e1), Error::Io(ref e2)) => e1.kind() == e2.kind(), + // (Error::Io(ref e1), Error::Io(ref e2)) => e1.kind() == e2.kind(), (Error::StepLocalMsg, Error::StepLocalMsg) => true, (Error::ConfigInvalid(ref e1), Error::ConfigInvalid(ref e2)) => e1 == e2, (Error::RequestSnapshotDropped, Error::RequestSnapshotDropped) => true, @@ -67,26 +103,43 @@ impl PartialEq for Error { } /// An error with the storage. -#[derive(Debug, Error)] +#[derive(Debug)] pub enum StorageError { /// The storage was compacted and not accessible - #[error("log compacted")] Compacted, /// The log is not available. - #[error("log unavailable")] Unavailable, /// The log is being fetched. - #[error("log is temporarily unavailable")] LogTemporarilyUnavailable, /// The snapshot is out of date. - #[error("snapshot out of date")] SnapshotOutOfDate, /// The snapshot is being created. - #[error("snapshot is temporarily unavailable")] SnapshotTemporarilyUnavailable, - /// Some other error occurred. - #[error("unknown error {0}")] - Other(#[from] Box), + // /// Some other error occurred. + // #[error("unknown error {0}")] + // Other(#[from] Box), +} + +impl fmt::Display for StorageError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + StorageError::Compacted => write!(f, "log compacted"), + StorageError::Unavailable => write!(f, "log unavailable"), + StorageError::LogTemporarilyUnavailable => write!(f, "log is temporarily unavailable"), + StorageError::SnapshotOutOfDate => write!(f, "snapshot out of date"), + StorageError::SnapshotTemporarilyUnavailable => { + write!(f, "snapshot is temporarily unavailable") + } + } + } +} + +impl core::error::Error for StorageError { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { + match *self { + _ => None, + } + } } impl PartialEq for StorageError { @@ -113,13 +166,13 @@ impl PartialEq for StorageError { } /// A result type that wraps up the raft errors. -pub type Result = std::result::Result; +pub type Result = core::result::Result; #[allow(clippy::eq_op)] #[cfg(test)] mod tests { use super::*; - use std::io; + // use std::io; #[test] fn test_error_equal() { @@ -128,14 +181,14 @@ mod tests { Error::Store(StorageError::Compacted), Error::Store(StorageError::Compacted) ); - assert_eq!( - Error::Io(io::Error::new(io::ErrorKind::UnexpectedEof, "oh no!")), - Error::Io(io::Error::new(io::ErrorKind::UnexpectedEof, "oh yes!")) - ); - assert_ne!( - Error::Io(io::Error::new(io::ErrorKind::NotFound, "error")), - Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "error")) - ); + // assert_eq!( + // Error::Io(io::Error::new(io::ErrorKind::UnexpectedEof, "oh no!")), + // Error::Io(io::Error::new(io::ErrorKind::UnexpectedEof, "oh yes!")) + // ); + // assert_ne!( + // Error::Io(io::Error::new(io::ErrorKind::NotFound, "error")), + // Error::Io(io::Error::new(io::ErrorKind::BrokenPipe, "error")) + // ); assert_eq!(Error::StepLocalMsg, Error::StepLocalMsg); assert_eq!( Error::ConfigInvalid(String::from("config error")), @@ -145,10 +198,10 @@ mod tests { Error::ConfigInvalid(String::from("config error")), Error::ConfigInvalid(String::from("other error")) ); - assert_eq!( - Error::from(io::Error::new(io::ErrorKind::Other, "oh no!")), - Error::from(io::Error::new(io::ErrorKind::Other, "oh yes!")) - ); + // assert_eq!( + // Error::from(io::Error::new(io::ErrorKind::Other, "oh no!")), + // Error::from(io::Error::new(io::ErrorKind::Other, "oh yes!")) + // ); assert_ne!( Error::StepPeerNotFound, Error::Store(StorageError::Compacted) @@ -168,9 +221,9 @@ mod tests { StorageError::SnapshotTemporarilyUnavailable ); assert_ne!(StorageError::Compacted, StorageError::Unavailable); - assert_ne!( - StorageError::Other(Box::new(StorageError::Unavailable)), - StorageError::Unavailable - ); + // assert_ne!( + // StorageError::Other(Box::new(StorageError::Unavailable)), + // StorageError::Unavailable + // ); } } diff --git a/src/lib.rs b/src/lib.rs index f0485042..ab4629d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -486,6 +486,10 @@ before taking old, removed peers offline. // We use `default` method a lot to be support prost and rust-protobuf at the // same time. And reassignment can be optimized by compiler. #![allow(clippy::field_reassign_with_default)] +#![cfg_attr(not(test), no_std)] +#![feature(error_in_core)] + +extern crate alloc; macro_rules! fatal { ($logger:expr, $msg:expr) => {{ @@ -574,31 +578,31 @@ pub mod prelude { /// Currently, this is a `log` adaptor behind a `Once` to ensure there is no clobbering. #[cfg(any(test, feature = "default-logger"))] pub fn default_logger() -> slog::Logger { - use slog::{o, Drain}; - use std::sync::{Mutex, Once}; - - static LOGGER_INITIALIZED: Once = Once::new(); - static mut LOGGER: Option = None; - - let logger = unsafe { - LOGGER_INITIALIZED.call_once(|| { - let decorator = slog_term::TermDecorator::new().build(); - let drain = slog_term::CompactFormat::new(decorator).build(); - let drain = slog_envlogger::new(drain); - LOGGER = Some(slog::Logger::root(Mutex::new(drain).fuse(), o!())); - }); - LOGGER.as_ref().unwrap() - }; - if let Some(case) = std::thread::current() - .name() - .and_then(|v| v.split(':').last()) - { - logger.new(o!("case" => case.to_string())) - } else { - logger.new(o!()) - } + use slog::o; + // use std::sync::{Mutex, Once}; + + // static LOGGER_INITIALIZED: Once = Once::new(); + // static mut LOGGER: Option = None; + + // let logger = unsafe { + // LOGGER_INITIALIZED.call_once(|| { + // let decorator = slog_term::TermDecorator::new().build(); + // let drain = slog_term::CompactFormat::new(decorator).build(); + // let drain = slog_envlogger::new(drain); + // LOGGER = Some(slog::Logger::root(Mutex::new(drain).fuse(), o!())); + // }); + // LOGGER.as_ref().unwrap() + // }; + // if let Some(case) = std::thread::current() + // .name() + // .and_then(|v| v.split(':').last()) + // { + // logger.new(o!("case" => case.to_string())) + // } else { + slog::Logger::root(slog::Discard, o!()) + // } } -type DefaultHashBuilder = std::hash::BuildHasherDefault; -type HashMap = std::collections::HashMap; -type HashSet = std::collections::HashSet; +// type DefaultHashBuilder = core::hash::BuildHasherDefault; +type HashMap = alloc::collections::btree_map::BTreeMap; +type HashSet = alloc::collections::btree_set::BTreeSet; diff --git a/src/log_unstable.rs b/src/log_unstable.rs index e27b9cf6..9645fa95 100644 --- a/src/log_unstable.rs +++ b/src/log_unstable.rs @@ -16,6 +16,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +extern crate alloc; + +use alloc::vec; +use alloc::vec::Vec; + use crate::eraftpb::{Entry, Snapshot}; use crate::util::entry_approximate_size; use slog::Logger; diff --git a/src/quorum.rs b/src/quorum.rs index 24c6d6a8..aa0ba20f 100644 --- a/src/quorum.rs +++ b/src/quorum.rs @@ -4,8 +4,10 @@ pub mod datadriven_test; pub mod joint; pub mod majority; -use std::collections::HashMap; -use std::fmt::{self, Debug, Display, Formatter}; +extern crate alloc; + +use alloc::collections::btree_map::BTreeMap; +use core::fmt::{self, Debug, Display, Formatter}; /// VoteResult indicates the outcome of a vote. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -64,7 +66,7 @@ pub trait AckedIndexer { fn acked_index(&self, voter_id: u64) -> Option; } -pub type AckIndexer = HashMap; +pub type AckIndexer = BTreeMap; impl AckedIndexer for AckIndexer { #[inline] diff --git a/src/quorum/joint.rs b/src/quorum/joint.rs index 679509f0..95eb34e0 100644 --- a/src/quorum/joint.rs +++ b/src/quorum/joint.rs @@ -1,10 +1,12 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. +extern crate alloc; + use super::{AckedIndexer, VoteResult}; use crate::util::Union; use crate::HashSet; use crate::MajorityConfig; -use std::cmp; +use core::cmp; /// A configuration of two groups of (possibly overlapping) majority configurations. /// Decisions require the support of both majorities. diff --git a/src/quorum/majority.rs b/src/quorum/majority.rs index 5fcd103e..d77c187f 100644 --- a/src/quorum/majority.rs +++ b/src/quorum/majority.rs @@ -1,13 +1,19 @@ // Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0. +extern crate alloc; + +use alloc::string::String; +use alloc::string::ToString; +use alloc::vec::Vec; + use super::{AckedIndexer, Index, VoteResult}; -use crate::{DefaultHashBuilder, HashSet}; +use crate::HashSet; -use std::collections::hash_set::Iter; -use std::fmt::Formatter; -use std::mem::MaybeUninit; -use std::ops::{Deref, DerefMut}; -use std::{cmp, slice, u64}; +use alloc::collections::btree_set::Iter; +use core::fmt::Formatter; +use core::mem::MaybeUninit; +use core::ops::{Deref, DerefMut}; +use core::{cmp, slice, u64}; /// A set of IDs that uses majority quorums to make decisions. #[derive(Clone, Debug, Default, PartialEq, Eq)] @@ -15,8 +21,8 @@ pub struct Configuration { voters: HashSet, } -impl std::fmt::Display for Configuration { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for Configuration { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { write!( f, "({})", @@ -38,7 +44,7 @@ impl Configuration { /// Creates an empty configuration with given capacity. pub fn with_capacity(cap: usize) -> Configuration { Configuration { - voters: HashSet::with_capacity_and_hasher(cap, DefaultHashBuilder::default()), + voters: HashSet::new(), } } @@ -169,7 +175,7 @@ impl Configuration { /// ``` #[cfg(test)] pub(crate) fn describe(&self, l: &impl AckedIndexer) -> String { - use std::fmt::Write; + use core::fmt::Write; let n = self.voters.len(); if n == 0 { diff --git a/src/raft.rs b/src/raft.rs index 5af1eca4..c4cd4590 100644 --- a/src/raft.rs +++ b/src/raft.rs @@ -14,9 +14,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::cmp; -use std::convert::TryFrom; -use std::ops::{Deref, DerefMut}; +extern crate alloc; + +use alloc::vec::Vec; + +use core::cmp; +use core::convert::TryFrom; +use core::ops::{Deref, DerefMut}; use crate::eraftpb::{ ConfChange, ConfChangeV2, ConfState, Entry, EntryType, HardState, Message, MessageType, @@ -874,7 +878,7 @@ impl Raft { pub fn inflight_buffers_size(&self) -> usize { let mut total_size = 0; for (_, pr) in self.prs().iter() { - total_size += pr.ins.buffer_capacity() * std::mem::size_of::(); + total_size += pr.ins.buffer_capacity() * core::mem::size_of::(); } total_size } diff --git a/src/raft_log.rs b/src/raft_log.rs index fcfcf32e..602c0497 100644 --- a/src/raft_log.rs +++ b/src/raft_log.rs @@ -14,7 +14,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::cmp; +extern crate alloc; + +use alloc::string::String; +use alloc::string::ToString; +use alloc::vec; +use alloc::vec::Vec; + +use alloc::format; +use core::cmp; use slog::warn; use slog::Logger; @@ -660,7 +668,7 @@ impl RaftLog { } } -#[cfg(test)] +#[cfg(all(test, std))] mod test { use std::{ cmp, diff --git a/src/raw_node.rs b/src/raw_node.rs index f88c3b3b..9b594ef1 100644 --- a/src/raw_node.rs +++ b/src/raw_node.rs @@ -20,7 +20,13 @@ //! nodes but not the raft consensus itself. Generally, you'll interact with the //! RawNode first and use it to access the inner workings of the consensus protocol. -use std::{collections::VecDeque, mem}; +extern crate alloc; + +use alloc::vec; +use alloc::vec::Vec; + +use alloc::collections::VecDeque; +use core::mem; use protobuf::Message as PbMessage; use raft_proto::ConfChangeI; diff --git a/src/read_only.rs b/src/read_only.rs index 6ae37282..e8c34a9d 100644 --- a/src/read_only.rs +++ b/src/read_only.rs @@ -14,7 +14,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::collections::VecDeque; +extern crate alloc; + +use alloc::collections::VecDeque; +use alloc::vec; +use alloc::vec::Vec; use slog::Logger; diff --git a/src/storage.rs b/src/storage.rs index ae58f566..d7e89524 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -20,8 +20,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::cmp; -use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; +extern crate alloc; + +use alloc::vec::Vec; + +use alloc::sync::Arc; //, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use core::cmp; +use spin; use crate::eraftpb::*; @@ -120,7 +125,7 @@ pub trait Storage { /// Storage should check context.can_async() first and decide whether to fetch entries asynchronously /// based on its own implementation. If the entries are fetched asynchronously, storage should return /// LogTemporarilyUnavailable, and application needs to call `on_entries_fetched(context)` to trigger - /// re-fetch of the entries after the storage finishes fetching the entries. + /// re-fetch of the entries after the storage finishes fetching the entries. /// /// # Panics /// @@ -379,7 +384,7 @@ impl MemStorageCore { /// in `MemStorage`. #[derive(Clone, Default)] pub struct MemStorage { - core: Arc>, + core: Arc>, } impl MemStorage { @@ -423,14 +428,14 @@ impl MemStorage { /// Opens up a read lock on the storage and returns a guard handle. Use this /// with functions that don't require mutation. - pub fn rl(&self) -> RwLockReadGuard<'_, MemStorageCore> { - self.core.read().unwrap() + pub fn rl(&self) -> spin::RwLockReadGuard<'_, MemStorageCore> { + self.core.read() } /// Opens up a write lock on the storage and returns guard handle. Use this /// with functions that take a mutable reference to self. - pub fn wl(&self) -> RwLockWriteGuard<'_, MemStorageCore> { - self.core.write().unwrap() + pub fn wl(&self) -> spin::RwLockWriteGuard<'_, MemStorageCore> { + self.core.write() } } diff --git a/src/tracker.rs b/src/tracker.rs index 4814d381..d09b51b2 100644 --- a/src/tracker.rs +++ b/src/tracker.rs @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +extern crate alloc; + mod inflights; mod progress; mod state; @@ -25,9 +27,9 @@ pub use self::state::ProgressState; use crate::confchange::{MapChange, MapChangeType}; use crate::eraftpb::ConfState; use crate::quorum::{AckedIndexer, Index, VoteResult}; -use crate::{DefaultHashBuilder, HashMap, HashSet, JointConfig}; +use crate::{HashMap, HashSet, JointConfig}; +use core::fmt::Debug; use getset::Getters; -use std::fmt::Debug; /// Config reflects the configuration tracked in a ProgressTracker. #[derive(Clone, Debug, Default, PartialEq, Eq, Getters)] @@ -90,8 +92,8 @@ pub struct Configuration { // Display and crate::itertools used only for test #[cfg(test)] -impl std::fmt::Display for Configuration { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for Configuration { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { use itertools::Itertools; if self.voters.outgoing.is_empty() { write!(f, "voters={}", self.voters.incoming)? @@ -149,7 +151,7 @@ impl Configuration { fn with_capacity(voters: usize, learners: usize) -> Self { Self { voters: JointConfig::with_capacity(voters), - learners: HashSet::with_capacity_and_hasher(learners, DefaultHashBuilder::default()), + learners: HashSet::new(), learners_next: HashSet::default(), auto_leave: false, } @@ -213,12 +215,9 @@ impl ProgressTracker { /// Create a progress set with the specified sizes already reserved. pub fn with_capacity(voters: usize, learners: usize, max_inflight: usize) -> Self { ProgressTracker { - progress: HashMap::with_capacity_and_hasher( - voters + learners, - DefaultHashBuilder::default(), - ), + progress: HashMap::new(), conf: Configuration::with_capacity(voters, learners), - votes: HashMap::with_capacity_and_hasher(voters, DefaultHashBuilder::default()), + votes: HashMap::new(), max_inflight, group_commit: false, } @@ -334,8 +333,7 @@ impl ProgressTracker { /// /// This should only be called by the leader. pub fn quorum_recently_active(&mut self, perspective_of: u64) -> bool { - let mut active = - HashSet::with_capacity_and_hasher(self.progress.len(), DefaultHashBuilder::default()); + let mut active = HashSet::new(); for (id, pr) in &mut self.progress { if *id == perspective_of { pr.recent_active = true; diff --git a/src/tracker/inflights.rs b/src/tracker/inflights.rs index 7b99e175..83e90ac8 100644 --- a/src/tracker/inflights.rs +++ b/src/tracker/inflights.rs @@ -13,8 +13,12 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +extern crate alloc; -use std::cmp::Ordering; +use alloc::vec; +use alloc::vec::Vec; + +use core::cmp::Ordering; /// A buffer of inflight messages. #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/src/tracker/progress.rs b/src/tracker/progress.rs index b154c577..7600ec2d 100644 --- a/src/tracker/progress.rs +++ b/src/tracker/progress.rs @@ -1,7 +1,9 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. +extern crate alloc; + use crate::{Inflights, ProgressState, INVALID_INDEX}; -use std::cmp; +use core::cmp; /// The progress of catching up from a restart. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/tracker/state.rs b/src/tracker/state.rs index 5c6b4d40..e063be06 100644 --- a/src/tracker/state.rs +++ b/src/tracker/state.rs @@ -14,8 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt; -use std::fmt::{Display, Formatter}; +use core::fmt; +use core::fmt::{Display, Formatter}; /// The state of the progress. #[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] diff --git a/src/util.rs b/src/util.rs index 9ad603d2..e8e133cf 100644 --- a/src/util.rs +++ b/src/util.rs @@ -3,9 +3,14 @@ // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. -use std::fmt; -use std::fmt::Write; -use std::u64; +extern crate alloc; + +use alloc::borrow::ToOwned; +use alloc::string::String; +use alloc::vec::Vec; +use core::fmt; +use core::fmt::Write; +use core::u64; use slog::{OwnedKVList, Record, KV};