log_array.rs 21 KB

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