| 127 | } |
| 128 | |
| 129 | fn truncate(&mut self, index: u64) -> nodedb_raft::error::Result<()> { |
| 130 | let write_txn = |
| 131 | self.db |
| 132 | .begin_write() |
| 133 | .map_err(|e| nodedb_raft::error::RaftError::Storage { |
| 134 | detail: format!("write txn: {e}"), |
| 135 | })?; |
| 136 | { |
| 137 | let mut table = write_txn.open_table(ENTRIES).map_err(|e| { |
| 138 | nodedb_raft::error::RaftError::Storage { |
| 139 | detail: format!("open entries: {e}"), |
| 140 | } |
| 141 | })?; |
| 142 | |
| 143 | // Collect keys >= index to remove. |
| 144 | let start = index_key(index); |
| 145 | let keys_to_remove: Vec<[u8; 8]> = table |
| 146 | .range(start.as_slice()..) |
| 147 | .map_err(|e| nodedb_raft::error::RaftError::Storage { |
| 148 | detail: format!("range: {e}"), |
| 149 | })? |
| 150 | .filter_map(|r| { |
| 151 | r.ok().map(|(k, _)| { |
| 152 | let mut buf = [0u8; 8]; |
| 153 | buf.copy_from_slice(k.value()); |
| 154 | buf |
| 155 | }) |
| 156 | }) |
| 157 | .collect(); |
| 158 | |
| 159 | for key in &keys_to_remove { |
| 160 | table.remove(key.as_slice()).map_err(|e| { |
| 161 | nodedb_raft::error::RaftError::Storage { |
| 162 | detail: format!("remove: {e}"), |
| 163 | } |
| 164 | })?; |
| 165 | } |
| 166 | } |
| 167 | write_txn |
| 168 | .commit() |
| 169 | .map_err(|e| nodedb_raft::error::RaftError::Storage { |
| 170 | detail: format!("commit truncate: {e}"), |
| 171 | })?; |
| 172 | |
| 173 | debug!(from_index = index, "raft log truncated"); |
| 174 | Ok(()) |
| 175 | } |
| 176 | |
| 177 | fn load_entries_after(&self, snapshot_index: u64) -> nodedb_raft::error::Result<Vec<LogEntry>> { |
| 178 | let read_txn = |