1use crate::format::builder::{
6 FormatCreateBuilder, FormatCreateBuilderBase, FormatDriverBuilder, FormatDriverBuilderBase,
7};
8use crate::format::drivers::FormatDriverInstance;
9use crate::format::gate::ImplicitOpenGate;
10use crate::format::{Format, PreallocateMode};
11use crate::{
12 storage, DenyImplicitOpenGate, ShallowMapping, Storage, StorageExt, StorageOpenOptions,
13};
14use maybe_async::maybe_async;
15use std::fmt::{self, Display, Formatter};
16use std::io;
17use std::path::{Path, PathBuf};
18use std::sync::atomic::{AtomicU64, Ordering};
19
20#[derive(Debug)]
22pub struct Raw<S: Storage + 'static> {
23 inner: S,
25
26 writable: bool,
28
29 size: AtomicU64,
31}
32
33#[maybe_async]
34impl<S: Storage + 'static> Raw<S> {
35 pub fn builder(image: S) -> RawOpenBuilder<S> {
37 RawOpenBuilder::new(image)
38 }
39
40 pub fn builder_path<P: AsRef<Path>>(image_path: P) -> RawOpenBuilder<S> {
42 RawOpenBuilder::new_path(image_path)
43 }
44
45 pub fn create_builder(image: S) -> RawCreateBuilder<S> {
47 RawCreateBuilder::new(image)
48 }
49
50 pub async fn open_image(inner: S, writable: bool) -> io::Result<Self> {
52 let size = inner.size()?;
53 Ok(Raw {
54 inner,
55 writable,
56 size: size.into(),
57 })
58 }
59
60 pub async fn open_path<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
62 let storage_opts = StorageOpenOptions::new().write(writable).filename(path);
63 let inner = S::open(storage_opts).await?;
64 Self::open_image(inner, writable).await
65 }
66
67 #[cfg(feature = "sync-wrappers")]
69 pub fn open_image_sync(inner: S, writable: bool) -> io::Result<Self> {
70 let size = inner.size()?;
71 Ok(Raw {
72 inner,
73 writable,
74 size: size.into(),
75 })
76 }
77
78 #[cfg(feature = "sync-wrappers")]
79 pub fn open_path_sync<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
81 tokio::runtime::Builder::new_current_thread()
82 .build()?
83 .block_on(Self::open_path(path, writable))
84 }
85}
86
87#[maybe_async(?Send)]
88impl<S: Storage + 'static> FormatDriverInstance for Raw<S> {
89 type Storage = S;
90
91 fn format(&self) -> Format {
92 Format::Raw
93 }
94
95 async unsafe fn probe(_storage: &S) -> io::Result<bool>
96 where
97 Self: Sized,
98 {
99 Ok(true)
100 }
101
102 fn size(&self) -> u64 {
103 self.size.load(Ordering::Relaxed)
104 }
105
106 fn zero_granularity(&self) -> Option<u64> {
107 None
108 }
109
110 fn collect_storage_dependencies(&self) -> Vec<&S> {
111 vec![&self.inner]
112 }
113
114 fn writable(&self) -> bool {
115 self.writable
116 }
117
118 #[allow(clippy::needless_lifetimes)] async fn get_mapping<'a>(
120 &'a self,
121 offset: u64,
122 max_length: u64,
123 ) -> io::Result<(ShallowMapping<'a, S>, u64)> {
124 let remaining = match self.size().checked_sub(offset) {
125 None | Some(0) => return Ok((ShallowMapping::Eof {}, 0)),
126 Some(remaining) => remaining,
127 };
128
129 Ok((
130 ShallowMapping::Raw {
131 storage: &self.inner,
132 offset,
133 writable: true,
134 },
135 std::cmp::min(max_length, remaining),
136 ))
137 }
138
139 #[allow(clippy::needless_lifetimes)] async fn ensure_data_mapping<'a>(
141 &'a self,
142 offset: u64,
143 length: u64,
144 _overwrite: bool,
145 ) -> io::Result<(&'a S, u64, u64)> {
146 let Some(remaining) = self.size().checked_sub(offset) else {
147 return Err(io::Error::other("Cannot allocate past the end of file"));
148 };
149 if length > remaining {
150 return Err(io::Error::other("Cannot allocate past the end of file"));
151 }
152
153 Ok((&self.inner, offset, length))
154 }
155
156 async fn ensure_zero_mapping(&self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
157 let zero_align = self.inner.zero_align();
158 assert!(zero_align.is_power_of_two());
159
160 let zero_align_mask = zero_align as u64 - 1;
161
162 let aligned_end = (offset + length) & !zero_align_mask;
163 let aligned_offset = (offset + zero_align_mask) & !zero_align_mask;
164 let aligned_length = aligned_end.saturating_sub(aligned_offset);
165 if aligned_length == 0 {
166 return Ok((aligned_offset, 0));
167 }
168
169 self.inner
171 .write_zeroes(aligned_offset, aligned_length)
172 .await?;
173 Ok((aligned_offset, aligned_length))
174 }
175
176 async unsafe fn discard_to_zero_unsafe(
177 &self,
178 offset: u64,
179 length: u64,
180 ) -> io::Result<(u64, u64)> {
181 self.ensure_zero_mapping(offset, length).await
182 }
183
184 async unsafe fn discard_to_any_unsafe(
185 &self,
186 offset: u64,
187 length: u64,
188 ) -> io::Result<(u64, u64)> {
189 let discard_align = self.inner.discard_align();
190 assert!(discard_align.is_power_of_two());
191
192 let discard_align_mask = discard_align as u64 - 1;
193
194 let aligned_end = (offset + length) & !discard_align_mask;
195 let aligned_offset = (offset + discard_align_mask) & !discard_align_mask;
196 let aligned_length = aligned_end.saturating_sub(aligned_offset);
197 if aligned_length == 0 {
198 return Ok((aligned_offset, 0));
199 }
200
201 self.inner.discard(aligned_offset, aligned_length).await?;
202 Ok((aligned_offset, aligned_length))
203 }
204
205 async unsafe fn discard_to_backing_unsafe(
206 &self,
207 offset: u64,
208 length: u64,
209 ) -> io::Result<(u64, u64)> {
210 unsafe { self.discard_to_zero_unsafe(offset, length).await }
211 }
212
213 async fn flush(&self) -> io::Result<()> {
214 self.inner.flush().await
216 }
217
218 async fn sync(&self) -> io::Result<()> {
219 self.inner.sync().await
220 }
221
222 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
223 unsafe { self.inner.invalidate_cache() }.await
226 }
227
228 async fn resize_grow(
229 &self,
230 new_size: u64,
231 format_prealloc_mode: PreallocateMode,
232 ) -> io::Result<()> {
233 if self
234 .size
235 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| {
236 (new_size > old).then_some(new_size)
237 })
238 .is_err()
239 {
240 return Ok(()); }
242
243 let storage_prealloc_mode = match format_prealloc_mode {
244 PreallocateMode::None => storage::PreallocateMode::None,
245 PreallocateMode::Zero | PreallocateMode::FormatAllocate => {
246 storage::PreallocateMode::Zero
247 }
248 PreallocateMode::FullAllocate => storage::PreallocateMode::Allocate,
249 PreallocateMode::WriteData => storage::PreallocateMode::WriteData,
250 };
251 self.inner.resize(new_size, storage_prealloc_mode).await
252 }
253
254 async fn resize_shrink(&mut self, new_size: u64) -> io::Result<()> {
255 if self
256 .size
257 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |old| {
258 (new_size < old).then_some(new_size)
259 })
260 .is_err()
261 {
262 return Ok(()); }
264
265 self.inner
266 .resize(new_size, storage::PreallocateMode::None)
267 .await
268 }
269}
270
271impl<S: Storage + 'static> Display for Raw<S> {
272 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
273 write!(f, "raw[{}]", self.inner)
274 }
275}
276
277pub struct RawOpenBuilder<S: Storage + 'static>(FormatDriverBuilderBase<S>);
279
280#[maybe_async(AFIT)]
281impl<S: Storage + 'static> FormatDriverBuilder<S> for RawOpenBuilder<S> {
282 type Format = Raw<S>;
283 const FORMAT: Format = Format::Raw;
284
285 fn new(image: S) -> Self {
286 RawOpenBuilder(FormatDriverBuilderBase::new(image))
287 }
288
289 fn new_path<P: AsRef<Path>>(path: P) -> Self {
290 RawOpenBuilder(FormatDriverBuilderBase::new_path(path))
291 }
292
293 fn write(mut self, writable: bool) -> Self {
294 self.0.set_write(writable);
295 self
296 }
297
298 fn storage_open_options(mut self, options: StorageOpenOptions) -> Self {
299 self.0.set_storage_open_options(options);
300 self
301 }
302
303 async fn open<G: ImplicitOpenGate<S>>(self, mut gate: G) -> io::Result<Self::Format> {
304 let writable = self.0.get_writable();
305 let file = self.0.open_image(&mut gate).await?;
306 Raw::open_image(file, writable).await
307 }
308
309 fn get_image_path(&self) -> Option<PathBuf> {
310 self.0.get_image_path()
311 }
312
313 fn get_writable(&self) -> bool {
314 self.0.get_writable()
315 }
316
317 fn get_storage_open_options(&self) -> Option<&StorageOpenOptions> {
318 self.0.get_storage_opts()
319 }
320}
321
322pub struct RawCreateBuilder<S: Storage + 'static>(FormatCreateBuilderBase<S>);
324
325#[maybe_async(AFIT)]
326impl<S: Storage + 'static> FormatCreateBuilder<S> for RawCreateBuilder<S> {
327 const FORMAT: Format = Format::Raw;
328 type DriverBuilder = RawOpenBuilder<S>;
329
330 fn new(image: S) -> Self {
331 RawCreateBuilder(FormatCreateBuilderBase::new(image))
332 }
333
334 fn size(mut self, size: u64) -> Self {
335 self.0.set_size(size);
336 self
337 }
338
339 fn preallocate(mut self, prealloc_mode: PreallocateMode) -> Self {
340 self.0.set_preallocate(prealloc_mode);
341 self
342 }
343
344 fn get_size(&self) -> u64 {
345 self.0.get_size()
346 }
347
348 fn get_preallocate(&self) -> PreallocateMode {
349 self.0.get_preallocate()
350 }
351
352 async fn create(self) -> io::Result<()> {
353 self.create_open(DenyImplicitOpenGate::default(), |image| {
354 Ok(Raw::builder(image))
355 })
356 .await?;
357 Ok(())
358 }
359
360 async fn create_open<
361 G: ImplicitOpenGate<S>,
362 F: FnOnce(S) -> io::Result<Self::DriverBuilder>,
363 >(
364 self,
365 open_gate: G,
366 open_builder_fn: F,
367 ) -> io::Result<Raw<S>> {
368 let size = self.0.get_size();
369 let prealloc = self.0.get_preallocate();
370 let image = self.0.get_image();
371
372 if image.size()? > 0 {
374 image.resize(size, storage::PreallocateMode::None).await?;
375 }
376
377 let img = open_builder_fn(image)?.write(true).open(open_gate).await?;
378 if size > 0 {
379 img.resize_grow(size, prealloc).await?;
380 }
381
382 Ok(img)
383 }
384}