Show More
@@ -10,6 +10,7 b' use crate::{' | |||
|
10 | 10 | utils::{node_from_py_bytes, node_from_py_object}, |
|
11 | 11 | }; |
|
12 | 12 | use cpython::{ |
|
13 | buffer::{Element, PyBuffer}, | |
|
13 | 14 | exc::{IndexError, ValueError}, |
|
14 | 15 | ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyModule, PyObject, |
|
15 | 16 | PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject, |
@@ -36,6 +37,8 b' py_class!(pub class MixedIndex |py| {' | |||
|
36 | 37 | data cindex: RefCell<cindex::Index>; |
|
37 | 38 | data nt: RefCell<Option<NodeTree>>; |
|
38 | 39 | data docket: RefCell<Option<PyObject>>; |
|
40 | // Holds a reference to the mmap'ed persistent nodemap data | |
|
41 | data mmap: RefCell<Option<PyBuffer>>; | |
|
39 | 42 | |
|
40 | 43 | def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> { |
|
41 | 44 | Self::new(py, cindex) |
@@ -268,6 +271,14 b' py_class!(pub class MixedIndex |py| {' | |||
|
268 | 271 | def nodemap_data_incremental(&self) -> PyResult<PyObject> { |
|
269 | 272 | self.inner_nodemap_data_incremental(py) |
|
270 | 273 | } |
|
274 | def update_nodemap_data( | |
|
275 | &self, | |
|
276 | docket: PyObject, | |
|
277 | nm_data: PyObject | |
|
278 | ) -> PyResult<PyObject> { | |
|
279 | self.inner_update_nodemap_data(py, docket, nm_data) | |
|
280 | } | |
|
281 | ||
|
271 | 282 | |
|
272 | 283 | }); |
|
273 | 284 | |
@@ -278,6 +289,7 b' impl MixedIndex {' | |||
|
278 | 289 | RefCell::new(cindex::Index::new(py, cindex)?), |
|
279 | 290 | RefCell::new(None), |
|
280 | 291 | RefCell::new(None), |
|
292 | RefCell::new(None), | |
|
281 | 293 | ) |
|
282 | 294 | } |
|
283 | 295 | |
@@ -374,6 +386,56 b' impl MixedIndex {' | |||
|
374 | 386 | .to_py_object(py) |
|
375 | 387 | .into_object()) |
|
376 | 388 | } |
|
389 | ||
|
390 | /// Update the nodemap from the new (mmaped) data. | |
|
391 | /// The docket is kept as a reference for later incremental calls. | |
|
392 | fn inner_update_nodemap_data( | |
|
393 | &self, | |
|
394 | py: Python, | |
|
395 | docket: PyObject, | |
|
396 | nm_data: PyObject, | |
|
397 | ) -> PyResult<PyObject> { | |
|
398 | let buf = PyBuffer::get(py, &nm_data)?; | |
|
399 | let len = buf.item_count(); | |
|
400 | ||
|
401 | // Build a slice from the mmap'ed buffer data | |
|
402 | let cbuf = buf.buf_ptr(); | |
|
403 | let bytes = if std::mem::size_of::<u8>() == buf.item_size() | |
|
404 | && buf.is_c_contiguous() | |
|
405 | && u8::is_compatible_format(buf.format()) | |
|
406 | { | |
|
407 | unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) } | |
|
408 | } else { | |
|
409 | return Err(PyErr::new::<ValueError, _>( | |
|
410 | py, | |
|
411 | "Nodemap data buffer has an invalid memory representation" | |
|
412 | .to_string(), | |
|
413 | )); | |
|
414 | }; | |
|
415 | ||
|
416 | // Keep a reference to the mmap'ed buffer, otherwise we get a dangling | |
|
417 | // pointer. | |
|
418 | self.mmap(py).borrow_mut().replace(buf); | |
|
419 | ||
|
420 | let mut nt = NodeTree::load_bytes(Box::new(bytes), len); | |
|
421 | ||
|
422 | let data_tip = | |
|
423 | docket.getattr(py, "tip_rev")?.extract::<Revision>(py)?; | |
|
424 | self.docket(py).borrow_mut().replace(docket.clone_ref(py)); | |
|
425 | let idx = self.cindex(py).borrow(); | |
|
426 | let current_tip = idx.len(); | |
|
427 | ||
|
428 | for r in (data_tip + 1)..current_tip as Revision { | |
|
429 | let rev = r as Revision; | |
|
430 | // in this case node() won't ever return None | |
|
431 | nt.insert(&*idx, idx.node(rev).unwrap(), rev) | |
|
432 | .map_err(|e| nodemap_error(py, e))? | |
|
433 | } | |
|
434 | ||
|
435 | *self.nt(py).borrow_mut() = Some(nt); | |
|
436 | ||
|
437 | Ok(py.None()) | |
|
438 | } | |
|
377 | 439 | } |
|
378 | 440 | |
|
379 | 441 | fn revlog_error(py: Python) -> PyErr { |
General Comments 0
You need to be logged in to leave comments.
Login now