1pub mod drivers;
7pub mod ext;
8
9use crate::io_buffers::{IoBuffer, IoVector, IoVectorMut};
10use drivers::CommonStorageHelper;
11use maybe_async::maybe_async;
12use std::any::Any;
13use std::fmt::{Debug, Display};
14#[cfg(feature = "async")]
15use std::future::Future;
16use std::path::{Path, PathBuf};
17#[cfg(feature = "async")]
18use std::pin::Pin;
19use std::sync::Arc;
20use std::{cmp, io};
21
22#[derive(Clone, Debug, Default)]
24pub struct StorageOpenOptions {
25 pub(crate) filename: Option<PathBuf>,
27
28 pub(crate) writable: bool,
30
31 pub(crate) direct: bool,
33
34 #[cfg(target_os = "macos")]
36 pub(crate) relaxed_sync: bool,
37}
38
39#[derive(Clone, Debug)]
41pub struct StorageCreateOptions {
42 pub(crate) open_opts: StorageOpenOptions,
46
47 pub(crate) size: u64,
49
50 pub(crate) prealloc_mode: PreallocateMode,
52
53 pub(crate) overwrite: bool,
55}
56
57#[maybe_async(AFIT)]
59pub trait Storage: Debug + Display + Send + Sized + Sync {
60 #[allow(async_fn_in_trait)] async fn open(_opts: StorageOpenOptions) -> io::Result<Self> {
65 Err(io::Error::new(
66 io::ErrorKind::Unsupported,
67 format!(
68 "Cannot open storage objects of type {}",
69 std::any::type_name::<Self>()
70 ),
71 ))
72 }
73
74 #[cfg(feature = "sync-wrappers")]
76 fn open_sync(opts: StorageOpenOptions) -> io::Result<Self> {
77 tokio::runtime::Builder::new_current_thread()
78 .build()?
79 .block_on(Self::open(opts))
80 }
81
82 #[allow(async_fn_in_trait)] async fn create_open(_opts: StorageCreateOptions) -> io::Result<Self> {
89 Err(io::Error::new(
90 io::ErrorKind::Unsupported,
91 format!(
92 "Cannot create storage objects of type {}",
93 std::any::type_name::<Self>()
94 ),
95 ))
96 }
97
98 #[allow(async_fn_in_trait)] async fn create(opts: StorageCreateOptions) -> io::Result<()> {
103 Self::create_open(opts).await?;
104 Ok(())
105 }
106
107 fn mem_align(&self) -> usize {
109 1
110 }
111
112 fn req_align(&self) -> usize {
114 1
115 }
116
117 fn zero_align(&self) -> usize {
121 self.req_align()
122 }
123
124 fn discard_align(&self) -> usize {
128 self.req_align()
129 }
130
131 fn size(&self) -> io::Result<u64>;
133
134 fn resolve_relative_path<P: AsRef<Path>>(&self, _relative: P) -> io::Result<PathBuf> {
144 Err(io::ErrorKind::Unsupported.into())
145 }
146
147 fn get_filename(&self) -> Option<PathBuf> {
152 None
153 }
154
155 #[allow(async_fn_in_trait)] async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()>;
168
169 #[allow(async_fn_in_trait)] async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()>;
185
186 #[allow(async_fn_in_trait)] async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
204 unsafe { pure_write_full_zeroes(self, offset, length).await }
205 }
206
207 #[allow(async_fn_in_trait)] async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
226 unsafe { pure_write_full_zeroes(self, offset, length).await }
227 }
228
229 #[allow(async_fn_in_trait)] async unsafe fn pure_discard(&self, _offset: u64, _length: u64) -> io::Result<()> {
244 Ok(())
245 }
246
247 #[allow(async_fn_in_trait)] async fn flush(&self) -> io::Result<()>;
256
257 #[allow(async_fn_in_trait)] async fn sync(&self) -> io::Result<()>;
263
264 #[allow(async_fn_in_trait)] async unsafe fn invalidate_cache(&self) -> io::Result<()>;
274
275 fn get_storage_helper(&self) -> &CommonStorageHelper;
278
279 #[allow(async_fn_in_trait)] async fn resize(&self, _new_size: u64, _prealloc_mode: PreallocateMode) -> io::Result<()> {
289 Err(io::ErrorKind::Unsupported.into())
290 }
291}
292
293pub trait DynStorage: Any + Debug + Display + Send + Sync {
309 fn dyn_mem_align(&self) -> usize;
311
312 fn dyn_req_align(&self) -> usize;
314
315 fn dyn_zero_align(&self) -> usize;
317
318 fn dyn_discard_align(&self) -> usize;
320
321 fn dyn_size(&self) -> io::Result<u64>;
323
324 fn dyn_resolve_relative_path(&self, relative: &Path) -> io::Result<PathBuf>;
326
327 fn dyn_get_filename(&self) -> Option<PathBuf>;
329
330 #[cfg(feature = "async")]
335 unsafe fn dyn_pure_readv<'a>(
336 &'a self,
337 bufv: IoVectorMut<'a>,
338 offset: u64,
339 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>>;
340
341 #[cfg(feature = "sync")]
346 unsafe fn dyn_pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()>;
347
348 #[cfg(feature = "async")]
353 unsafe fn dyn_pure_writev<'a>(
354 &'a self,
355 bufv: IoVector<'a>,
356 offset: u64,
357 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>>;
358
359 #[cfg(feature = "sync")]
364 unsafe fn dyn_pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()>;
365
366 #[cfg(feature = "async")]
371 unsafe fn dyn_pure_write_zeroes(
372 &self,
373 offset: u64,
374 length: u64,
375 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
376
377 #[cfg(feature = "sync")]
382 unsafe fn dyn_pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()>;
383
384 #[cfg(feature = "async")]
389 unsafe fn dyn_pure_write_allocated_zeroes(
390 &self,
391 offset: u64,
392 length: u64,
393 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
394
395 #[cfg(feature = "sync")]
400 unsafe fn dyn_pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()>;
401
402 #[cfg(feature = "async")]
407 unsafe fn dyn_pure_discard(
408 &self,
409 offset: u64,
410 length: u64,
411 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
412
413 #[cfg(feature = "sync")]
418 unsafe fn dyn_pure_discard(&self, offset: u64, length: u64) -> io::Result<()>;
419
420 #[cfg(feature = "async")]
422 fn dyn_flush(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
423
424 #[cfg(feature = "sync")]
426 fn dyn_flush(&self) -> io::Result<()>;
427
428 #[cfg(feature = "async")]
430 fn dyn_sync(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
431
432 #[cfg(feature = "sync")]
434 fn dyn_sync(&self) -> io::Result<()>;
435
436 #[cfg(feature = "async")]
441 unsafe fn dyn_invalidate_cache(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
442
443 #[cfg(feature = "sync")]
448 unsafe fn dyn_invalidate_cache(&self) -> io::Result<()>;
449
450 fn dyn_get_storage_helper(&self) -> &CommonStorageHelper;
452
453 #[cfg(feature = "async")]
455 fn dyn_resize(
456 &self,
457 new_size: u64,
458 prealloc_mode: PreallocateMode,
459 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
460
461 #[cfg(feature = "sync")]
463 fn dyn_resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()>;
464}
465
466#[derive(Clone, Copy, Debug, Eq, PartialEq)]
471#[non_exhaustive]
472pub enum PreallocateMode {
473 None,
477
478 Zero,
483
484 Allocate,
488
489 WriteData,
493}
494
495#[maybe_async(AFIT)]
496impl<S: Storage> Storage for &S {
497 fn mem_align(&self) -> usize {
498 (*self).mem_align()
499 }
500
501 fn req_align(&self) -> usize {
502 (*self).req_align()
503 }
504
505 fn zero_align(&self) -> usize {
506 (*self).zero_align()
507 }
508
509 fn discard_align(&self) -> usize {
510 (*self).discard_align()
511 }
512
513 fn size(&self) -> io::Result<u64> {
514 (*self).size()
515 }
516
517 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
518 (*self).resolve_relative_path(relative)
519 }
520
521 fn get_filename(&self) -> Option<PathBuf> {
522 (*self).get_filename()
523 }
524
525 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
526 unsafe { (*self).pure_readv(bufv, offset).await }
527 }
528
529 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
530 unsafe { (*self).pure_writev(bufv, offset).await }
531 }
532
533 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
534 unsafe { (*self).pure_write_zeroes(offset, length).await }
535 }
536
537 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
538 unsafe { (*self).pure_write_allocated_zeroes(offset, length).await }
539 }
540
541 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
542 unsafe { (*self).pure_discard(offset, length).await }
543 }
544
545 async fn flush(&self) -> io::Result<()> {
546 (*self).flush().await
547 }
548
549 async fn sync(&self) -> io::Result<()> {
550 (*self).sync().await
551 }
552
553 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
554 unsafe { (*self).invalidate_cache().await }
555 }
556
557 fn get_storage_helper(&self) -> &CommonStorageHelper {
558 (*self).get_storage_helper()
559 }
560
561 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
562 (*self).resize(new_size, prealloc_mode).await
563 }
564}
565
566impl<S: Storage + 'static> DynStorage for S {
567 fn dyn_mem_align(&self) -> usize {
568 <S as Storage>::mem_align(self)
569 }
570
571 fn dyn_req_align(&self) -> usize {
572 <S as Storage>::req_align(self)
573 }
574
575 fn dyn_zero_align(&self) -> usize {
576 <S as Storage>::zero_align(self)
577 }
578
579 fn dyn_discard_align(&self) -> usize {
580 <S as Storage>::discard_align(self)
581 }
582
583 fn dyn_size(&self) -> io::Result<u64> {
584 <S as Storage>::size(self)
585 }
586
587 fn dyn_resolve_relative_path(&self, relative: &Path) -> io::Result<PathBuf> {
588 <S as Storage>::resolve_relative_path(self, relative)
589 }
590
591 fn dyn_get_filename(&self) -> Option<PathBuf> {
592 <S as Storage>::get_filename(self)
593 }
594
595 #[cfg(feature = "async")]
596 unsafe fn dyn_pure_readv<'a>(
597 &'a self,
598 bufv: IoVectorMut<'a>,
599 offset: u64,
600 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>> {
601 Box::pin(unsafe { <S as Storage>::pure_readv(self, bufv, offset) })
602 }
603
604 #[cfg(feature = "sync")]
605 unsafe fn dyn_pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
606 unsafe { <S as Storage>::pure_readv(self, bufv, offset) }
607 }
608
609 #[cfg(feature = "async")]
610 unsafe fn dyn_pure_writev<'a>(
611 &'a self,
612 bufv: IoVector<'a>,
613 offset: u64,
614 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>> {
615 Box::pin(unsafe { <S as Storage>::pure_writev(self, bufv, offset) })
616 }
617
618 #[cfg(feature = "sync")]
619 unsafe fn dyn_pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
620 unsafe { <S as Storage>::pure_writev(self, bufv, offset) }
621 }
622
623 #[cfg(feature = "async")]
624 unsafe fn dyn_pure_write_zeroes(
625 &self,
626 offset: u64,
627 length: u64,
628 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
629 Box::pin(unsafe { <S as Storage>::pure_write_zeroes(self, offset, length) })
630 }
631
632 #[cfg(feature = "sync")]
633 unsafe fn dyn_pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
634 unsafe { <S as Storage>::pure_write_zeroes(self, offset, length) }
635 }
636
637 #[cfg(feature = "async")]
638 unsafe fn dyn_pure_write_allocated_zeroes(
639 &self,
640 offset: u64,
641 length: u64,
642 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
643 Box::pin(unsafe { <S as Storage>::pure_write_allocated_zeroes(self, offset, length) })
644 }
645
646 #[cfg(feature = "sync")]
647 unsafe fn dyn_pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
648 unsafe { <S as Storage>::pure_write_allocated_zeroes(self, offset, length) }
649 }
650
651 #[cfg(feature = "async")]
652 unsafe fn dyn_pure_discard(
653 &self,
654 offset: u64,
655 length: u64,
656 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
657 Box::pin(unsafe { <S as Storage>::pure_discard(self, offset, length) })
658 }
659
660 #[cfg(feature = "sync")]
661 unsafe fn dyn_pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
662 unsafe { <S as Storage>::pure_discard(self, offset, length) }
663 }
664
665 #[cfg(feature = "async")]
666 fn dyn_flush(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
667 Box::pin(<S as Storage>::flush(self))
668 }
669
670 #[cfg(feature = "sync")]
671 fn dyn_flush(&self) -> io::Result<()> {
672 <S as Storage>::flush(self)
673 }
674
675 #[cfg(feature = "async")]
676 fn dyn_sync(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
677 Box::pin(<S as Storage>::sync(self))
678 }
679
680 #[cfg(feature = "sync")]
681 fn dyn_sync(&self) -> io::Result<()> {
682 <S as Storage>::sync(self)
683 }
684
685 #[cfg(feature = "async")]
686 unsafe fn dyn_invalidate_cache(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
687 Box::pin(unsafe { <S as Storage>::invalidate_cache(self) })
688 }
689
690 #[cfg(feature = "sync")]
691 unsafe fn dyn_invalidate_cache(&self) -> io::Result<()> {
692 unsafe { <S as Storage>::invalidate_cache(self) }
693 }
694
695 fn dyn_get_storage_helper(&self) -> &CommonStorageHelper {
696 <S as Storage>::get_storage_helper(self)
697 }
698
699 #[cfg(feature = "async")]
700 fn dyn_resize(
701 &self,
702 new_size: u64,
703 prealloc_mode: PreallocateMode,
704 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
705 Box::pin(<S as Storage>::resize(self, new_size, prealloc_mode))
706 }
707
708 #[cfg(feature = "sync")]
709 fn dyn_resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
710 <S as Storage>::resize(self, new_size, prealloc_mode)
711 }
712}
713
714#[maybe_async(AFIT)]
715impl Storage for Box<dyn DynStorage> {
716 async fn open(opts: StorageOpenOptions) -> io::Result<Self> {
717 Ok(Box::new(crate::file::File::open(opts).await?))
721 }
722
723 async fn create_open(opts: StorageCreateOptions) -> io::Result<Self> {
724 Ok(Box::new(crate::file::File::create_open(opts).await?))
726 }
727
728 fn mem_align(&self) -> usize {
729 self.as_ref().dyn_mem_align()
730 }
731
732 fn req_align(&self) -> usize {
733 self.as_ref().dyn_req_align()
734 }
735
736 fn zero_align(&self) -> usize {
737 self.as_ref().dyn_zero_align()
738 }
739
740 fn discard_align(&self) -> usize {
741 self.as_ref().dyn_discard_align()
742 }
743
744 fn size(&self) -> io::Result<u64> {
745 self.as_ref().dyn_size()
746 }
747
748 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
749 self.as_ref().dyn_resolve_relative_path(relative.as_ref())
750 }
751
752 fn get_filename(&self) -> Option<PathBuf> {
753 self.as_ref().dyn_get_filename()
754 }
755
756 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
757 unsafe { self.as_ref().dyn_pure_readv(bufv, offset).await }
758 }
759
760 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
761 unsafe { self.as_ref().dyn_pure_writev(bufv, offset).await }
762 }
763
764 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
765 unsafe { self.as_ref().dyn_pure_write_zeroes(offset, length).await }
766 }
767
768 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
769 unsafe {
770 self.as_ref()
771 .dyn_pure_write_allocated_zeroes(offset, length)
772 .await
773 }
774 }
775
776 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
777 unsafe { self.as_ref().dyn_pure_discard(offset, length).await }
778 }
779
780 async fn flush(&self) -> io::Result<()> {
781 self.as_ref().dyn_flush().await
782 }
783
784 async fn sync(&self) -> io::Result<()> {
785 self.as_ref().dyn_sync().await
786 }
787
788 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
789 unsafe { self.as_ref().dyn_invalidate_cache().await }
790 }
791
792 fn get_storage_helper(&self) -> &CommonStorageHelper {
793 self.as_ref().dyn_get_storage_helper()
794 }
795
796 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
797 self.as_ref().dyn_resize(new_size, prealloc_mode).await
798 }
799}
800
801#[maybe_async(AFIT)]
802impl Storage for Arc<dyn DynStorage> {
803 async fn open(opts: StorageOpenOptions) -> io::Result<Self> {
804 Box::<dyn DynStorage>::open(opts).await.map(Into::into)
805 }
806
807 async fn create_open(opts: StorageCreateOptions) -> io::Result<Self> {
808 Box::<dyn DynStorage>::create_open(opts)
809 .await
810 .map(Into::into)
811 }
812
813 fn mem_align(&self) -> usize {
814 self.as_ref().dyn_mem_align()
815 }
816
817 fn req_align(&self) -> usize {
818 self.as_ref().dyn_req_align()
819 }
820
821 fn zero_align(&self) -> usize {
822 self.as_ref().dyn_zero_align()
823 }
824
825 fn discard_align(&self) -> usize {
826 self.as_ref().dyn_discard_align()
827 }
828
829 fn size(&self) -> io::Result<u64> {
830 self.as_ref().dyn_size()
831 }
832
833 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
834 self.as_ref().dyn_resolve_relative_path(relative.as_ref())
835 }
836
837 fn get_filename(&self) -> Option<PathBuf> {
838 self.as_ref().dyn_get_filename()
839 }
840
841 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
842 unsafe { self.as_ref().dyn_pure_readv(bufv, offset) }.await
843 }
844
845 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
846 unsafe { self.as_ref().dyn_pure_writev(bufv, offset) }.await
847 }
848
849 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
850 unsafe { self.as_ref().dyn_pure_write_zeroes(offset, length) }.await
851 }
852
853 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
854 unsafe {
855 self.as_ref()
856 .dyn_pure_write_allocated_zeroes(offset, length)
857 }
858 .await
859 }
860
861 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
862 unsafe { self.as_ref().dyn_pure_discard(offset, length) }.await
863 }
864
865 async fn flush(&self) -> io::Result<()> {
866 self.as_ref().dyn_flush().await
867 }
868
869 async fn sync(&self) -> io::Result<()> {
870 self.as_ref().dyn_sync().await
871 }
872
873 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
874 unsafe { self.as_ref().dyn_invalidate_cache().await }
875 }
876
877 fn get_storage_helper(&self) -> &CommonStorageHelper {
878 self.as_ref().dyn_get_storage_helper()
879 }
880
881 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
882 self.as_ref().dyn_resize(new_size, prealloc_mode).await
883 }
884}
885
886impl StorageOpenOptions {
887 pub fn new() -> Self {
889 StorageOpenOptions::default()
890 }
891
892 pub fn filename<P: AsRef<Path>>(mut self, filename: P) -> Self {
894 self.filename = Some(filename.as_ref().to_owned());
895 self
896 }
897
898 pub fn write(mut self, write: bool) -> Self {
900 self.writable = write;
901 self
902 }
903
904 pub fn direct(mut self, direct: bool) -> Self {
906 self.direct = direct;
907 self
908 }
909
910 #[cfg(target_os = "macos")]
917 pub fn relaxed_sync(mut self, relaxed_sync: bool) -> Self {
918 self.relaxed_sync = relaxed_sync;
919 self
920 }
921
922 pub fn get_filename(&self) -> Option<&Path> {
924 self.filename.as_deref()
925 }
926
927 pub fn get_writable(&self) -> bool {
929 self.writable
930 }
931
932 pub fn get_direct(&self) -> bool {
934 self.direct
935 }
936
937 #[cfg(target_os = "macos")]
939 pub fn get_relaxed_sync(&self) -> bool {
940 self.relaxed_sync
941 }
942}
943
944impl StorageCreateOptions {
945 pub fn new() -> Self {
947 StorageCreateOptions::default()
948 }
949
950 pub fn filename<P: AsRef<Path>>(self, filename: P) -> Self {
952 self.modify_open_opts(|o| o.filename(filename))
953 }
954
955 pub fn size(mut self, size: u64) -> Self {
957 self.size = size;
958 self
959 }
960
961 pub fn preallocate(mut self, prealloc_mode: PreallocateMode) -> Self {
963 self.prealloc_mode = prealloc_mode;
964 self
965 }
966
967 pub fn overwrite(mut self, overwrite: bool) -> Self {
969 self.overwrite = overwrite;
970 self
971 }
972
973 pub fn modify_open_opts<F: FnOnce(StorageOpenOptions) -> StorageOpenOptions>(
975 mut self,
976 f: F,
977 ) -> Self {
978 self.open_opts = f(self.open_opts);
979 self
980 }
981
982 pub fn get_filename(&self) -> Option<&Path> {
984 self.open_opts.filename.as_deref()
985 }
986
987 pub fn get_size(&self) -> u64 {
989 self.size
990 }
991
992 pub fn get_preallocate(&self) -> PreallocateMode {
994 self.prealloc_mode
995 }
996
997 pub fn get_overwrite(&self) -> bool {
999 self.overwrite
1000 }
1001
1002 pub fn get_open_options(self) -> StorageOpenOptions {
1004 self.open_opts
1005 }
1006}
1007
1008impl Default for StorageCreateOptions {
1009 fn default() -> Self {
1010 StorageCreateOptions {
1011 open_opts: Default::default(),
1012 size: 0,
1013 prealloc_mode: PreallocateMode::None,
1014 overwrite: false,
1015 }
1016 }
1017}
1018
1019#[maybe_async]
1031async unsafe fn pure_write_full_zeroes<S: Storage>(
1032 storage: S,
1033 mut offset: u64,
1034 mut length: u64,
1035) -> io::Result<()> {
1036 let req_align = storage.req_align() as u64;
1037 if !(offset | length).is_multiple_of(req_align) {
1038 return Err(io::Error::new(
1039 io::ErrorKind::InvalidInput,
1040 "write_zeroes fallback: offset/length not aligned to request alignment",
1041 ));
1042 }
1043
1044 let mem_align = storage.mem_align() as u64;
1045 let max_chunk_len = cmp::max(cmp::max(req_align, mem_align), 1048576);
1046 let buflen = cmp::min(length, max_chunk_len) as usize;
1047 let mut buf = IoBuffer::new(buflen, storage.mem_align())?;
1048 buf.as_mut().into_slice().fill(0);
1049
1050 while length > 0 {
1051 let chunk_len = cmp::min(length, max_chunk_len) as usize;
1052 unsafe {
1053 storage
1054 .pure_writev(buf.as_ref_range(0..chunk_len).into(), offset)
1055 .await
1056 }?;
1057 offset += chunk_len as u64;
1058 length -= chunk_len as u64;
1059 }
1060
1061 Ok(())
1062}