Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/revlog/file_io.rs @ 52280:f4aede0f01af
rust-manifest: use `memchr` crate for all byte-finding needs
While writing a very dumb manifest diffing algorithm for a proof-of-concept
I saw that `Manifest::find_by_path` was much slower than I was expecting.
It turns out that the Rust stdlib uses slow (all is relative) code when
searching for byte positions for reasons ranging from portability, SIMD
API stability, nobody doing the work, etc. `memch` is much faster for these
purposes, so let's use it.
I was measuring ~670ms of profile time in `find_by_path`, after this patch
it went down to ~230ms.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 12 Nov 2024 23:20:04 +0100 |
parents | 8d35941689af |
children | 645d247d4c75 |
rev | line source |
---|---|
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
1 //! Helpers for revlog file reading and writing. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
2 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
3 use std::{ |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
4 cell::RefCell, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
5 io::{Read, Seek, SeekFrom, Write}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
6 path::{Path, PathBuf}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
7 sync::{Arc, Mutex}, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
8 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
9 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
10 use crate::{ |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
11 errors::{HgError, IoResultExt}, |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
12 vfs::{Vfs, VfsFile}, |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
13 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
14 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
15 /// Wraps accessing arbitrary chunks of data within a file and reusing handles. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
16 /// This is currently useful for accessing a revlog's data file, only reading |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
17 /// the ranges that are currently relevant, like a sort of basic and manual |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
18 /// file-based mmap. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
19 /// |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
20 /// XXX should this just be replaced with `mmap` + `madvise` ranges? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
21 /// The upcoming `UncompressedChunkCache` will make up for most of the slowness |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
22 /// of re-reading the same chunks, so this might not be as useful. Aside from |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
23 /// the major benefit of having less code to take care of, using `mmap` will |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
24 /// allow multiple processes to share the same pages, especially for the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
25 /// changelog and manifest, which would make a difference in server contexts. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
26 pub struct RandomAccessFile { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
27 /// The current store VFS to pass it to [`FileHandle`] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
28 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
29 /// Filename of the open file, relative to the vfs root |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
30 pub filename: PathBuf, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
31 /// The current read-only handle on the file, if any |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
32 pub reading_handle: RefCell<Option<FileHandle>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
33 /// The current read-write handle on the file, if any |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
34 pub writing_handle: RefCell<Option<FileHandle>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
35 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
36 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
37 impl RandomAccessFile { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
38 /// Wrap a file for random access |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
39 pub fn new(vfs: Box<dyn Vfs>, filename: PathBuf) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
40 assert!(filename.is_relative()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
41 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
42 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
43 filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
44 reading_handle: RefCell::new(None), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
45 writing_handle: RefCell::new(None), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
46 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
47 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
48 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
49 /// Read a chunk of bytes from the file. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
50 pub fn read_chunk( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
51 &self, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
52 offset: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
53 length: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
54 ) -> Result<Vec<u8>, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
55 let mut handle = self.get_read_handle()?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
56 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
57 .seek(SeekFrom::Start(offset as u64)) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
58 .when_reading_file(&self.filename)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
59 handle.read_exact(length).when_reading_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
60 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
61 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
62 /// `pub` only for hg-cpython |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
63 #[doc(hidden)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
64 pub fn get_read_handle(&self) -> Result<FileHandle, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
65 if let Some(handle) = &*self.writing_handle.borrow() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
66 // Use a file handle being actively used for writes, if available. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
67 // There is some danger to doing this because reads will seek the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
68 // file. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
69 // However, [`Revlog::write_entry`] performs a `SeekFrom::End(0)` |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
70 // before all writes, so we should be safe. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
71 return Ok(handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
72 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
73 if let Some(handle) = &*self.reading_handle.borrow() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
74 return Ok(handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
75 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
76 // early returns done to work around borrowck being overzealous |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
77 // See https://github.com/rust-lang/rust/issues/103108 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
78 let new_handle = FileHandle::new( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
79 dyn_clone::clone_box(&*self.vfs), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
80 &self.filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
81 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
82 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
83 )?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
84 *self.reading_handle.borrow_mut() = Some(new_handle.clone()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
85 Ok(new_handle) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
86 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
87 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
88 /// `pub` only for hg-cpython |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
89 #[doc(hidden)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
90 pub fn exit_reading_context(&self) { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
91 self.reading_handle.take(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
92 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
93 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
94 // Returns whether this file currently open |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
95 pub fn is_open(&self) -> bool { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
96 self.reading_handle.borrow().is_some() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
97 || self.writing_handle.borrow().is_some() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
98 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
99 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
100 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
101 /// A buffer that holds new changelog index data that needs to be written |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
102 /// after the manifest and filelogs so that the repo is updated atomically to |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
103 /// external processes. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
104 #[derive(Clone, Debug, Default)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
105 pub struct DelayedBuffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
106 // The actual in-memory bytes storing the delayed writes |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
107 pub(super) buffer: Vec<u8>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
108 /// The current offset into the virtual file composed of file + buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
109 offset: u64, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
110 /// The size of the file at the time of opening |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
111 file_size: u64, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
112 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
113 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
114 impl DelayedBuffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
115 /// Returns the length of the full data (on-disk + buffer length). |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
116 pub fn len(&self) -> u64 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
117 self.buffer.len() as u64 + self.file_size |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
118 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
119 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
120 pub fn is_empty(&self) -> bool { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
121 self.len() == 0 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
122 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
123 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
124 |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
125 /// Holds an open [`VfsFile`] and the related data. This can be used for |
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
126 /// reading and writing. Writes can be delayed to a buffer before touching |
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
127 /// the disk, if relevant (in the changelog case), but reads are transparent. |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
128 pub struct FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
129 /// The actual open file |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
130 pub file: VfsFile, |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
131 /// The VFS with which the file was opened |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
132 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
133 /// Filename of the open file, relative to the repo root |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
134 filename: PathBuf, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
135 /// Buffer of delayed entry writes to the changelog index. This points |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
136 /// back to the buffer inside the revlog this handle refers to. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
137 delayed_buffer: Option<Arc<Mutex<DelayedBuffer>>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
138 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
139 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
140 impl std::fmt::Debug for FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
142 f.debug_struct("FileHandle") |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
143 .field("filename", &self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
144 .field("delayed_buffer", &self.delayed_buffer) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
145 .field("file", &self.file) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
146 .finish() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
147 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
148 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
149 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
150 impl Clone for FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
151 fn clone(&self) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
152 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
153 vfs: dyn_clone::clone_box(&*self.vfs), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
154 filename: self.filename.clone(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
155 delayed_buffer: self.delayed_buffer.clone(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
156 // This can only fail if the OS doesn't have the file handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
157 // anymore, so we're not going to do anything useful anyway. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
158 file: self.file.try_clone().expect("couldn't clone file handle"), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
159 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
160 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
161 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
162 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
163 impl FileHandle { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
164 /// Get a (read or write) file handle to `filename`. Only creates the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
165 /// if `create` is `true`. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
166 pub fn new( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
167 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
168 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
169 create: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
170 write: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
171 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
172 let file = if create { |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
173 vfs.create(filename.as_ref(), false)? |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
174 } else if write { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
175 vfs.open(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
176 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
177 vfs.open_read(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
178 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
179 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
180 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
181 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
182 delayed_buffer: None, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
183 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
184 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
185 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
186 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
187 /// Get a file handle to `filename`, but writes go to a [`DelayedBuffer`]. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
188 pub fn new_delayed( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
189 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
190 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
191 create: bool, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
192 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
193 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
194 let mut file = if create { |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
195 vfs.create(filename.as_ref(), false)? |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
196 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
197 vfs.open(filename.as_ref())? |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
198 }; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
199 let size = vfs.file_size(&file)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
200 let offset = file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
201 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
202 .when_reading_file(filename.as_ref())?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
203 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
204 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
205 let mut buf = delayed_buffer.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
206 buf.file_size = size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
207 buf.offset = offset; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
208 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
209 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
210 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
211 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
212 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
213 delayed_buffer: Some(delayed_buffer), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
214 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
215 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
216 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
217 |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
218 /// Wrap an existing [`VfsFile`] |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
219 pub fn from_file( |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
220 file: VfsFile, |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
221 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
222 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
223 ) -> Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
224 Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
225 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
226 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
227 delayed_buffer: None, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
228 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
229 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
230 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
231 |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
232 /// Wrap an existing [`VfsFile`], but writes go to a [`DelayedBuffer`]. |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
233 pub fn from_file_delayed( |
52181
8d35941689af
rust-vfs: support checkambig
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52167
diff
changeset
|
234 mut file: VfsFile, |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
235 vfs: Box<dyn Vfs>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
236 filename: impl AsRef<Path>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
237 delayed_buffer: Arc<Mutex<DelayedBuffer>>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
238 ) -> Result<Self, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
239 let size = vfs.file_size(&file)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
240 let offset = file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
241 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
242 .when_reading_file(filename.as_ref())?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
243 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
244 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
245 let mut buf = delayed_buffer.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
246 buf.file_size = size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
247 buf.offset = offset; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
248 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
249 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
250 Ok(Self { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
251 vfs, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
252 filename: filename.as_ref().to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
253 delayed_buffer: Some(delayed_buffer), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
254 file, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
255 }) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
256 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
257 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
258 /// Move the position of the handle to `pos`, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
259 /// spanning the [`DelayedBuffer`] if defined. Will return an error if |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
260 /// an invalid seek position is asked, or for any standard io error. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
261 pub fn seek(&mut self, pos: SeekFrom) -> Result<u64, std::io::Error> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
262 if let Some(delay_buf) = &self.delayed_buffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
263 let mut delay_buf = delay_buf.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
264 // Virtual file offset spans real file and data |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
265 match pos { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
266 SeekFrom::Start(offset) => delay_buf.offset = offset, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
267 SeekFrom::End(offset) => { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
268 delay_buf.offset = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
269 delay_buf.len().saturating_add_signed(offset) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
270 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
271 SeekFrom::Current(offset) => { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
272 delay_buf.offset = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
273 delay_buf.offset.saturating_add_signed(offset); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
274 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
275 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
276 if delay_buf.offset < delay_buf.file_size { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
277 self.file.seek(pos) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
278 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
279 Ok(delay_buf.offset) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
280 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
281 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
282 self.file.seek(pos) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
283 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
284 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
285 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
286 /// Read exactly `length` bytes from the current position. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
287 /// Errors are the same as [`std::io::Read::read_exact`]. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
288 pub fn read_exact( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
289 &mut self, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
290 length: usize, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
291 ) -> Result<Vec<u8>, std::io::Error> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
292 if let Some(delay_buf) = self.delayed_buffer.as_mut() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
293 let mut delay_buf = delay_buf.lock().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
294 let mut buf = vec![0; length]; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
295 let offset: isize = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
296 delay_buf.offset.try_into().expect("buffer too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
297 let file_size: isize = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
298 delay_buf.file_size.try_into().expect("file too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
299 let span: isize = offset - file_size; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
300 let length = length.try_into().expect("too large of a length"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
301 let absolute_span: u64 = |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
302 span.unsigned_abs().try_into().expect("length too large"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
303 if span < 0 { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
304 if length <= absolute_span { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
305 // We're only in the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
306 self.file.read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
307 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
308 // We're spanning file and buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
309 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
310 .read_exact(&mut buf[..absolute_span as usize])?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
311 delay_buf |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
312 .buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
313 .take(length - absolute_span) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
314 .read_exact(&mut buf[absolute_span as usize..])?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
315 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
316 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
317 // We're only in the buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
318 delay_buf.buffer[absolute_span as usize..] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
319 .take(length) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
320 .read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
321 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
322 delay_buf.offset += length; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
323 Ok(buf.to_owned()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
324 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
325 let mut buf = vec![0; length]; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
326 self.file.read_exact(&mut buf)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
327 Ok(buf) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
328 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
329 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
330 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
331 /// Flush the in-memory changes to disk. This does *not* write the |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
332 /// delayed buffer, only the pending file changes. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
333 pub fn flush(&mut self) -> Result<(), HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
334 self.file.flush().when_writing_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
335 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
336 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
337 /// Return the current position in the file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
338 pub fn position(&mut self) -> Result<u64, HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
339 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
340 .stream_position() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
341 .when_reading_file(&self.filename) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
342 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
343 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
344 /// Append `data` to the file, or to the [`DelayedBuffer`], if any. |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
345 pub fn write_all(&mut self, data: &[u8]) -> Result<(), HgError> { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
346 if let Some(buf) = &mut self.delayed_buffer { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
347 let mut delayed_buffer = buf.lock().expect("propagate the panic"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
348 assert_eq!(delayed_buffer.offset, delayed_buffer.len()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
349 delayed_buffer.buffer.extend_from_slice(data); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
350 delayed_buffer.offset += data.len() as u64; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
351 Ok(()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
352 } else { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
353 self.file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
354 .write_all(data) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
355 .when_writing_file(&self.filename)?; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
356 Ok(()) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
357 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
358 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
359 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
360 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
361 /// Write handles to a given revlog (index + maybe data) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
362 #[derive(Debug)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
363 pub struct WriteHandles { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
364 /// Handle to the index file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
365 pub index_handle: FileHandle, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
366 /// Handle to the data file, if the revlog is non-inline |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
367 pub data_handle: Option<FileHandle>, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
368 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
369 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
370 #[cfg(test)] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
371 mod tests { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
372 use std::io::ErrorKind; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
373 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
374 use crate::vfs::VfsImpl; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
375 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
376 use super::*; |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
377 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
378 #[test] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
379 fn test_random_access_file() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
380 let base = tempfile::tempdir().unwrap().into_path(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
381 let filename = Path::new("a"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
382 let file_path = base.join(filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
383 let raf = RandomAccessFile::new( |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
384 Box::new(VfsImpl::new(base.clone(), true)), |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
385 filename.to_owned(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
386 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
387 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
388 assert!(!raf.is_open()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
389 assert_eq!(&raf.filename, &filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
390 // Should fail to read a non-existing file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
391 match raf.get_read_handle().unwrap_err() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
392 HgError::IoError { error, .. } => match error.kind() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
393 std::io::ErrorKind::NotFound => {} |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
394 _ => panic!("should be not found"), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
395 }, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
396 e => panic!("{}", e.to_string()), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
397 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
398 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
399 std::fs::write(file_path, b"1234567890").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
400 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
401 // Should be able to open an existing file |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
402 let mut handle = raf.get_read_handle().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
403 assert!(raf.is_open()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
404 assert_eq!(handle.read_exact(10).unwrap(), b"1234567890".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
405 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
406 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
407 #[test] |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
408 fn test_file_handle() { |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
409 let base = tempfile::tempdir().unwrap().into_path(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
410 let filename = base.join("a"); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
411 // No `create` should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
412 FileHandle::new( |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
413 Box::new(VfsImpl::new(base.clone(), false)), |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
414 &filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
415 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
416 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
417 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
418 .unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
419 std::fs::write(&filename, b"1234567890").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
420 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
421 let mut read_handle = FileHandle::new( |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
422 Box::new(VfsImpl::new(base.clone(), true)), |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
423 &filename, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
424 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
425 false, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
426 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
427 .unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
428 assert_eq!(&read_handle.filename, &filename); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
429 assert_eq!(read_handle.position().unwrap(), 0); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
430 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
431 // Writing to an explicit read handle should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
432 read_handle.write_all(b"some data").unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
433 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
434 // reading exactly n bytes should work |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
435 assert_eq!(read_handle.read_exact(3).unwrap(), b"123".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
436 // and the position should be remembered |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
437 assert_eq!(read_handle.read_exact(2).unwrap(), b"45".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
438 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
439 // Seeking should work |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
440 let position = read_handle.position().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
441 read_handle.seek(SeekFrom::Current(-2)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
442 assert_eq!(position - 2, read_handle.position().unwrap()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
443 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
444 // Seeking too much data should fail |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
445 read_handle.read_exact(1000).unwrap_err(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
446 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
447 // Open a write handle |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
448 let mut handle = FileHandle::new( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
449 Box::new(VfsImpl::new(base.clone(), false)), |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
450 &filename, |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
451 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
452 true, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
453 ) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
454 .unwrap(); |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
455 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
456 // Now writing should succeed |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
457 handle.write_all(b"new data").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
458 // Opening or writing does not seek, so we should be at the start |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
459 assert_eq!(handle.position().unwrap(), 8); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
460 // We can still read |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
461 assert_eq!(handle.read_exact(2).unwrap(), b"90".to_vec()); |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
462 |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
463 let mut read_handle = FileHandle::new( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
464 Box::new(VfsImpl::new(base.clone(), true)), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
465 &filename, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
466 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
467 false, |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
468 ) |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
469 .unwrap(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
470 read_handle.seek(SeekFrom::Start(0)).unwrap(); |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
471 // On-disk file contents should be changed |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
472 assert_eq!( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
473 &read_handle.read_exact(10).unwrap(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
474 &b"new data90".to_vec(), |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
475 ); |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
476 // Flushing doesn't do anything unexpected |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
477 handle.flush().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
478 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
479 let delayed_buffer = Arc::new(Mutex::new(DelayedBuffer::default())); |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
480 let mut handle = FileHandle::new_delayed( |
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
481 Box::new(VfsImpl::new(base.clone(), false)), |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
482 &filename, |
52167
7be39c5110c9
hg-core: add a complete VFS
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52155
diff
changeset
|
483 false, |
52155
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
484 delayed_buffer, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
485 ) |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
486 .unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
487 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
488 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
489 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
490 .delayed_buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
491 .as_ref() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
492 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
493 .lock() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
494 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
495 .file_size, |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
496 10 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
497 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
498 handle.seek(SeekFrom::End(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
499 handle.write_all(b"should go to buffer").unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
500 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
501 handle |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
502 .delayed_buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
503 .as_ref() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
504 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
505 .lock() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
506 .unwrap() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
507 .len(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
508 29 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
509 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
510 read_handle.seek(SeekFrom::Start(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
511 // On-disk file contents should be unchanged |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
512 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
513 read_handle.read_exact(10).unwrap(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
514 b"new data90".to_vec(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
515 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
516 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
517 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
518 read_handle.read_exact(1).unwrap_err().kind(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
519 ErrorKind::UnexpectedEof |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
520 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
521 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
522 handle.flush().unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
523 // On-disk file contents should still be unchanged after a flush |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
524 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
525 read_handle.read_exact(1).unwrap_err().kind(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
526 ErrorKind::UnexpectedEof |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
527 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
528 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
529 // Read from the buffer only |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
530 handle.seek(SeekFrom::End(-1)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
531 assert_eq!(handle.read_exact(1).unwrap(), b"r".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
532 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
533 // Read from an overlapping section of file and buffer |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
534 handle.seek(SeekFrom::Start(6)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
535 assert_eq!( |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
536 handle.read_exact(20).unwrap(), |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
537 b"ta90should go to buf".to_vec() |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
538 ); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
539 |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
540 // Read from file only |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
541 handle.seek(SeekFrom::Start(0)).unwrap(); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
542 assert_eq!(handle.read_exact(8).unwrap(), b"new data".to_vec()); |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
543 } |
426696af24d3
rust-revlog: add file IO helpers
Rapha?l Gom?s <rgomes@octobus.net>
parents:
diff
changeset
|
544 } |