Show More
@@ -10,6 +10,7 b' use crate::{' | |||||
10 | utils::{node_from_py_bytes, node_from_py_object}, |
|
10 | utils::{node_from_py_bytes, node_from_py_object}, | |
11 | }; |
|
11 | }; | |
12 | use cpython::{ |
|
12 | use cpython::{ | |
|
13 | buffer::{Element, PyBuffer}, | |||
13 | exc::{IndexError, ValueError}, |
|
14 | exc::{IndexError, ValueError}, | |
14 | ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyModule, PyObject, |
|
15 | ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyModule, PyObject, | |
15 | PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject, |
|
16 | PyResult, PyString, PyTuple, Python, PythonObject, ToPyObject, | |
@@ -36,6 +37,8 b' py_class!(pub class MixedIndex |py| {' | |||||
36 | data cindex: RefCell<cindex::Index>; |
|
37 | data cindex: RefCell<cindex::Index>; | |
37 | data nt: RefCell<Option<NodeTree>>; |
|
38 | data nt: RefCell<Option<NodeTree>>; | |
38 | data docket: RefCell<Option<PyObject>>; |
|
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 | def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> { |
|
43 | def __new__(_cls, cindex: PyObject) -> PyResult<MixedIndex> { | |
41 | Self::new(py, cindex) |
|
44 | Self::new(py, cindex) | |
@@ -268,6 +271,14 b' py_class!(pub class MixedIndex |py| {' | |||||
268 | def nodemap_data_incremental(&self) -> PyResult<PyObject> { |
|
271 | def nodemap_data_incremental(&self) -> PyResult<PyObject> { | |
269 | self.inner_nodemap_data_incremental(py) |
|
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 | RefCell::new(cindex::Index::new(py, cindex)?), |
|
289 | RefCell::new(cindex::Index::new(py, cindex)?), | |
279 | RefCell::new(None), |
|
290 | RefCell::new(None), | |
280 | RefCell::new(None), |
|
291 | RefCell::new(None), | |
|
292 | RefCell::new(None), | |||
281 | ) |
|
293 | ) | |
282 | } |
|
294 | } | |
283 |
|
295 | |||
@@ -374,6 +386,56 b' impl MixedIndex {' | |||||
374 | .to_py_object(py) |
|
386 | .to_py_object(py) | |
375 | .into_object()) |
|
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 | fn revlog_error(py: Python) -> PyErr { |
|
441 | fn revlog_error(py: Python) -> PyErr { |
General Comments 0
You need to be logged in to leave comments.
Login now