1pub mod drivers;
7pub mod ext;
8
9use crate::io_buffers::{IoVector, IoVectorMut};
10use drivers::CommonStorageHelper;
11use std::any::Any;
12use std::fmt::{Debug, Display};
13use std::future::Future;
14use std::io;
15use std::path::{Path, PathBuf};
16use std::pin::Pin;
17use std::sync::Arc;
18
19#[derive(Clone, Debug, Default)]
21pub struct StorageOpenOptions {
22 pub(crate) filename: Option<PathBuf>,
24
25 pub(crate) writable: bool,
27
28 pub(crate) direct: bool,
30
31 #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "musl")))]
33 pub(crate) write_dontcache: bool,
34
35 #[cfg(target_os = "macos")]
37 pub(crate) relaxed_sync: bool,
38}
39
40#[derive(Clone, Debug)]
42pub struct StorageCreateOptions {
43 pub(crate) open_opts: StorageOpenOptions,
47
48 pub(crate) size: u64,
50
51 pub(crate) prealloc_mode: PreallocateMode,
53
54 pub(crate) overwrite: bool,
56}
57
58pub 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 {
119 1
120 }
121
122 fn discard_align(&self) -> usize {
124 1
125 }
126
127 fn size(&self) -> io::Result<u64>;
129
130 fn resolve_relative_path<P: AsRef<Path>>(&self, _relative: P) -> io::Result<PathBuf> {
140 Err(io::ErrorKind::Unsupported.into())
141 }
142
143 fn get_filename(&self) -> Option<PathBuf> {
148 None
149 }
150
151 #[allow(async_fn_in_trait)] async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()>;
164
165 #[allow(async_fn_in_trait)] async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()>;
181
182 #[allow(async_fn_in_trait)] async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
195 ext::write_full_zeroes(self, offset, length).await
196 }
197
198 #[allow(async_fn_in_trait)] async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
212 ext::write_full_zeroes(self, offset, length).await
213 }
214
215 #[allow(async_fn_in_trait)] async unsafe fn pure_discard(&self, _offset: u64, _length: u64) -> io::Result<()> {
230 Ok(())
231 }
232
233 #[allow(async_fn_in_trait)] async fn flush(&self) -> io::Result<()>;
242
243 #[allow(async_fn_in_trait)] async fn sync(&self) -> io::Result<()>;
249
250 #[allow(async_fn_in_trait)] async unsafe fn invalidate_cache(&self) -> io::Result<()>;
260
261 fn get_storage_helper(&self) -> &CommonStorageHelper;
264
265 #[allow(async_fn_in_trait)] async fn resize(&self, _new_size: u64, _prealloc_mode: PreallocateMode) -> io::Result<()> {
275 Err(io::ErrorKind::Unsupported.into())
276 }
277}
278
279pub trait DynStorage: Any + Debug + Display + Send + Sync {
293 fn dyn_mem_align(&self) -> usize;
295
296 fn dyn_req_align(&self) -> usize;
298
299 fn dyn_zero_align(&self) -> usize;
301
302 fn dyn_discard_align(&self) -> usize;
304
305 fn dyn_size(&self) -> io::Result<u64>;
307
308 fn dyn_resolve_relative_path(&self, relative: &Path) -> io::Result<PathBuf>;
310
311 fn dyn_get_filename(&self) -> Option<PathBuf>;
313
314 unsafe fn dyn_pure_readv<'a>(
319 &'a self,
320 bufv: IoVectorMut<'a>,
321 offset: u64,
322 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>>;
323
324 unsafe fn dyn_pure_writev<'a>(
329 &'a self,
330 bufv: IoVector<'a>,
331 offset: u64,
332 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>>;
333
334 unsafe fn dyn_pure_write_zeroes(
339 &self,
340 offset: u64,
341 length: u64,
342 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
343
344 unsafe fn dyn_pure_write_allocated_zeroes(
349 &self,
350 offset: u64,
351 length: u64,
352 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
353
354 unsafe fn dyn_pure_discard(
359 &self,
360 offset: u64,
361 length: u64,
362 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
363
364 fn dyn_flush(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
366
367 fn dyn_sync(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
369
370 unsafe fn dyn_invalidate_cache(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
375
376 fn dyn_get_storage_helper(&self) -> &CommonStorageHelper;
378
379 fn dyn_resize(
381 &self,
382 new_size: u64,
383 prealloc_mode: PreallocateMode,
384 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>>;
385}
386
387#[derive(Clone, Copy, Debug, Eq, PartialEq)]
392#[non_exhaustive]
393pub enum PreallocateMode {
394 None,
398
399 Zero,
404
405 Allocate,
409
410 WriteData,
414}
415
416impl<S: Storage> Storage for &S {
417 fn mem_align(&self) -> usize {
418 (*self).mem_align()
419 }
420
421 fn req_align(&self) -> usize {
422 (*self).req_align()
423 }
424
425 fn zero_align(&self) -> usize {
426 (*self).zero_align()
427 }
428
429 fn discard_align(&self) -> usize {
430 (*self).discard_align()
431 }
432
433 fn size(&self) -> io::Result<u64> {
434 (*self).size()
435 }
436
437 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
438 (*self).resolve_relative_path(relative)
439 }
440
441 fn get_filename(&self) -> Option<PathBuf> {
442 (*self).get_filename()
443 }
444
445 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
446 unsafe { (*self).pure_readv(bufv, offset).await }
447 }
448
449 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
450 unsafe { (*self).pure_writev(bufv, offset).await }
451 }
452
453 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
454 unsafe { (*self).pure_write_zeroes(offset, length).await }
455 }
456
457 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
458 unsafe { (*self).pure_write_allocated_zeroes(offset, length).await }
459 }
460
461 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
462 unsafe { (*self).pure_discard(offset, length).await }
463 }
464
465 async fn flush(&self) -> io::Result<()> {
466 (*self).flush().await
467 }
468
469 async fn sync(&self) -> io::Result<()> {
470 (*self).sync().await
471 }
472
473 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
474 unsafe { (*self).invalidate_cache().await }
475 }
476
477 fn get_storage_helper(&self) -> &CommonStorageHelper {
478 (*self).get_storage_helper()
479 }
480
481 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
482 (*self).resize(new_size, prealloc_mode).await
483 }
484}
485
486impl<S: Storage + 'static> DynStorage for S {
487 fn dyn_mem_align(&self) -> usize {
488 <S as Storage>::mem_align(self)
489 }
490
491 fn dyn_req_align(&self) -> usize {
492 <S as Storage>::req_align(self)
493 }
494
495 fn dyn_zero_align(&self) -> usize {
496 <S as Storage>::zero_align(self)
497 }
498
499 fn dyn_discard_align(&self) -> usize {
500 <S as Storage>::discard_align(self)
501 }
502
503 fn dyn_size(&self) -> io::Result<u64> {
504 <S as Storage>::size(self)
505 }
506
507 fn dyn_resolve_relative_path(&self, relative: &Path) -> io::Result<PathBuf> {
508 <S as Storage>::resolve_relative_path(self, relative)
509 }
510
511 fn dyn_get_filename(&self) -> Option<PathBuf> {
512 <S as Storage>::get_filename(self)
513 }
514
515 unsafe fn dyn_pure_readv<'a>(
516 &'a self,
517 bufv: IoVectorMut<'a>,
518 offset: u64,
519 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>> {
520 Box::pin(unsafe { <S as Storage>::pure_readv(self, bufv, offset) })
521 }
522
523 unsafe fn dyn_pure_writev<'a>(
524 &'a self,
525 bufv: IoVector<'a>,
526 offset: u64,
527 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + 'a>> {
528 Box::pin(unsafe { <S as Storage>::pure_writev(self, bufv, offset) })
529 }
530
531 unsafe fn dyn_pure_write_zeroes(
532 &self,
533 offset: u64,
534 length: u64,
535 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
536 Box::pin(unsafe { <S as Storage>::pure_write_zeroes(self, offset, length) })
537 }
538
539 unsafe fn dyn_pure_write_allocated_zeroes(
540 &self,
541 offset: u64,
542 length: u64,
543 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
544 Box::pin(unsafe { <S as Storage>::pure_write_allocated_zeroes(self, offset, length) })
545 }
546
547 unsafe fn dyn_pure_discard(
548 &self,
549 offset: u64,
550 length: u64,
551 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
552 Box::pin(unsafe { <S as Storage>::pure_discard(self, offset, length) })
553 }
554
555 fn dyn_flush(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
556 Box::pin(<S as Storage>::flush(self))
557 }
558
559 fn dyn_sync(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
560 Box::pin(<S as Storage>::sync(self))
561 }
562
563 unsafe fn dyn_invalidate_cache(&self) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
564 Box::pin(unsafe { <S as Storage>::invalidate_cache(self) })
565 }
566
567 fn dyn_get_storage_helper(&self) -> &CommonStorageHelper {
568 <S as Storage>::get_storage_helper(self)
569 }
570
571 fn dyn_resize(
572 &self,
573 new_size: u64,
574 prealloc_mode: PreallocateMode,
575 ) -> Pin<Box<dyn Future<Output = io::Result<()>> + '_>> {
576 Box::pin(<S as Storage>::resize(self, new_size, prealloc_mode))
577 }
578}
579
580impl Storage for Box<dyn DynStorage> {
581 async fn open(opts: StorageOpenOptions) -> io::Result<Self> {
582 Ok(Box::new(crate::file::File::open(opts).await?))
586 }
587
588 async fn create_open(opts: StorageCreateOptions) -> io::Result<Self> {
589 Ok(Box::new(crate::file::File::create_open(opts).await?))
591 }
592
593 fn mem_align(&self) -> usize {
594 self.as_ref().dyn_mem_align()
595 }
596
597 fn req_align(&self) -> usize {
598 self.as_ref().dyn_req_align()
599 }
600
601 fn zero_align(&self) -> usize {
602 self.as_ref().dyn_zero_align()
603 }
604
605 fn discard_align(&self) -> usize {
606 self.as_ref().dyn_discard_align()
607 }
608
609 fn size(&self) -> io::Result<u64> {
610 self.as_ref().dyn_size()
611 }
612
613 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
614 self.as_ref().dyn_resolve_relative_path(relative.as_ref())
615 }
616
617 fn get_filename(&self) -> Option<PathBuf> {
618 self.as_ref().dyn_get_filename()
619 }
620
621 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
622 unsafe { self.as_ref().dyn_pure_readv(bufv, offset).await }
623 }
624
625 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
626 unsafe { self.as_ref().dyn_pure_writev(bufv, offset).await }
627 }
628
629 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
630 unsafe { self.as_ref().dyn_pure_write_zeroes(offset, length).await }
631 }
632
633 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
634 unsafe {
635 self.as_ref()
636 .dyn_pure_write_allocated_zeroes(offset, length)
637 .await
638 }
639 }
640
641 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
642 unsafe { self.as_ref().dyn_pure_discard(offset, length).await }
643 }
644
645 async fn flush(&self) -> io::Result<()> {
646 self.as_ref().dyn_flush().await
647 }
648
649 async fn sync(&self) -> io::Result<()> {
650 self.as_ref().dyn_sync().await
651 }
652
653 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
654 unsafe { self.as_ref().dyn_invalidate_cache().await }
655 }
656
657 fn get_storage_helper(&self) -> &CommonStorageHelper {
658 self.as_ref().dyn_get_storage_helper()
659 }
660
661 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
662 self.as_ref().dyn_resize(new_size, prealloc_mode).await
663 }
664}
665
666impl Storage for Arc<dyn DynStorage> {
667 async fn open(opts: StorageOpenOptions) -> io::Result<Self> {
668 Box::<dyn DynStorage>::open(opts).await.map(Into::into)
669 }
670
671 async fn create_open(opts: StorageCreateOptions) -> io::Result<Self> {
672 Box::<dyn DynStorage>::create_open(opts)
673 .await
674 .map(Into::into)
675 }
676
677 fn mem_align(&self) -> usize {
678 self.as_ref().dyn_mem_align()
679 }
680
681 fn req_align(&self) -> usize {
682 self.as_ref().dyn_req_align()
683 }
684
685 fn zero_align(&self) -> usize {
686 self.as_ref().dyn_zero_align()
687 }
688
689 fn discard_align(&self) -> usize {
690 self.as_ref().dyn_discard_align()
691 }
692
693 fn size(&self) -> io::Result<u64> {
694 self.as_ref().dyn_size()
695 }
696
697 fn resolve_relative_path<P: AsRef<Path>>(&self, relative: P) -> io::Result<PathBuf> {
698 self.as_ref().dyn_resolve_relative_path(relative.as_ref())
699 }
700
701 fn get_filename(&self) -> Option<PathBuf> {
702 self.as_ref().dyn_get_filename()
703 }
704
705 async unsafe fn pure_readv(&self, bufv: IoVectorMut<'_>, offset: u64) -> io::Result<()> {
706 unsafe { self.as_ref().dyn_pure_readv(bufv, offset) }.await
707 }
708
709 async unsafe fn pure_writev(&self, bufv: IoVector<'_>, offset: u64) -> io::Result<()> {
710 unsafe { self.as_ref().dyn_pure_writev(bufv, offset) }.await
711 }
712
713 async unsafe fn pure_write_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
714 unsafe { self.as_ref().dyn_pure_write_zeroes(offset, length) }.await
715 }
716
717 async unsafe fn pure_write_allocated_zeroes(&self, offset: u64, length: u64) -> io::Result<()> {
718 unsafe {
719 self.as_ref()
720 .dyn_pure_write_allocated_zeroes(offset, length)
721 }
722 .await
723 }
724
725 async unsafe fn pure_discard(&self, offset: u64, length: u64) -> io::Result<()> {
726 unsafe { self.as_ref().dyn_pure_discard(offset, length) }.await
727 }
728
729 async fn flush(&self) -> io::Result<()> {
730 self.as_ref().dyn_flush().await
731 }
732
733 async fn sync(&self) -> io::Result<()> {
734 self.as_ref().dyn_sync().await
735 }
736
737 async unsafe fn invalidate_cache(&self) -> io::Result<()> {
738 unsafe { self.as_ref().dyn_invalidate_cache().await }
739 }
740
741 fn get_storage_helper(&self) -> &CommonStorageHelper {
742 self.as_ref().dyn_get_storage_helper()
743 }
744
745 async fn resize(&self, new_size: u64, prealloc_mode: PreallocateMode) -> io::Result<()> {
746 self.as_ref().dyn_resize(new_size, prealloc_mode).await
747 }
748}
749
750impl StorageOpenOptions {
751 pub fn new() -> Self {
753 StorageOpenOptions::default()
754 }
755
756 pub fn filename<P: AsRef<Path>>(mut self, filename: P) -> Self {
758 self.filename = Some(filename.as_ref().to_owned());
759 self
760 }
761
762 pub fn write(mut self, write: bool) -> Self {
764 self.writable = write;
765 self
766 }
767
768 pub fn direct(mut self, direct: bool) -> Self {
770 self.direct = direct;
771 self
772 }
773
774 #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "musl")))]
782 pub fn write_dontcache(mut self, write_dontcache: bool) -> Self {
783 self.write_dontcache = write_dontcache;
784 self
785 }
786
787 #[cfg(target_os = "macos")]
794 pub fn relaxed_sync(mut self, relaxed_sync: bool) -> Self {
795 self.relaxed_sync = relaxed_sync;
796 self
797 }
798
799 pub fn get_filename(&self) -> Option<&Path> {
801 self.filename.as_deref()
802 }
803
804 pub fn get_writable(&self) -> bool {
806 self.writable
807 }
808
809 pub fn get_direct(&self) -> bool {
811 self.direct
812 }
813
814 #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "musl")))]
817 pub fn get_write_dontcache(&self) -> bool {
818 self.write_dontcache
819 }
820
821 #[cfg(target_os = "macos")]
823 pub fn get_relaxed_sync(&self) -> bool {
824 self.relaxed_sync
825 }
826}
827
828impl StorageCreateOptions {
829 pub fn new() -> Self {
831 StorageCreateOptions::default()
832 }
833
834 pub fn filename<P: AsRef<Path>>(self, filename: P) -> Self {
836 self.modify_open_opts(|o| o.filename(filename))
837 }
838
839 pub fn size(mut self, size: u64) -> Self {
841 self.size = size;
842 self
843 }
844
845 pub fn preallocate(mut self, prealloc_mode: PreallocateMode) -> Self {
847 self.prealloc_mode = prealloc_mode;
848 self
849 }
850
851 pub fn overwrite(mut self, overwrite: bool) -> Self {
853 self.overwrite = overwrite;
854 self
855 }
856
857 pub fn modify_open_opts<F: FnOnce(StorageOpenOptions) -> StorageOpenOptions>(
859 mut self,
860 f: F,
861 ) -> Self {
862 self.open_opts = f(self.open_opts);
863 self
864 }
865
866 pub fn get_filename(&self) -> Option<&Path> {
868 self.open_opts.filename.as_deref()
869 }
870
871 pub fn get_size(&self) -> u64 {
873 self.size
874 }
875
876 pub fn get_preallocate(&self) -> PreallocateMode {
878 self.prealloc_mode
879 }
880
881 pub fn get_overwrite(&self) -> bool {
883 self.overwrite
884 }
885
886 pub fn get_open_options(self) -> StorageOpenOptions {
888 self.open_opts
889 }
890}
891
892impl Default for StorageCreateOptions {
893 fn default() -> Self {
894 StorageCreateOptions {
895 open_opts: Default::default(),
896 size: 0,
897 prealloc_mode: PreallocateMode::None,
898 overwrite: false,
899 }
900 }
901}