##// END OF EJS Templates
rust-nodemap: add binding to `nodemap_update_data`...
Georges Racinet -
r44997:15febf99 default
parent child Browse files
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