openssh_sftp_client/options.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
use std::{
num::{NonZeroU16, NonZeroUsize},
time::Duration,
};
#[cfg(feature = "__ci-tests")]
use std::num::NonZeroU32;
/// Options when creating [`super::Sftp`].
#[derive(Debug, Copy, Clone, Default)]
pub struct SftpOptions {
read_end_buffer_size: Option<NonZeroUsize>,
write_end_buffer_size: Option<NonZeroUsize>,
flush_interval: Option<Duration>,
max_pending_requests: Option<NonZeroU16>,
tokio_compat_file_write_limit: Option<NonZeroUsize>,
#[cfg(feature = "__ci-tests")]
max_read_len: Option<NonZeroU32>,
#[cfg(feature = "__ci-tests")]
max_write_len: Option<NonZeroU32>,
}
impl SftpOptions {
/// Create a new [`SftpOptions`].
pub const fn new() -> Self {
Self {
read_end_buffer_size: None,
write_end_buffer_size: None,
flush_interval: None,
max_pending_requests: None,
tokio_compat_file_write_limit: None,
#[cfg(feature = "__ci-tests")]
max_read_len: None,
#[cfg(feature = "__ci-tests")]
max_write_len: None,
}
}
/// Set `flush_interval`, default value is 0.5 ms.
///
/// `flush_interval` decides the maximum time your requests would stay
/// in the write buffer before it is actually sent to the remote.
///
/// If another thread is doing flushing, then the internal `flush_task`
/// [`super::Sftp`] started would wait for another `flush_interval`.
///
/// Setting it to be larger might improve overall performance by grouping
/// writes and reducing the overhead of packet sent over network, but it
/// might also increase latency, so be careful when setting the
/// `flush_interval`.
///
/// If `flush_interval` is set to 0, then every packet
/// is flushed immediately.
///
/// NOTE that it is perfectly OK to set `flush_interval` to 0 and
/// it would not slowdown the program, as flushing is only performed
/// on daemon.
#[must_use]
pub const fn flush_interval(mut self, flush_interval: Duration) -> Self {
self.flush_interval = Some(flush_interval);
self
}
pub(super) fn get_flush_interval(&self) -> Duration {
self.flush_interval
.unwrap_or_else(|| Duration::from_micros(500))
}
/// Set `max_pending_requests`.
///
/// If the pending_requests is larger than max_pending_requests, then the
/// flush task will flush the write buffer without waiting for `flush_interval`.
///
/// It is set to 100 by default.
#[must_use]
pub const fn max_pending_requests(mut self, max_pending_requests: NonZeroU16) -> Self {
self.max_pending_requests = Some(max_pending_requests);
self
}
pub(super) fn get_max_pending_requests(&self) -> u16 {
self.max_pending_requests
.map(NonZeroU16::get)
.unwrap_or(100)
}
/// Set the init buffer size for requests.
/// It is used to store [`bytes::Bytes`] and it will be resized
/// to fit the pending requests.
///
/// NOTE that sftp uses double buffer for efficient flushing
/// without blocking the writers.
///
/// It is set to 100 by default.
#[must_use]
pub const fn requests_buffer_size(mut self, buffer_size: NonZeroUsize) -> Self {
self.write_end_buffer_size = Some(buffer_size);
self
}
pub(super) fn get_write_end_buffer_size(&self) -> NonZeroUsize {
self.write_end_buffer_size
.unwrap_or_else(|| NonZeroUsize::new(100).unwrap())
}
/// Set the init buffer size for responses.
/// If the header of the response is larger than the buffer, then the buffer
/// will be resized to fit the size of the header.
///
/// It is set to 1024 by default.
#[must_use]
pub const fn responses_buffer_size(mut self, buffer_size: NonZeroUsize) -> Self {
self.read_end_buffer_size = Some(buffer_size);
self
}
pub(super) fn get_read_end_buffer_size(&self) -> NonZeroUsize {
self.read_end_buffer_size
.unwrap_or_else(|| NonZeroUsize::new(1024).unwrap())
}
/// Set the write buffer limit for tokio compat file.
/// If [`crate::file::TokioCompatFile`] has hit the write buffer limit
/// set here, then it will flush one write buffer and continue
/// sending (part of) the buffer to the server, which could be buffered.
///
/// It is set to 640KB (640 * 1024 bytes) by default.
#[must_use]
pub const fn tokio_compat_file_write_limit(mut self, limit: NonZeroUsize) -> Self {
self.tokio_compat_file_write_limit = Some(limit);
self
}
pub(super) fn get_tokio_compat_file_write_limit(&self) -> usize {
self.tokio_compat_file_write_limit
.map(NonZeroUsize::get)
.unwrap_or(640 * 1024)
}
}
#[cfg(feature = "__ci-tests")]
impl SftpOptions {
/// Set `max_read_len`.
///
/// It can be used to reduce `max_read_len`, but cannot be used
/// to increase `max_read_len`.
#[must_use]
pub const fn max_read_len(mut self, max_read_len: NonZeroU32) -> Self {
self.max_read_len = Some(max_read_len);
self
}
pub(super) fn get_max_read_len(&self) -> Option<u32> {
self.max_read_len.map(NonZeroU32::get)
}
/// Set `max_write_len`.
///
/// It can be used to reduce `max_write_len`, but cannot be used
/// to increase `max_write_len`.
#[must_use]
pub const fn max_write_len(mut self, max_write_len: NonZeroU32) -> Self {
self.max_write_len = Some(max_write_len);
self
}
pub(super) fn get_max_write_len(&self) -> Option<u32> {
self.max_write_len.map(NonZeroU32::get)
}
}
#[cfg(not(feature = "__ci-tests"))]
impl SftpOptions {
pub(super) const fn get_max_read_len(&self) -> Option<u32> {
None
}
pub(super) const fn get_max_write_len(&self) -> Option<u32> {
None
}
}