Mercurial > public > mercurial-scm > hg
comparison rust/hg-cpython/src/revlog.rs @ 44510:15febf99a9c6
rust-nodemap: add binding to `nodemap_update_data`
Differential Revision: https://phab.mercurial-scm.org/D8160
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Wed, 12 Feb 2020 10:53:19 +0100 |
parents | 5bbf887275b0 |
children | cadcc8c20860 |
comparison
equal
deleted
inserted
replaced
44509:5bbf887275b0 | 44510:15febf99a9c6 |
---|---|
8 use crate::{ | 8 use crate::{ |
9 cindex, | 9 cindex, |
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, |
16 }; | 17 }; |
17 use hg::{ | 18 use hg::{ |
34 | 35 |
35 py_class!(pub class MixedIndex |py| { | 36 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) |
42 } | 45 } |
43 | 46 |
266 } | 269 } |
267 | 270 |
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 |
274 impl MixedIndex { | 285 impl MixedIndex { |
275 fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> { | 286 fn new(py: Python, cindex: PyObject) -> PyResult<MixedIndex> { |
276 Self::create_instance( | 287 Self::create_instance( |
277 py, | 288 py, |
278 RefCell::new(cindex::Index::new(py, cindex)?), | 289 RefCell::new(cindex::Index::new(py, cindex)?), |
290 RefCell::new(None), | |
279 RefCell::new(None), | 291 RefCell::new(None), |
280 RefCell::new(None), | 292 RefCell::new(None), |
281 ) | 293 ) |
282 } | 294 } |
283 | 295 |
372 | 384 |
373 Ok((docket, changed, PyBytes::new(py, &data)) | 385 Ok((docket, changed, PyBytes::new(py, &data)) |
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 { |
380 match py | 442 match py |
381 .import("mercurial.error") | 443 .import("mercurial.error") |