1use super::*;
2use coven_foundation::clock::FixedClock;
3
4pub struct MemoryStorageBuilder {
6 config: StorageConfig,
7 clock: ClockRef,
8 time_resolution: Duration,
9 single_limit: u64,
10 part_size: usize,
11 independent_parts: bool,
12 whole_part_reads: bool,
13 listing_page: usize,
14}
15
16impl MemoryStorageBuilder {
17 pub(super) fn new() -> Self {
18 Self {
19 config: location(CloudProvider::S3),
20 clock: Arc::new(FixedClock::new(std::time::UNIX_EPOCH)),
21 time_resolution: Duration::from_nanos(1),
22 single_limit: 4 * 1024 * 1024,
23 part_size: 64 * 1024,
24 independent_parts: false,
25 whole_part_reads: false,
26 listing_page: usize::MAX,
27 }
28 }
29
30 pub fn provider(mut self, provider: CloudProvider) -> Self {
32 self.config = location(provider);
33 self
34 }
35 pub fn location(mut self, config: StorageConfig) -> Self {
37 self.config = config;
38 self
39 }
40 pub fn clock(mut self, clock: ClockRef) -> Self {
42 self.clock = clock;
43 self
44 }
45 pub fn time_resolution(mut self, resolution: Duration) -> Self {
47 self.time_resolution = resolution;
48 self
49 }
50 pub fn transfer_limits(mut self, single_limit: u64, part_size: usize) -> Self {
52 self.single_limit = single_limit;
53 self.part_size = part_size;
54 self
55 }
56 pub fn independent_parts(mut self) -> Self {
60 self.independent_parts = true;
61 self
62 }
63 pub fn reads_whole_parts(mut self) -> Self {
70 self.whole_part_reads = true;
71 self
72 }
73 pub fn listing_page(mut self, entries: std::num::NonZeroUsize) -> Self {
76 self.listing_page = entries.get();
77 self
78 }
79 pub fn build(self) -> Result<MemoryStorage, StorageError> {
81 let Self {
82 config,
83 clock,
84 time_resolution,
85 single_limit,
86 part_size,
87 independent_parts,
88 whole_part_reads,
89 listing_page,
90 } = self;
91 config.validate()?;
92 if time_resolution.is_zero() {
93 return Err(StorageFailure::InvalidConfiguration.with_source("zero provider time unit"));
94 }
95 if single_limit == 0 || part_size == 0 {
96 return Err(StorageFailure::InvalidPart.into());
97 }
98 Ok(MemoryStorage::from_memory(Arc::new(MemoryProvider {
99 config,
100 online: Arc::new(std::sync::atomic::AtomicBool::new(true)),
101 single_limit,
102 part_size,
103 independent_parts,
104 whole_part_reads,
105 listing_page,
106 requests: Arc::new(tokio::sync::watch::channel(0).0),
107 request_trace: Arc::new(std::sync::Mutex::new(Vec::new())),
108 active_requests: Arc::new(std::sync::atomic::AtomicUsize::new(0)),
109 peak_requests: Arc::new(std::sync::atomic::AtomicUsize::new(0)),
110 clock,
111 time_resolution,
112 tokens: Arc::new(Mutex::new(None)),
113 s3_key: Arc::new(Mutex::new(None)),
114 account: Account::Owner,
115 state: Arc::new(Mutex::new(MemoryState {
116 location_marker: None,
117 folder_name: "Household".into(),
118 objects: super::memory_objects::MemoryObjects::new(),
119 uploads: BTreeMap::new(),
120 next: 1,
121 accounts: BTreeMap::new(),
122 retained_access: BTreeMap::new(),
123 faults: Faults::none(),
124 creation_barrier: None,
125 creation_gate: None,
126 part_gate: None,
127 read_gate: None,
128 ranges: Vec::new(),
129 reads: Vec::new(),
130 moved: BTreeMap::new(),
131 received_buffers: Vec::new(),
132 sent_bytes: 0,
133 largest_part: 0,
134 held_listing: None,
135 held_read: None,
136 held_body: None,
137 held_creation: None,
138 held_request: None,
139 held_access: None,
140 rejected_tokens: Default::default(),
141 })),
142 })))
143 }
144}
145
146fn location(provider: CloudProvider) -> StorageConfig {
147 match provider {
148 CloudProvider::S3 => StorageConfig::S3 {
149 bucket: "test".into(),
150 region: "us-east-1".into(),
151 endpoint: None,
152 profile: None,
153 },
154 CloudProvider::Dropbox => StorageConfig::Dropbox {
155 account_label: None,
156 location: crate::DropboxLocation::SharedFolder { namespace_id: "store".into() },
157 folder_label: None,
158 },
159 CloudProvider::OneDrive => StorageConfig::OneDrive {
160 account_label: None,
161 drive_id: "drive".into(),
162 folder_id: "store".into(),
163 folder_label: None,
164 },
165 CloudProvider::CloudKit => StorageConfig::CloudKit {
166 container: "container".into(),
167 owner: "owner".into(),
168 zone: "store".into(),
169 },
170 }
171}