##// END OF EJS Templates
rust-dirstate: remember the data file uuid dirstate was loaded with...
Raphaël Gomès -
r51138:6cce0afc stable
parent child Browse files
Show More
@@ -573,11 +573,15 b' if rustmod is not None:'
573 testing.wait_on_cfg(self._ui, b'dirstate.post-docket-read-file')
573 testing.wait_on_cfg(self._ui, b'dirstate.post-docket-read-file')
574 if not self.docket.uuid:
574 if not self.docket.uuid:
575 data = b''
575 data = b''
576 self._map = rustmod.DirstateMap.new_empty()
576 else:
577 else:
577 data = self._read_v2_data()
578 data = self._read_v2_data()
578 self._map = rustmod.DirstateMap.new_v2(
579 self._map = rustmod.DirstateMap.new_v2(
579 data, self.docket.data_size, self.docket.tree_metadata
580 data,
580 )
581 self.docket.data_size,
582 self.docket.tree_metadata,
583 self.docket.uuid,
584 )
581 parents = self.docket.parents
585 parents = self.docket.parents
582 else:
586 else:
583 self._set_identity()
587 self._set_identity()
@@ -66,9 +66,16 b" pub struct DirstateMap<'on_disk> {"
66 pub(super) unreachable_bytes: u32,
66 pub(super) unreachable_bytes: u32,
67
67
68 /// Size of the data used to first load this `DirstateMap`. Used in case
68 /// Size of the data used to first load this `DirstateMap`. Used in case
69 /// we need to write some new metadata, but no new data on disk.
69 /// we need to write some new metadata, but no new data on disk,
70 /// as well as to detect writes that have happened in another process
71 /// since first read.
70 pub(super) old_data_size: usize,
72 pub(super) old_data_size: usize,
71
73
74 /// UUID used when first loading this `DirstateMap`. Used to check if
75 /// the UUID has been changed by another process since first read.
76 /// Can be `None` if using dirstate v1 or if it's a brand new dirstate.
77 pub(super) old_uuid: Option<Vec<u8>>,
78
72 pub(super) dirstate_version: DirstateVersion,
79 pub(super) dirstate_version: DirstateVersion,
73
80
74 /// Controlled by config option `devel.dirstate.v2.data_update_mode`
81 /// Controlled by config option `devel.dirstate.v2.data_update_mode`
@@ -460,6 +467,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
460 ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN],
467 ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN],
461 unreachable_bytes: 0,
468 unreachable_bytes: 0,
462 old_data_size: 0,
469 old_data_size: 0,
470 old_uuid: None,
463 dirstate_version: DirstateVersion::V1,
471 dirstate_version: DirstateVersion::V1,
464 write_mode: DirstateMapWriteMode::Auto,
472 write_mode: DirstateMapWriteMode::Auto,
465 }
473 }
@@ -470,9 +478,10 b" impl<'on_disk> DirstateMap<'on_disk> {"
470 on_disk: &'on_disk [u8],
478 on_disk: &'on_disk [u8],
471 data_size: usize,
479 data_size: usize,
472 metadata: &[u8],
480 metadata: &[u8],
481 uuid: Vec<u8>,
473 ) -> Result<Self, DirstateError> {
482 ) -> Result<Self, DirstateError> {
474 if let Some(data) = on_disk.get(..data_size) {
483 if let Some(data) = on_disk.get(..data_size) {
475 Ok(on_disk::read(data, metadata)?)
484 Ok(on_disk::read(data, metadata, uuid)?)
476 } else {
485 } else {
477 Err(DirstateV2ParseError::new("not enough bytes on disk").into())
486 Err(DirstateV2ParseError::new("not enough bytes on disk").into())
478 }
487 }
@@ -1843,6 +1852,7 b' mod tests {'
1843 packed,
1852 packed,
1844 packed_len,
1853 packed_len,
1845 metadata.as_bytes(),
1854 metadata.as_bytes(),
1855 vec![],
1846 )?;
1856 )?;
1847
1857
1848 // Check that everything is accounted for
1858 // Check that everything is accounted for
@@ -290,6 +290,7 b' pub fn read_docket('
290 pub(super) fn read<'on_disk>(
290 pub(super) fn read<'on_disk>(
291 on_disk: &'on_disk [u8],
291 on_disk: &'on_disk [u8],
292 metadata: &[u8],
292 metadata: &[u8],
293 uuid: Vec<u8>,
293 ) -> Result<DirstateMap<'on_disk>, DirstateV2ParseError> {
294 ) -> Result<DirstateMap<'on_disk>, DirstateV2ParseError> {
294 if on_disk.is_empty() {
295 if on_disk.is_empty() {
295 let mut map = DirstateMap::empty(on_disk);
296 let mut map = DirstateMap::empty(on_disk);
@@ -312,6 +313,7 b" pub(super) fn read<'on_disk>("
312 ignore_patterns_hash: meta.ignore_patterns_hash,
313 ignore_patterns_hash: meta.ignore_patterns_hash,
313 unreachable_bytes: meta.unreachable_bytes.get(),
314 unreachable_bytes: meta.unreachable_bytes.get(),
314 old_data_size: on_disk.len(),
315 old_data_size: on_disk.len(),
316 old_uuid: Some(uuid),
315 dirstate_version: DirstateVersion::V2,
317 dirstate_version: DirstateVersion::V2,
316 write_mode: DirstateMapWriteMode::Auto,
318 write_mode: DirstateMapWriteMode::Auto,
317 };
319 };
@@ -57,6 +57,7 b' impl OwningDirstateMap {'
57 on_disk: OnDisk,
57 on_disk: OnDisk,
58 data_size: usize,
58 data_size: usize,
59 metadata: &[u8],
59 metadata: &[u8],
60 uuid: Vec<u8>,
60 ) -> Result<Self, DirstateError>
61 ) -> Result<Self, DirstateError>
61 where
62 where
62 OnDisk: Deref<Target = [u8]> + Send + 'static,
63 OnDisk: Deref<Target = [u8]> + Send + 'static,
@@ -66,7 +67,7 b' impl OwningDirstateMap {'
66 OwningDirstateMapTryBuilder {
67 OwningDirstateMapTryBuilder {
67 on_disk,
68 on_disk,
68 map_builder: |bytes| {
69 map_builder: |bytes| {
69 DirstateMap::new_v2(&bytes, data_size, metadata)
70 DirstateMap::new_v2(&bytes, data_size, metadata, uuid)
70 },
71 },
71 }
72 }
72 .try_build()
73 .try_build()
@@ -86,4 +87,12 b' impl OwningDirstateMap {'
86 pub fn on_disk(&self) -> &[u8] {
87 pub fn on_disk(&self) -> &[u8] {
87 self.borrow_on_disk()
88 self.borrow_on_disk()
88 }
89 }
90
91 pub fn old_uuid(&self) -> Option<&[u8]> {
92 self.get_map().old_uuid.as_deref()
93 }
94
95 pub fn old_data_size(&self) -> usize {
96 self.get_map().old_data_size
97 }
89 }
98 }
@@ -383,6 +383,7 b' impl Repo {'
383 self.dirstate_parents.set(docket.parents());
383 self.dirstate_parents.set(docket.parents());
384 self.dirstate_data_file_uuid
384 self.dirstate_data_file_uuid
385 .set(Some(docket.uuid.to_owned()));
385 .set(Some(docket.uuid.to_owned()));
386 let uuid = docket.uuid.to_owned();
386 let data_size = docket.data_size();
387 let data_size = docket.data_size();
387
388
388 let context = "between reading dirstate docket and data file";
389 let context = "between reading dirstate docket and data file";
@@ -415,16 +416,16 b' impl Repo {'
415 }
416 }
416 Err(e) => return Err(e.into()),
417 Err(e) => return Err(e.into()),
417 };
418 };
418 OwningDirstateMap::new_v2(contents, data_size, metadata)
419 OwningDirstateMap::new_v2(contents, data_size, metadata, uuid)
419 } else {
420 } else {
420 match self
421 match self
421 .hg_vfs()
422 .hg_vfs()
422 .mmap_open(docket.data_filename())
423 .mmap_open(docket.data_filename())
423 .io_not_found_as_none()
424 .io_not_found_as_none()
424 {
425 {
425 Ok(Some(data_mmap)) => {
426 Ok(Some(data_mmap)) => OwningDirstateMap::new_v2(
426 OwningDirstateMap::new_v2(data_mmap, data_size, metadata)
427 data_mmap, data_size, metadata, uuid,
427 }
428 ),
428 Ok(None) => {
429 Ok(None) => {
429 // Race where the data file was deleted right after we
430 // Race where the data file was deleted right after we
430 // read the docket, try again
431 // read the docket, try again
@@ -66,18 +66,28 b' py_class!(pub class DirstateMap |py| {'
66 on_disk: PyBytes,
66 on_disk: PyBytes,
67 data_size: usize,
67 data_size: usize,
68 tree_metadata: PyBytes,
68 tree_metadata: PyBytes,
69 uuid: PyBytes,
69 ) -> PyResult<PyObject> {
70 ) -> PyResult<PyObject> {
70 let dirstate_error = |e: DirstateError| {
71 let dirstate_error = |e: DirstateError| {
71 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
72 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
72 };
73 };
73 let on_disk = PyBytesDeref::new(py, on_disk);
74 let on_disk = PyBytesDeref::new(py, on_disk);
75 let uuid = uuid.data(py);
74 let map = OwningDirstateMap::new_v2(
76 let map = OwningDirstateMap::new_v2(
75 on_disk, data_size, tree_metadata.data(py),
77 on_disk, data_size, tree_metadata.data(py), uuid.to_owned(),
76 ).map_err(dirstate_error)?;
78 ).map_err(dirstate_error)?;
77 let map = Self::create_instance(py, map)?;
79 let map = Self::create_instance(py, map)?;
78 Ok(map.into_object())
80 Ok(map.into_object())
79 }
81 }
80
82
83 /// Returns an empty DirstateMap. Only used for a new dirstate.
84 @staticmethod
85 def new_empty() -> PyResult<PyObject> {
86 let map = OwningDirstateMap::new_empty(vec![]);
87 let map = Self::create_instance(py, map)?;
88 Ok(map.into_object())
89 }
90
81 def clear(&self) -> PyResult<PyObject> {
91 def clear(&self) -> PyResult<PyObject> {
82 self.inner(py).borrow_mut().clear();
92 self.inner(py).borrow_mut().clear();
83 Ok(py.None())
93 Ok(py.None())
General Comments 0
You need to be logged in to leave comments. Login now