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::sync_primitives::{Mutex, MutexGuard};
12use crate::{
13 storage, DenyImplicitOpenGate, ShallowMapping, Storage, StorageExt, StorageOpenOptions,
14};
15use maybe_async::maybe_async;
16use std::fmt::{self, Display, Formatter};
17use std::io;
18use std::path::{Path, PathBuf};
19use std::sync::atomic::{AtomicU64, Ordering};
20
21#[derive(Debug)]
23pub struct Raw<S: Storage + 'static> {
24 inner: S,
26
27 writable: bool,
29
30 size: AtomicU64,
35
36 resize_lock: Mutex<u64>,
42}
43
44#[maybe_async]
45impl<S: Storage + 'static> Raw<S> {
46 pub fn builder(image: S) -> RawOpenBuilder<S> {
48 RawOpenBuilder::new(image)
49 }
50
51 pub fn builder_path<P: AsRef<Path>>(image_path: P) -> RawOpenBuilder<S> {
53 RawOpenBuilder::new_path(image_path)
54 }
55
56 pub fn create_builder(image: S) -> RawCreateBuilder<S> {
58 RawCreateBuilder::new(image)
59 }
60
61 pub async fn open_image(inner: S, writable: bool) -> io::Result<Self> {
63 let size = inner.size()?;
64 Ok(Raw {
65 inner,
66 writable,
67 size: size.into(),
68 resize_lock: Mutex::new(size),
69 })
70 }
71
72 pub async fn open_path<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
74 let storage_opts = StorageOpenOptions::new().write(writable).filename(path);
75 let inner = S::open(storage_opts).await?;
76 Self::open_image(inner, writable).await
77 }
78
79 #[cfg(feature = "sync-wrappers")]
81 pub fn open_image_sync(inner: S, writable: bool) -> io::Result<Self> {
82 let size = inner.size()?;
83 Ok(Raw {
84 inner,
85 writable,
86 size: size.into(),
87 resize_lock: Mutex::new(size),
88 })
89 }
90
91 #[cfg(feature = "sync-wrappers")]
92 pub fn open_path_sync<P: AsRef<Path>>(path: P, writable: bool) -> io::Result<Self> {
94 tokio::runtime::Builder::new_current_thread()
95 .build()?
96 .block_on(Self::open_path(path, writable))
97 }
98
99 fn set_size(&self, size_guard: &mut MutexGuard<'_, u64>, new_size: u64) {
104 **size_guard = new_size;
105 self.size.store(new_size, Ordering::Relaxed);
106 }
107}
108
109#[maybe_async(?Send)]
110impl<S: Storage + 'static> FormatDriverInstance for Raw<S> {
111 type Storage = S;
112
113 fn format(&self) -> Format {
114 Format::Raw
115 }
116
117 async unsafe fn probe(_storage: &S) -> io::Result<bool>
118 where
119 Self: Sized,
120 {
121 Ok(true)
122 }
123
124 fn size(&self) -> u64 {
125 self.size.load(Ordering::Relaxed)
126 }
127
128 fn zero_granularity(&self) -> Option<u64> {
129 None
130 }
131
132 fn collect_storage_dependencies(&self) -> Vec<&S> {
133 vec![&self.inner]
134 }
135
136 fn writable(&self) -> bool {
137 self.writable
138 }
139
140 #[allow(clippy::needless_lifetimes)] async fn get_mapping<'a>(
142 &'a self,
143 offset: u64,
144 max_length: u64,
145 ) -> io::Result<(ShallowMapping<'a, S>, u64)> {
146 let remaining = match self.size().checked_sub(offset) {
147 None | Some(0) => return Ok((ShallowMapping::Eof {}, 0)),
148 Some(remaining) => remaining,
149 };
150
151 Ok((
152 ShallowMapping::Raw {
153 storage: &self.inner,
154 offset,
155 writable: true,
156 },
157 std::cmp::min(max_length, remaining),
158 ))
159 }
160
161 #[allow(clippy::needless_lifetimes)] async fn ensure_data_mapping<'a>(
163 &'a self,
164 offset: u64,
165 length: u64,
166 _overwrite: bool,
167 ) -> io::Result<(&'a S, u64, u64)> {
168 let Some(remaining) = self.size().checked_sub(offset) else {
169 return Err(io::Error::other("Cannot allocate past the end of file"));
170 };
171 if length > remaining {
172 return Err(io::Error::other("Cannot allocate past the end of file"));
173 }
174
175 Ok((&self.inner, offset, length))
176 }
177
178 async fn ensure_zero_mapping(&self, offset: u64, length: u64) -> io::Result<(u64, u64)> {
179 let zero_align = self.inner.zero_align();
180 assert!(zero_align.is_power_of_two());
181
182 let zero_align_mask = zero_align as u64 - 1;
183
184 let aligned_end = (offset + length) & !zero_align_mask;
185 let aligned_offset = (offset + zero_align_mask) & !zero_align_mask;
186 let aligned_length = aligned_end.saturating_sub(aligned_offset);
187 if aligned_length == 0 {
188 return Ok((aligned_offset, 0));
189 }
190
191 self.inner
193 .write_zeroes(aligned_offset, aligned_length)
194 .await?;
195 Ok((aligned_offset, aligned_length))
196 }
197
198 async unsafe fn discard_to_zero_unsafe(
199 &self,
200 offset: u64,
201 length: u64,
202 ) -> io::Result<(u64, u64)> {
203 self.ensure_zero_mapping(offset, length).await
204 }
205
206 async unsafe fn discard_to_any_unsafe(
207 &self,
208 offset: u64,
209 length: u64,
210 ) -> io::Result<(u64, u64)> {
211 let discard_align = self.inner.discard_align();
212 assert!(discard_align.is_power_of_two());
213
214 let discard_align_mask = discard_align as u64 - 1;
215
216 let aligned_end = (offset + length) & !discard_align_mask;
217 let aligned_offset = (offset + discard_align_mask) & !discard_align_mask;
218 let aligned_length = aligned_end.saturating_sub(aligned_offset);
219 if aligned_length == 0 {
220 return Ok((aligned_offset, 0));
221 }
222
223 self.inner.discard(aligned_offset, aligned_length).await?;
224 Ok((aligned_offset, aligned_length))
225 }
226
227 async unsafe fn discard_to_backing_unsafe(
228 &self,
229 offset: u64,
230 length: u64,
231 ) -> io::Result<(u64, u64)> {
232 unsafe { self.discard_to_zero_unsafe(offset, length).await }
233 }
234
235 async fn flush(&self) -> io::Result<()> {
236 self.inner.flush().await
238 }
239
240 async fn sync(&self) -> io::Result<()> {
241 self.inner.sync().await
242 }
243
244 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
245 unsafe { self.inner.invalidate_cache() }.await
248 }
249
250 async fn resize_grow(
251 &self,
252 new_size: u64,
253 format_prealloc_mode: PreallocateMode,
254 ) -> io::Result<()> {
255 let mut size_guard = self.resize_lock.lock().await;
256 if new_size <= *size_guard {
257 return Ok(()); }
259
260 let storage_prealloc_mode = match format_prealloc_mode {
261 PreallocateMode::None => storage::PreallocateMode::None,
262 PreallocateMode::Zero | PreallocateMode::FormatAllocate => {
263 storage::PreallocateMode::Zero
264 }
265 PreallocateMode::FullAllocate => storage::PreallocateMode::Allocate,
266 PreallocateMode::WriteData => storage::PreallocateMode::WriteData,
267 };
268
269 self.inner.resize(new_size, storage_prealloc_mode).await?;
271
272 self.set_size(&mut size_guard, new_size);
273 Ok(())
274 }
275
276 async fn resize_shrink(&mut self, new_size: u64) -> io::Result<()> {
277 let mut size_guard = self.resize_lock.lock().await;
279 let old_size = *size_guard;
280 if new_size >= old_size {
281 return Ok(()); }
283
284 self.set_size(&mut size_guard, new_size);
286
287 if let Err(err) = self
288 .inner
289 .resize(new_size, storage::PreallocateMode::None)
290 .await
291 {
292 self.set_size(&mut size_guard, old_size);
293 return Err(err);
294 }
295
296 Ok(())
297 }
298}
299
300impl<S: Storage + 'static> Display for Raw<S> {
301 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
302 write!(f, "raw[{}]", self.inner)
303 }
304}
305
306pub struct RawOpenBuilder<S: Storage + 'static>(FormatDriverBuilderBase<S>);
308
309#[maybe_async(AFIT)]
310impl<S: Storage + 'static> FormatDriverBuilder<S> for RawOpenBuilder<S> {
311 type Format = Raw<S>;
312 const FORMAT: Format = Format::Raw;
313
314 fn new(image: S) -> Self {
315 RawOpenBuilder(FormatDriverBuilderBase::new(image))
316 }
317
318 fn new_path<P: AsRef<Path>>(path: P) -> Self {
319 RawOpenBuilder(FormatDriverBuilderBase::new_path(path))
320 }
321
322 fn write(mut self, writable: bool) -> Self {
323 self.0.set_write(writable);
324 self
325 }
326
327 fn storage_open_options(mut self, options: StorageOpenOptions) -> Self {
328 self.0.set_storage_open_options(options);
329 self
330 }
331
332 async fn open<G: ImplicitOpenGate<S>>(self, mut gate: G) -> io::Result<Self::Format> {
333 let writable = self.0.get_writable();
334 let file = self.0.open_image(&mut gate).await?;
335 Raw::open_image(file, writable).await
336 }
337
338 fn get_image_path(&self) -> Option<PathBuf> {
339 self.0.get_image_path()
340 }
341
342 fn get_writable(&self) -> bool {
343 self.0.get_writable()
344 }
345
346 fn get_storage_open_options(&self) -> Option<&StorageOpenOptions> {
347 self.0.get_storage_opts()
348 }
349}
350
351pub struct RawCreateBuilder<S: Storage + 'static>(FormatCreateBuilderBase<S>);
353
354#[maybe_async(AFIT)]
355impl<S: Storage + 'static> FormatCreateBuilder<S> for RawCreateBuilder<S> {
356 const FORMAT: Format = Format::Raw;
357 type DriverBuilder = RawOpenBuilder<S>;
358
359 fn new(image: S) -> Self {
360 RawCreateBuilder(FormatCreateBuilderBase::new(image))
361 }
362
363 fn size(mut self, size: u64) -> Self {
364 self.0.set_size(size);
365 self
366 }
367
368 fn preallocate(mut self, prealloc_mode: PreallocateMode) -> Self {
369 self.0.set_preallocate(prealloc_mode);
370 self
371 }
372
373 fn get_size(&self) -> u64 {
374 self.0.get_size()
375 }
376
377 fn get_preallocate(&self) -> PreallocateMode {
378 self.0.get_preallocate()
379 }
380
381 async fn create(self) -> io::Result<()> {
382 self.create_open(DenyImplicitOpenGate::default(), |image| {
383 Ok(Raw::builder(image))
384 })
385 .await?;
386 Ok(())
387 }
388
389 async fn create_open<
390 G: ImplicitOpenGate<S>,
391 F: FnOnce(S) -> io::Result<Self::DriverBuilder>,
392 >(
393 self,
394 open_gate: G,
395 open_builder_fn: F,
396 ) -> io::Result<Raw<S>> {
397 let size = self.0.get_size();
398 let prealloc = self.0.get_preallocate();
399 let image = self.0.get_image();
400
401 if image.size()? > 0 {
403 image.resize(size, storage::PreallocateMode::None).await?;
404 }
405
406 let img = open_builder_fn(image)?.write(true).open(open_gate).await?;
407 if size > 0 {
408 img.resize_grow(size, prealloc).await?;
409 }
410
411 Ok(img)
412 }
413}
414
415#[cfg(test)]
416mod tests {
417 use super::*;
418 use crate::io_buffers::{IoVector, IoVectorMut};
419 use crate::null::Null;
420 use crate::storage::drivers::CommonStorageHelper;
421 use crate::FormatAccess;
422 use std::sync::atomic::AtomicBool;
423
424 #[derive(Debug, Default)]
426 struct ResizeTestStorage {
427 size: AtomicU64,
429
430 fail_resize: AtomicBool,
432
433 #[cfg(feature = "async")]
435 hold_resize_to: AtomicU64,
436
437 #[cfg(feature = "async")]
439 release_resize: tokio::sync::Notify,
440
441 common_storage_helper: CommonStorageHelper,
443 }
444
445 impl ResizeTestStorage {
446 fn new(size: u64) -> Self {
447 ResizeTestStorage {
448 size: size.into(),
449 ..Default::default()
450 }
451 }
452 }
453
454 impl Display for ResizeTestStorage {
455 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
456 write!(f, "resize-test:[{}B]", self.size.load(Ordering::Relaxed))
457 }
458 }
459
460 #[maybe_async(AFIT)]
461 impl Storage for ResizeTestStorage {
462 fn size(&self) -> io::Result<u64> {
463 Ok(self.size.load(Ordering::Relaxed))
464 }
465
466 async unsafe fn pure_readv(
467 &self,
468 mut bufv: IoVectorMut<'_>,
469 _offset: u64,
470 ) -> io::Result<()> {
471 bufv.fill(0);
472 Ok(())
473 }
474
475 async unsafe fn pure_writev(&self, _bufv: IoVector<'_>, _offset: u64) -> io::Result<()> {
476 Ok(())
477 }
478
479 async fn flush(&self) -> io::Result<()> {
480 Ok(())
481 }
482
483 async fn sync(&self) -> io::Result<()> {
484 Ok(())
485 }
486
487 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
488 Ok(())
489 }
490
491 fn get_storage_helper(&self) -> &CommonStorageHelper {
492 &self.common_storage_helper
493 }
494
495 async fn resize(
496 &self,
497 new_size: u64,
498 _prealloc_mode: storage::PreallocateMode,
499 ) -> io::Result<()> {
500 #[cfg(feature = "async")]
501 if self.hold_resize_to.load(Ordering::Relaxed) == new_size {
502 self.release_resize.notified().await;
503 }
504
505 if self.fail_resize.load(Ordering::Relaxed) {
506 return Err(io::Error::other("Resize failed"));
507 }
508
509 self.size.store(new_size, Ordering::Relaxed);
510 Ok(())
511 }
512 }
513
514 fn storage(image: &FormatAccess<ResizeTestStorage>) -> &ResizeTestStorage {
516 image.collect_storage_dependencies()[0]
517 }
518
519 #[maybe_async::test(feature = "sync", async(feature = "async", tokio::test))]
521 async fn test_failed_resize() {
522 let raw = Raw::open_image(ResizeTestStorage::new(1024), true)
523 .await
524 .unwrap();
525 let mut image = FormatAccess::new(raw);
526
527 storage(&image).fail_resize.store(true, Ordering::Relaxed);
528
529 image
530 .resize_grow(2048, PreallocateMode::None)
531 .await
532 .unwrap_err();
533 assert_eq!(image.size(), 1024);
534 assert_eq!(storage(&image).size().unwrap(), 1024);
535
536 image.resize_shrink(512).await.unwrap_err();
537 assert_eq!(image.size(), 1024);
538 assert_eq!(storage(&image).size().unwrap(), 1024);
539
540 storage(&image).fail_resize.store(false, Ordering::Relaxed);
542
543 image
544 .resize_grow(2048, PreallocateMode::None)
545 .await
546 .unwrap();
547 assert_eq!(image.size(), 2048);
548 assert_eq!(storage(&image).size().unwrap(), 2048);
549
550 image.resize_shrink(512).await.unwrap();
551 assert_eq!(image.size(), 512);
552 assert_eq!(storage(&image).size().unwrap(), 512);
553 }
554
555 #[cfg(feature = "async")]
558 #[tokio::test]
559 async fn test_concurrent_grow() {
560 let raw = Raw::open_image(ResizeTestStorage::new(1024), true)
561 .await
562 .unwrap();
563 let image = FormatAccess::new(raw);
564
565 storage(&image)
567 .hold_resize_to
568 .store(2048, Ordering::Relaxed);
569
570 let (small, large, ()) = futures::future::join3(
572 image.resize_grow(2048, PreallocateMode::None),
573 image.resize_grow(4096, PreallocateMode::None),
574 async { storage(&image).release_resize.notify_one() },
575 )
576 .await;
577 small.unwrap();
578 large.unwrap();
579
580 assert_eq!(image.size(), 4096);
581 assert_eq!(storage(&image).size().unwrap(), 4096);
582 }
583
584 #[maybe_async::test(feature = "sync", async(feature = "async", tokio::test))]
587 async fn test_access_beyond_disk_size() {
588 let size = 1024;
589 let raw = Raw::open_image(Null::new(size), true).await.unwrap();
590 let mut image = FormatAccess::new(raw);
591
592 let check = |image: &FormatAccess<Null>, result: io::Result<()>, req: &str| {
593 let err = result.expect_err(req);
594 assert_eq!(err.kind(), io::ErrorKind::UnexpectedEof, "{req}: {err}");
595 let storage_size = image.collect_storage_dependencies()[0].size().unwrap();
596 assert_eq!(storage_size, size, "{req}");
597 };
598
599 for offset in [size, size / 2] {
601 let result = image.write(&[0u8; 4096][..], offset).await;
602 check(&image, result, &format!("write() at {offset}"));
603
604 let result = image.write_zeroes(offset, 4096).await;
605 check(&image, result, &format!("write_zeroes() at {offset}"));
606
607 let result = image.discard_to_zero(offset, 4096).await;
608 check(&image, result, &format!("discard_to_zero() at {offset}"));
609
610 let result = image.discard_to_any(offset, 4096).await;
611 check(&image, result, &format!("discard_to_any() at {offset}"));
612
613 let result = image.discard_to_backing(offset, 4096).await;
614 check(&image, result, &format!("discard_to_backing() at {offset}"));
615
616 let result = image
617 .ensure_data_mapping(offset, 4096, true)
618 .await
619 .map(|_| ());
620 check(
621 &image,
622 result,
623 &format!("ensure_data_mapping() at {offset}"),
624 );
625 }
626
627 image.write(&[0u8; 0][..], size).await.unwrap();
629 image.write_zeroes(size, 0).await.unwrap();
630 image.discard_to_zero(size, 0).await.unwrap();
631 image.discard_to_any(size, 0).await.unwrap();
632 image.discard_to_backing(size, 0).await.unwrap();
633
634 for offset in [size, 0] {
636 let (_, _, length) = image.ensure_data_mapping(offset, 0, true).await.unwrap();
637 assert_eq!(length, 0, "ensure_data_mapping() at {offset}");
638 }
639
640 assert_eq!(image.size(), size);
641 }
642}