coven_sync/
file_upload_settings.rs1use super::file_upload_pool::Lane;
6use super::{FilesInner, TrailingHold};
7use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
8
9pub struct UploadSettings {
12 paused: AtomicBool,
15 writes_paused: AtomicBool,
18 retries_asked: AtomicU64,
20 connections: std::sync::Arc<super::file_upload_connections::UploadConnections>,
22 hold_change: tokio::sync::Mutex<()>,
27 #[cfg(test)]
30 settings_read_gate: std::sync::Mutex<
31 Option<(tokio::sync::oneshot::Sender<()>, tokio::sync::oneshot::Receiver<()>)>,
32 >,
33 #[cfg(test)]
36 change_waits: tokio::sync::watch::Sender<usize>,
37}
38
39impl UploadSettings {
40 pub(super) fn new() -> Self {
41 Self {
42 paused: AtomicBool::new(false),
43 writes_paused: AtomicBool::new(false),
44 retries_asked: AtomicU64::new(0),
45 connections: std::sync::Arc::new(
46 super::file_upload_connections::UploadConnections::new(),
47 ),
48 hold_change: tokio::sync::Mutex::new(()),
49 #[cfg(test)]
50 settings_read_gate: std::sync::Mutex::new(None),
51 #[cfg(test)]
52 change_waits: tokio::sync::watch::channel(0).0,
53 }
54 }
55
56 pub(super) fn paused(&self) -> bool {
58 self.paused.load(Ordering::Acquire)
59 }
60 pub(super) fn set_paused(&self, paused: bool) {
61 self.paused.store(paused, Ordering::Release);
62 }
63 pub(super) fn writes_paused(&self) -> bool {
64 self.writes_paused.load(Ordering::Acquire)
65 }
66 pub(super) fn set_writes_paused(&self, paused: bool) {
67 self.writes_paused.store(paused, Ordering::Release);
68 }
69 pub(super) fn retries_asked(&self) -> u64 {
70 self.retries_asked.load(Ordering::Acquire)
71 }
72 #[cfg(test)]
73 pub(super) fn hold_after_settings_read(
74 &self,
75 gate: (tokio::sync::oneshot::Sender<()>, tokio::sync::oneshot::Receiver<()>),
76 ) {
77 *self.settings_read_gate.lock().expect("the gate is not poisoned") = Some(gate);
78 }
79 #[cfg(test)]
80 pub(super) fn take_settings_read_gate(
81 &self,
82 ) -> Option<(tokio::sync::oneshot::Sender<()>, tokio::sync::oneshot::Receiver<()>)> {
83 self.settings_read_gate.lock().expect("the gate is not poisoned").take()
84 }
85 pub(super) fn retry_asked(&self) -> u64 {
87 self.retries_asked.fetch_add(1, Ordering::AcqRel)
88 }
89
90 pub(super) async fn lock_hold_change(&self) -> tokio::sync::MutexGuard<'_, ()> {
92 #[cfg(test)]
93 match self.hold_change.try_lock() {
94 Ok(change) => return change,
95 Err(_) => self.change_waits.send_modify(|waits| *waits += 1),
96 }
97 self.hold_change.lock().await
98 }
99
100 pub(super) fn hold_change_blocking(&self) -> tokio::sync::MutexGuard<'_, ()> {
103 #[cfg(test)]
104 match self.hold_change.try_lock() {
105 Ok(change) => return change,
106 Err(_) => self.change_waits.send_modify(|waits| *waits += 1),
107 }
108 self.hold_change.blocking_lock()
109 }
110
111 #[cfg(test)]
114 pub(super) fn change_waits_from_now(&self) -> impl std::future::Future<Output = ()> {
115 let mut waits = self.change_waits.subscribe();
116 let now = *waits.borrow_and_update();
117 async move {
118 coven_foundation::clock::within(waits.wait_for(|waits| *waits > now))
119 .await
120 .expect("a change waits for the run")
121 .expect("the waits are kept");
122 }
123 }
124}
125
126impl FilesInner {
127 pub(super) fn connections_beside(&self, lane: Lane) -> usize {
130 self.uploads.connections.beside(lane)
131 }
132 pub(super) fn set_lane_attempts(&self, lane: Lane, attempts: usize) {
134 self.uploads.connections.set_attempts(lane, attempts);
135 }
136 pub(super) fn set_lane_waiting(&self, lane: Lane, waiting: bool) {
138 self.uploads.connections.set_waiting(lane, waiting);
139 }
140 pub(super) fn spare_connection(&self, lane: Lane) -> Option<super::SpareConnection> {
144 self.uploads.connections.spare(lane, self.transfers.limits().uploads.get())
145 }
146 pub(super) async fn connection_freed(&self) {
148 self.uploads.connections.freed().await;
149 }
150 #[cfg(test)]
153 pub(super) fn lane_waiting(&self, lane: Lane) -> bool {
154 self.uploads.connections.waiting(lane)
155 }
156 pub(crate) fn trailing_hold(&self) -> Option<TrailingHold> {
160 let uploads = &self.uploads;
161 if uploads.paused() {
162 Some(TrailingHold::Paused)
163 } else if uploads.writes_paused() {
164 Some(TrailingHold::MemberKeysChanging)
165 } else if self.metered_holds(false) {
166 Some(TrailingHold::Metered)
167 } else {
168 None
169 }
170 }
171 pub(crate) fn retries_asked(&self) -> u64 {
173 self.uploads.retries_asked()
174 }
175 pub(crate) fn writes_were_paused(&self) {
178 self.uploads.set_writes_paused(true);
179 }
180 pub(crate) fn trailing_held(&self) -> bool {
182 self.trailing_hold().is_some()
183 }
184 pub(crate) fn set_paused(&self, paused: bool) {
186 self.uploads.set_paused(paused);
187 }
188 pub(crate) fn retry_asked(&self) -> u64 {
190 self.uploads.retry_asked()
191 }
192 pub(crate) async fn lock_hold_change(&self) -> tokio::sync::MutexGuard<'_, ()> {
194 self.uploads.lock_hold_change().await
195 }
196 pub(super) fn hold_change_blocking(&self) -> tokio::sync::MutexGuard<'_, ()> {
198 self.uploads.hold_change_blocking()
199 }
200 #[cfg(test)]
203 pub(crate) fn change_waits_from_now(&self) -> impl std::future::Future<Output = ()> {
204 self.uploads.change_waits_from_now()
205 }
206 #[cfg(test)]
209 pub(crate) fn hold_after_settings_read(
210 &self,
211 gate: (tokio::sync::oneshot::Sender<()>, tokio::sync::oneshot::Receiver<()>),
212 ) {
213 self.uploads.hold_after_settings_read(gate);
214 }
215 #[cfg(test)]
217 pub(crate) fn take_settings_read_gate(
218 &self,
219 ) -> Option<(tokio::sync::oneshot::Sender<()>, tokio::sync::oneshot::Receiver<()>)> {
220 self.uploads.take_settings_read_gate()
221 }
222 pub(crate) async fn read_writes_paused(&self) -> Result<(), coven_database::DbError> {
224 let paused = self.database.writes_paused().await?;
225 self.uploads.set_writes_paused(paused);
226 Ok(())
227 }
228}