| 168 | } |
| 169 | |
| 170 | fn scan_from<'a>(&'a self, from: Hlc) -> ArrayResult<OpIter<'a>> { |
| 171 | let txn = self.db.begin_read().map_err(|e| ArrayError::InvalidOp { |
| 172 | detail: format!("scan_from begin_read: {e}"), |
| 173 | })?; |
| 174 | let table = txn |
| 175 | .open_table(ARRAY_OP_LOG) |
| 176 | .map_err(|e| ArrayError::InvalidOp { |
| 177 | detail: format!("scan_from open_table: {e}"), |
| 178 | })?; |
| 179 | |
| 180 | let mut results: Vec<ArrayOp> = Vec::new(); |
| 181 | let range = table.iter().map_err(|e| ArrayError::InvalidOp { |
| 182 | detail: format!("scan_from iter: {e}"), |
| 183 | })?; |
| 184 | for entry in range { |
| 185 | let (k, v) = entry.map_err(|e| ArrayError::InvalidOp { |
| 186 | detail: format!("scan_from entry: {e}"), |
| 187 | })?; |
| 188 | let key = k.value(); |
| 189 | // Any key shorter than 19 (1 len + at least 0 name + 18 hlc) is malformed. |
| 190 | if key.len() < 19 { |
| 191 | continue; |
| 192 | } |
| 193 | if let Some(hlc) = hlc_from_key(key, 0) |
| 194 | && hlc >= from |
| 195 | { |
| 196 | match op_codec::decode_op(v.value()) { |
| 197 | Ok(op) => results.push(op), |
| 198 | Err(e) => warn!(error = %e, "scan_from: skipping corrupt entry"), |
| 199 | } |
| 200 | } |
| 201 | } |
| 202 | Ok(Box::new(results.into_iter().map(Ok))) |
| 203 | } |
| 204 | |
| 205 | fn scan_range<'a>(&'a self, array: &str, from: Hlc, to: Hlc) -> ArrayResult<OpIter<'a>> { |
| 206 | let prefix = name_prefix(array).ok_or_else(|| ArrayError::InvalidOp { |