log_array.rs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. use crate::index_term::IndexTerm;
  2. use crate::{Index, LogEntry, Term};
  3. /// A log array that stores a tail of the whole Raft log.
  4. ///
  5. /// The Raft log represented by the log array has length `end()`. Only log
  6. /// entries after `start()` are physically stored in the log array (with some
  7. /// caveats). The index and term of log entries in range `[start(), end())` are
  8. /// accessible. A snapshot is stored at the beginning of the log array, which
  9. /// covers all commands before and **including** `start()`. The command at
  10. /// `start()` is **not** accessible, but all commands after that are.
  11. ///
  12. /// New entries can be appended to the end of the Raft log via `add_command()`
  13. /// or `push()`.
  14. ///
  15. /// The log array can be truncated to at most one entry, which is at `start()`
  16. /// and contains the snapshot. The start of the log array can be shifted towards
  17. /// `end()`, if another snapshot at that position is provided.
  18. ///
  19. /// The log array can also be reset to a single entry, contains an index, a term
  20. /// and a snapshot, via `reset()`.
  21. ///
  22. /// The log array is guaranteed to have at least one element, containing an
  23. /// index, a term and a snapshot.
  24. ///
  25. /// All APIs **will** panic if the given index(es) are out of bound.
  26. ///
  27. /// NOT THREAD SAFE.
  28. #[derive(Clone, Serialize, Deserialize)]
  29. pub(crate) struct LogArray<C> {
  30. inner: Vec<LogEntry<C>>,
  31. snapshot: Vec<u8>,
  32. }
  33. #[derive(Debug)]
  34. pub(crate) enum ValidationError {
  35. IndexMismatch(Index, Vec<IndexTerm>),
  36. TermSpike(Index, Vec<IndexTerm>),
  37. FutureTerm(Term, Index, Vec<IndexTerm>),
  38. }
  39. impl<C: Default> LogArray<C> {
  40. /// Create the initial Raft log with no user-supplied commands.
  41. pub fn create() -> LogArray<C> {
  42. let ret = LogArray {
  43. inner: vec![Self::build_first_entry(0, Term(0))],
  44. snapshot: vec![],
  45. };
  46. ret.check_one_element();
  47. ret
  48. }
  49. }
  50. // Log accessors
  51. impl<C> LogArray<C> {
  52. /// The start of the stored log entries. The command at this index is no
  53. /// longer accessible, since it is included in the snapshot.
  54. pub fn start(&self) -> Index {
  55. self.first_entry().index
  56. }
  57. /// The end index of the Raft log.
  58. pub fn end(&self) -> usize {
  59. self.start() + self.inner.len()
  60. }
  61. /// The first index and term stored in this log array.
  62. pub fn first_index_term(&self) -> IndexTerm {
  63. self.first_entry().into()
  64. }
  65. /// The last index and term of the Raft log.
  66. pub fn last_index_term(&self) -> IndexTerm {
  67. self.last_entry().into()
  68. }
  69. /// The log entry at the given index.
  70. pub fn at(&self, index: Index) -> &LogEntry<C> {
  71. let index = self.check_at_index(index);
  72. &self.inner[index]
  73. }
  74. /// The first log entry on or after the given index.
  75. pub fn first_after(&self, index: Index) -> &LogEntry<C> {
  76. if index >= self.start() {
  77. self.at(index)
  78. } else {
  79. self.first_entry()
  80. }
  81. }
  82. /// All log entries after the given index.
  83. pub fn after(&self, index: Index) -> &[LogEntry<C>] {
  84. let index = self.check_range_index(index);
  85. &self.inner[index..]
  86. }
  87. /// All log entries in range [start, end).
  88. pub fn between(&self, start: Index, end: Index) -> &[LogEntry<C>] {
  89. let start = self.check_range_index(start);
  90. let end = self.check_range_index(end);
  91. &self.inner[start..end]
  92. }
  93. /// All log entries stored in the array.
  94. #[cfg(test)]
  95. pub fn all(&self) -> &[LogEntry<C>] {
  96. &self.inner[..]
  97. }
  98. /// `IndexTerm` of all log entries, without command.
  99. pub fn all_index_term(&self) -> Vec<IndexTerm> {
  100. self.inner.iter().map(|e| e.into()).collect()
  101. }
  102. /// The snapshot before and including `start()`.
  103. pub fn snapshot(&self) -> (IndexTerm, &[u8]) {
  104. (self.first_index_term(), &self.snapshot)
  105. }
  106. pub fn validate(&self, current_term: Term) -> Result<(), ValidationError> {
  107. let all_index_term = self.all_index_term();
  108. let (mut index, mut term) = all_index_term[0].clone().into();
  109. for entry in all_index_term[1..].iter() {
  110. index += 1;
  111. if entry.index != index {
  112. return Err(ValidationError::IndexMismatch(
  113. index,
  114. all_index_term,
  115. ));
  116. }
  117. if entry.term < term {
  118. return Err(ValidationError::TermSpike(index, all_index_term));
  119. }
  120. if entry.term > current_term {
  121. return Err(ValidationError::FutureTerm(
  122. current_term,
  123. index,
  124. all_index_term,
  125. ));
  126. }
  127. term = entry.term;
  128. }
  129. Ok(())
  130. }
  131. }
  132. // Mutations
  133. impl<C> LogArray<C> {
  134. /// Add a new entry to the Raft log, with term and command. The new index is
  135. /// returned.
  136. pub fn add_command(&mut self, term: Term, command: C) -> Index {
  137. let index = self.end();
  138. self.push(LogEntry {
  139. index,
  140. term,
  141. command,
  142. });
  143. index
  144. }
  145. /// Push a LogEntry into the Raft log. The index of the log entry must match
  146. /// the next index in the log.
  147. pub fn push(&mut self, log_entry: LogEntry<C>) {
  148. let index = log_entry.index;
  149. assert_eq!(index, self.end(), "Expecting new index to be exact at len");
  150. self.inner.push(log_entry);
  151. assert_eq!(
  152. index + 1,
  153. self.end(),
  154. "Expecting len increase by one after push",
  155. );
  156. assert_eq!(
  157. self.at(index).index,
  158. index,
  159. "Expecting pushed element to have the same index",
  160. );
  161. self.check_one_element();
  162. }
  163. /// Remove all log entries on and after `index`.
  164. pub fn truncate(&mut self, index: Index) {
  165. let index = self.check_middle_index(index);
  166. self.inner.truncate(index);
  167. self.check_one_element()
  168. }
  169. }
  170. impl<C: Default> LogArray<C> {
  171. /// Shift the start of the array to `index`, and store a new snapshot that
  172. /// covers all commands before and at `index`.
  173. pub fn shift(&mut self, index: Index, snapshot: Vec<u8>) {
  174. // Discard everything before index and store the snapshot.
  175. let offset = self.check_middle_index(index);
  176. // WARNING: Potentially all entries after offset would be copied.
  177. self.inner.drain(0..offset);
  178. self.snapshot = snapshot;
  179. // Override the first entry, we know there is at least one entry. This
  180. // is not strictly needed. One benefit is that the command can be
  181. // released after this point.
  182. let first = self.first_index_term();
  183. self.inner[0] = Self::build_first_entry(first.index, first.term);
  184. assert_eq!(
  185. first.index, index,
  186. "Expecting the first entry to have the same index."
  187. );
  188. self.check_one_element()
  189. }
  190. /// Reset the array to contain only one snapshot at the given `index` with
  191. /// the given `term`.
  192. pub fn reset(
  193. &mut self,
  194. index: Index,
  195. term: Term,
  196. snapshot: Vec<u8>,
  197. ) -> Vec<LogEntry<C>> {
  198. let mut inner = vec![Self::build_first_entry(index, term)];
  199. std::mem::swap(&mut inner, &mut self.inner);
  200. self.snapshot = snapshot;
  201. self.check_one_element();
  202. inner
  203. }
  204. }
  205. impl<C> LogArray<C> {
  206. fn first_entry(&self) -> &LogEntry<C> {
  207. self.inner
  208. .first()
  209. .expect("There must be at least one element in log")
  210. }
  211. fn last_entry(&self) -> &LogEntry<C> {
  212. &self
  213. .inner
  214. .last()
  215. .expect("There must be at least one entry in log")
  216. }
  217. fn offset(&self, index: Index) -> usize {
  218. index - self.start()
  219. }
  220. fn check_at_index(&self, index: Index) -> usize {
  221. assert!(
  222. index >= self.start() && index < self.end(),
  223. "Accessing start log index {} out of range [{}, {})",
  224. index,
  225. self.start(),
  226. self.end()
  227. );
  228. self.offset(index)
  229. }
  230. fn check_range_index(&self, index: Index) -> usize {
  231. assert!(
  232. index >= self.start() && index <= self.end(),
  233. "Accessing end log index {} out of range ({}, {}]",
  234. index,
  235. self.start(),
  236. self.end()
  237. );
  238. self.offset(index)
  239. }
  240. fn check_middle_index(&self, index: Index) -> usize {
  241. assert!(
  242. index > self.start() && index < self.end(),
  243. "Log index {} out of range ({}, {})",
  244. index,
  245. self.start(),
  246. self.end()
  247. );
  248. self.offset(index)
  249. }
  250. #[allow(clippy::len_zero)]
  251. fn check_one_element(&self) {
  252. assert!(
  253. self.inner.len() >= 1,
  254. "There must be at least one element in log"
  255. )
  256. }
  257. }
  258. impl<C: Default> LogArray<C> {
  259. fn build_first_entry(index: Index, term: Term) -> LogEntry<C> {
  260. LogEntry {
  261. index,
  262. term,
  263. command: C::default(),
  264. }
  265. }
  266. }
  267. #[cfg(test)]
  268. mod tests {
  269. use std::panic::catch_unwind;
  270. use super::*;
  271. impl<C> std::ops::Index<usize> for LogArray<C> {
  272. type Output = LogEntry<C>;
  273. fn index(&self, index: usize) -> &Self::Output {
  274. self.at(index)
  275. }
  276. }
  277. fn make_log_array(len: usize) -> LogArray<i32> {
  278. make_log_array_range(0, len)
  279. }
  280. fn make_log_array_range(start: usize, end: usize) -> LogArray<i32> {
  281. let mut ret = vec![];
  282. for i in start..end {
  283. ret.push(LogEntry {
  284. term: Term(i / 3),
  285. index: i,
  286. command: (end - i) as i32,
  287. })
  288. }
  289. LogArray {
  290. inner: ret,
  291. snapshot: vec![1, 2, 3],
  292. }
  293. }
  294. fn default_log_array() -> (usize, usize, LogArray<i32>) {
  295. (8, 17, make_log_array_range(8, 17))
  296. }
  297. #[test]
  298. fn test_create() {
  299. let log = LogArray::<i32>::create();
  300. log.check_one_element();
  301. assert_eq!(1, log.end());
  302. assert_eq!((0, Term(0)), log.first_index_term().into());
  303. assert_eq!(0, log[0].command);
  304. }
  305. // TODO(ditsing): add invariant checks to restore and write a test.
  306. #[test]
  307. fn test_restore() {}
  308. #[test]
  309. fn test_start() {
  310. let log = make_log_array_range(9, 17);
  311. assert_eq!(9, log.start());
  312. let log = make_log_array(9);
  313. assert_eq!(0, log.start());
  314. }
  315. #[test]
  316. fn test_end() {
  317. let log = make_log_array(7);
  318. assert_eq!(7, log.end());
  319. let log = make_log_array_range(8, 17);
  320. assert_eq!(17, log.end());
  321. }
  322. #[test]
  323. fn test_accessors() {
  324. let (start, end, log) = default_log_array();
  325. assert_eq!((start, Term(2)), log.first_index_term().into());
  326. assert_eq!((end - 1, Term(5)), log.last_index_term().into());
  327. assert_eq!(
  328. ((start, Term(2)).into(), [1, 2, 3].as_ref()),
  329. log.snapshot()
  330. );
  331. let all = log.all();
  332. assert_eq!(end - start, all.len());
  333. for i in start..end {
  334. assert_eq!(all[i - start].index, i);
  335. }
  336. }
  337. #[test]
  338. fn test_at() {
  339. let (start, end, log) = default_log_array();
  340. let last = log.at(end - 1);
  341. assert_eq!(end - 1, last.index);
  342. assert_eq!(5, last.term.0);
  343. assert_eq!(1, last.command);
  344. let first = log.at(start);
  345. assert_eq!(start, first.index);
  346. assert_eq!(2, first.term.0);
  347. assert_eq!(9, first.command);
  348. assert!(start < 12);
  349. assert!(end > 12);
  350. let middle = log.at(12);
  351. assert_eq!(12, middle.index);
  352. assert_eq!(4, middle.term.0);
  353. assert_eq!(5, middle.command);
  354. let at_before_start = catch_unwind(|| {
  355. log.at(start - 1);
  356. });
  357. assert!(at_before_start.is_err());
  358. let at_after_end = catch_unwind(|| {
  359. log.at(end);
  360. });
  361. assert!(at_after_end.is_err());
  362. }
  363. #[test]
  364. fn test_first_after() {
  365. let (start, _, log) = default_log_array();
  366. assert_eq!(log.first_after(0).index, log.first_entry().index);
  367. assert_eq!(log.first_after(start).index, log.at(start).index);
  368. assert_eq!(log.first_after(start + 1).index, log.at(start + 1).index);
  369. assert_ne!(log.first_after(0).index, log.first_after(start + 1).index);
  370. }
  371. #[test]
  372. fn test_index_operator() {
  373. let (start, end, log) = default_log_array();
  374. for i in start..end {
  375. assert_eq!(log[i].index, log.at(i).index);
  376. assert_eq!(log[i].term, log.at(i).term);
  377. assert_eq!(log[i].command, log.at(i).command);
  378. }
  379. assert!(catch_unwind(|| log[0].term).is_err());
  380. assert!(catch_unwind(|| log[20].term).is_err());
  381. }
  382. #[test]
  383. fn test_after() {
  384. let (start, end, log) = default_log_array();
  385. let offset = 12;
  386. assert!(offset > start);
  387. assert!(offset < end);
  388. let after = log.after(offset);
  389. assert_eq!(end - offset, after.len());
  390. for i in offset..end {
  391. assert_eq!(after[i - offset].index, i);
  392. assert_eq!(after[i - offset].term.0, i / 3);
  393. }
  394. assert!(catch_unwind(|| log.after(start - 1)).is_err());
  395. assert!(catch_unwind(|| log.after(start)).is_ok());
  396. assert!(catch_unwind(|| log.after(end)).is_ok());
  397. assert!(catch_unwind(|| log.after(end + 1)).is_err());
  398. }
  399. #[test]
  400. fn test_between() {
  401. let (start, end, log) = default_log_array();
  402. let between = log.between(start + 2, end);
  403. assert_eq!(end - start - 2, between.len());
  404. for i in start + 2..end {
  405. assert_eq!(between[i - start - 2].index, i);
  406. assert_eq!(between[i - start - 2].term.0, i / 3);
  407. }
  408. assert!(catch_unwind(|| log.between(start - 1, end)).is_err());
  409. assert!(catch_unwind(|| log.between(start + 2, end + 1)).is_err());
  410. assert!(catch_unwind(|| log.between(start, end)).is_ok());
  411. }
  412. #[test]
  413. fn test_add_command() {
  414. let (_, end, mut log) = default_log_array();
  415. let index = log.add_command(Term(8), 9);
  416. assert_eq!(8, log.at(index).term.0);
  417. assert_eq!(9, log.at(index).command);
  418. assert_eq!(index, end);
  419. assert_eq!(index + 1, log.end());
  420. }
  421. #[test]
  422. fn test_push() {
  423. let (_, end, mut log) = default_log_array();
  424. log.push(LogEntry {
  425. term: Term(8),
  426. index: end,
  427. command: 1,
  428. });
  429. assert_eq!(8, log.at(end).term.0);
  430. assert_eq!(1, log.at(end).command);
  431. assert_eq!(end + 1, log.end());
  432. }
  433. #[test]
  434. #[should_panic]
  435. fn test_push_small_index() {
  436. let (_, end, mut log) = default_log_array();
  437. log.push(LogEntry {
  438. term: Term(8),
  439. index: end - 1,
  440. command: 1,
  441. });
  442. }
  443. #[test]
  444. #[should_panic]
  445. fn test_push_big_index() {
  446. let (_, end, mut log) = default_log_array();
  447. log.push(LogEntry {
  448. term: Term(8),
  449. index: end + 1,
  450. command: 1,
  451. });
  452. }
  453. #[test]
  454. fn test_truncate() {
  455. let (start, _, mut log) = default_log_array();
  456. log.truncate(start + 5);
  457. assert_eq!(start + 5, log.end());
  458. for i in start..start + 5 {
  459. assert_eq!(log[i].index, i);
  460. assert_eq!(log[i].term.0, i / 3);
  461. }
  462. log.truncate(start + 1);
  463. assert_eq!(1, log.all().len());
  464. }
  465. #[test]
  466. #[should_panic]
  467. fn test_truncate_at_start() {
  468. let (start, _, mut log) = default_log_array();
  469. log.truncate(start);
  470. }
  471. #[test]
  472. #[should_panic]
  473. fn test_truncate_at_end() {
  474. let (_, end, mut log) = default_log_array();
  475. log.truncate(end);
  476. }
  477. #[test]
  478. #[should_panic]
  479. fn test_truncate_before_start() {
  480. let (start, _, mut log) = default_log_array();
  481. log.truncate(start - 1);
  482. }
  483. #[test]
  484. #[should_panic]
  485. fn test_truncate_after_end() {
  486. let (_, end, mut log) = default_log_array();
  487. log.truncate(end + 1);
  488. }
  489. #[test]
  490. fn test_shift() {
  491. let (start, end, mut log) = default_log_array();
  492. let offset = 10;
  493. assert!(offset > start);
  494. assert!(offset < end);
  495. log.shift(offset, vec![]);
  496. assert_eq!((offset, Term(3)), log.first_index_term().into());
  497. assert_eq!(0, log[offset].command);
  498. let all = log.all();
  499. assert_eq!(end - offset, all.len());
  500. for i in offset..end {
  501. assert_eq!(i, all[i - offset].index);
  502. assert_eq!(i / 3, all[i - offset].term.0);
  503. }
  504. assert_eq!(log.snapshot, vec![]);
  505. }
  506. #[test]
  507. #[should_panic]
  508. fn test_shift_before_start() {
  509. let (start, end, mut log) = default_log_array();
  510. assert!(start < end);
  511. log.shift(start - 1, vec![]);
  512. }
  513. #[test]
  514. #[should_panic]
  515. fn test_shift_at_start() {
  516. let (start, end, mut log) = default_log_array();
  517. assert!(start < end);
  518. log.shift(start, vec![]);
  519. }
  520. #[test]
  521. #[should_panic]
  522. fn test_shift_at_end() {
  523. let (start, end, mut log) = default_log_array();
  524. assert!(start < end);
  525. log.shift(end, vec![]);
  526. }
  527. #[test]
  528. #[should_panic]
  529. fn test_shift_after_end() {
  530. let (start, end, mut log) = default_log_array();
  531. assert!(start < end);
  532. log.shift(end + 1, vec![]);
  533. }
  534. #[test]
  535. fn test_reset() {
  536. let (start, end, mut log) = default_log_array();
  537. let dump = log.reset(88, Term(99), vec![1, 2]);
  538. assert_eq!(1, log.all().len());
  539. assert_eq!(vec![1, 2], log.snapshot);
  540. assert_eq!(88, log[88].index);
  541. assert_eq!(99, log[88].term.0);
  542. assert_eq!(0, log[88].command);
  543. assert_eq!(end - start, dump.len());
  544. }
  545. #[test]
  546. fn test_private_accessors() {
  547. let (start, end, log) = default_log_array();
  548. let first = log.first_entry();
  549. assert_eq!(start, first.index);
  550. assert_eq!(start / 3, first.term.0);
  551. let last = log.last_entry();
  552. assert_eq!(end - 1, last.index);
  553. assert_eq!((end - 1) / 3, last.term.0);
  554. assert_eq!(10 - start, log.offset(10));
  555. }
  556. #[test]
  557. fn test_check_start_index() {
  558. let (start, end, log) = default_log_array();
  559. assert!(start < end);
  560. assert!(catch_unwind(|| log.check_at_index(start - 8)).is_err());
  561. assert!(catch_unwind(|| log.check_at_index(start - 1)).is_err());
  562. assert!(catch_unwind(|| log.check_at_index(start)).is_ok());
  563. assert!(catch_unwind(|| log.check_at_index(start + 1)).is_ok());
  564. assert!(catch_unwind(|| log.check_at_index(end - 1)).is_ok());
  565. assert!(catch_unwind(|| log.check_at_index(end)).is_err());
  566. assert!(catch_unwind(|| log.check_at_index(end + 1)).is_err());
  567. assert!(catch_unwind(|| log.check_at_index(end + 5)).is_err());
  568. }
  569. #[test]
  570. fn test_check_range_index() {
  571. let (start, end, log) = default_log_array();
  572. assert!(start < end);
  573. assert!(catch_unwind(|| log.check_range_index(start - 8)).is_err());
  574. assert!(catch_unwind(|| log.check_range_index(start - 1)).is_err());
  575. assert!(catch_unwind(|| log.check_range_index(start)).is_ok());
  576. assert!(catch_unwind(|| log.check_range_index(start + 1)).is_ok());
  577. assert!(catch_unwind(|| log.check_range_index(end - 1)).is_ok());
  578. assert!(catch_unwind(|| log.check_range_index(end)).is_ok());
  579. assert!(catch_unwind(|| log.check_range_index(end + 1)).is_err());
  580. assert!(catch_unwind(|| log.check_range_index(end + 5)).is_err());
  581. }
  582. #[test]
  583. fn test_check_middle_index() {
  584. let (start, end, log) = default_log_array();
  585. assert!(start < end);
  586. assert!(catch_unwind(|| log.check_middle_index(start - 8)).is_err());
  587. assert!(catch_unwind(|| log.check_middle_index(start - 1)).is_err());
  588. assert!(catch_unwind(|| log.check_middle_index(start)).is_err());
  589. assert!(catch_unwind(|| log.check_middle_index(start + 1)).is_ok());
  590. assert!(catch_unwind(|| log.check_middle_index(end - 1)).is_ok());
  591. assert!(catch_unwind(|| log.check_middle_index(end)).is_err());
  592. assert!(catch_unwind(|| log.check_middle_index(end + 1)).is_err());
  593. assert!(catch_unwind(|| log.check_middle_index(end + 5)).is_err());
  594. }
  595. #[test]
  596. fn test_check_one_element() {
  597. let log = make_log_array(0);
  598. assert!(catch_unwind(|| log.check_one_element()).is_err());
  599. }
  600. #[test]
  601. fn test_integration_test() {
  602. let mut log = make_log_array(1);
  603. log.add_command(Term(3), 19);
  604. log.push(LogEntry {
  605. term: Term(3),
  606. index: 2,
  607. command: 3,
  608. });
  609. log.add_command(Term(4), 20);
  610. log.push(LogEntry {
  611. term: Term(4),
  612. index: 4,
  613. command: 7,
  614. });
  615. for i in 0..100 {
  616. log.add_command(Term(5), i);
  617. }
  618. assert_eq!(0, log.start());
  619. assert_eq!(105, log.end());
  620. assert_eq!((0, Term(0)), log.first_index_term().into());
  621. assert_eq!((104, Term(5)), log.last_index_term().into());
  622. assert_eq!(8, log.at(8).index);
  623. assert_eq!(5, log[8].term.0);
  624. assert_eq!(7, log[4].command);
  625. log.truncate(50);
  626. // End changed, start does not.
  627. assert_eq!(0, log.start());
  628. assert_eq!(50, log.end());
  629. assert_eq!((49, Term(5)), log.last_index_term().into());
  630. assert_eq!(49, log.at(49).index);
  631. assert_eq!(44, log[49].command);
  632. assert_eq!(5, log.at(5).term.0);
  633. // Cannot assert 50 is out of range. log is mut and cannot be used in
  634. // catch_unwind().
  635. // Snapshot is not changed.
  636. assert_eq!(((0, Term(0)).into(), [1, 2, 3].as_ref()), log.snapshot());
  637. log.shift(5, vec![]);
  638. // Start changed, end did not;
  639. assert_eq!(5, log.start());
  640. assert_eq!((5, Term(5)), log.first_index_term().into());
  641. assert_eq!(5, log.at(5).index);
  642. assert_eq!(5, log.at(5).term.0);
  643. // Cannot assert 4 is out of range. log is mut and cannot be used in
  644. // catch_unwind().
  645. // Snapshot is changed, too.
  646. assert_eq!(((5, Term(5)).into(), [].as_ref()), log.snapshot());
  647. // Ranged accessors.
  648. assert_eq!(45, log.all().len());
  649. assert_eq!(10, log.after(40).len());
  650. assert_eq!(20, log.between(20, 40).len());
  651. // Reset!
  652. log.reset(9, Term(7), vec![7, 8, 9]);
  653. assert_eq!(10, log.end());
  654. assert_eq!(1, log.all().len());
  655. assert_eq!(log.first_index_term(), log.last_index_term());
  656. assert_eq!(((9, Term(7)).into(), [7, 8, 9].as_ref()), log.snapshot());
  657. }
  658. #[test]
  659. fn test_validate_or_panic_current_term() {
  660. let log_array = make_log_array(7);
  661. let last_term = log_array.last_index_term().term.0;
  662. log_array
  663. .validate(Term(last_term))
  664. .expect("Validation should not fail");
  665. log_array
  666. .validate(Term(last_term + 1))
  667. .expect("Validation should not fail");
  668. let err = log_array
  669. .validate(Term(last_term - 1))
  670. .expect_err("Validation should have failed");
  671. assert!(matches!(
  672. err,
  673. ValidationError::FutureTerm(Term(_last_term), _, _)
  674. ));
  675. }
  676. #[test]
  677. fn test_validate_or_panic_increasing_term() {
  678. let mut log_array = make_log_array(7);
  679. let last_term = log_array.last_index_term().term.0;
  680. log_array
  681. .validate(Term(last_term + 1))
  682. .expect("Validation should not fail");
  683. log_array.inner[1].term = Term(last_term + 1);
  684. let err = log_array
  685. .validate(Term(last_term + 1))
  686. .expect_err("Validation should have failed");
  687. assert!(matches!(err, ValidationError::TermSpike(2, _)));
  688. }
  689. #[test]
  690. fn test_validate_or_panic_increasing_index() {
  691. let mut log_array = make_log_array_range(7, 10);
  692. let last_term = log_array.last_index_term().term.0;
  693. // OK
  694. log_array.inner[1].index = 8;
  695. log_array
  696. .validate(Term(last_term + 1))
  697. .expect("Validation should not fail");
  698. // Not 8, error
  699. log_array.inner[1].index = 7;
  700. let err = log_array
  701. .validate(Term(last_term + 1))
  702. .expect_err("Validation should have failed");
  703. assert!(matches!(err, ValidationError::IndexMismatch(8, _)));
  704. // Not 8, error
  705. log_array.inner[1].index = 9;
  706. let err = log_array
  707. .validate(Term(last_term + 1))
  708. .expect_err("Validation should have failed");
  709. assert!(matches!(err, ValidationError::IndexMismatch(8, _)));
  710. }
  711. }