mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-05-30 03:01:21 +00:00
Remove a write optimisation in Negotiated.
This commit is contained in:
parent
a5415f9e1d
commit
1e8a90c606
@ -227,37 +227,14 @@ where
|
|||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
match &mut self.state {
|
match &mut self.state {
|
||||||
State::Completed { io, ref mut remaining } => {
|
State::Completed { io, ref mut remaining } => {
|
||||||
if !remaining.is_empty() {
|
while !remaining.is_empty() {
|
||||||
// Try to write `buf` together with `remaining` for efficiency,
|
let n = io.write(&remaining)?;
|
||||||
// regardless of whether the underlying I/O stream is buffered.
|
if n == 0 {
|
||||||
// Every call to `write` may imply a syscall and separate
|
return Err(io::ErrorKind::WriteZero.into())
|
||||||
// network packet.
|
|
||||||
let remaining_len = remaining.len();
|
|
||||||
remaining.extend_from_slice(buf);
|
|
||||||
match io.write(&remaining) {
|
|
||||||
Err(e) => {
|
|
||||||
remaining.split_off(remaining_len);
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
Ok(n) => {
|
|
||||||
remaining.split_to(n);
|
|
||||||
if !remaining.is_empty() {
|
|
||||||
let written = if n < buf.len() {
|
|
||||||
remaining.split_off(remaining_len);
|
|
||||||
n
|
|
||||||
} else {
|
|
||||||
buf.len()
|
|
||||||
};
|
|
||||||
debug_assert!(remaining.len() <= remaining_len);
|
|
||||||
Ok(written)
|
|
||||||
} else {
|
|
||||||
Ok(buf.len())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
remaining.split_to(n);
|
||||||
io.write(buf)
|
|
||||||
}
|
}
|
||||||
|
io.write(buf)
|
||||||
},
|
},
|
||||||
State::Expecting { io, .. } => io.write(buf),
|
State::Expecting { io, .. } => io.write(buf),
|
||||||
State::Invalid => panic!("Negotiated: Invalid state")
|
State::Invalid => panic!("Negotiated: Invalid state")
|
||||||
@ -382,44 +359,40 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn write_remaining() {
|
fn write_remaining() {
|
||||||
fn prop(rem: Vec<u8>, new: Vec<u8>, free: u8) -> TestResult {
|
fn prop(rem: Vec<u8>, new: Vec<u8>, free: u8, step: u8) -> TestResult {
|
||||||
let cap = rem.len() + free as usize;
|
let cap = rem.len() + free as usize;
|
||||||
let buf = Capped { buf: Vec::with_capacity(cap), step: free as usize };
|
let step = u8::min(free, step) as usize + 1;
|
||||||
let mut rem = BytesMut::from(rem);
|
let buf = Capped { buf: Vec::with_capacity(cap), step };
|
||||||
|
let rem = BytesMut::from(rem);
|
||||||
let mut io = Negotiated::completed(buf, rem.clone());
|
let mut io = Negotiated::completed(buf, rem.clone());
|
||||||
let mut written = 0;
|
let mut written = 0;
|
||||||
loop {
|
loop {
|
||||||
// Write until `new` has been fully written or the capped buffer is
|
// Write until `new` has been fully written or the capped buffer runs
|
||||||
// full (in which case the buffer should remain unchanged from the
|
// over capacity and yields WriteZero.
|
||||||
// last successful write).
|
|
||||||
match io.write(&new[written..]) {
|
match io.write(&new[written..]) {
|
||||||
Ok(n) =>
|
Ok(n) =>
|
||||||
if let State::Completed { remaining, .. } = &io.state {
|
if let State::Completed { remaining, .. } = &io.state {
|
||||||
if n == rem.len() + new[written..].len() {
|
assert!(remaining.is_empty());
|
||||||
assert!(remaining.is_empty())
|
|
||||||
} else {
|
|
||||||
assert!(remaining.len() <= rem.len());
|
|
||||||
}
|
|
||||||
written += n;
|
written += n;
|
||||||
if written == new.len() {
|
if written == new.len() {
|
||||||
return TestResult::passed()
|
return TestResult::passed()
|
||||||
}
|
}
|
||||||
rem = remaining.clone();
|
|
||||||
} else {
|
} else {
|
||||||
return TestResult::failed()
|
return TestResult::failed()
|
||||||
}
|
}
|
||||||
Err(_) =>
|
Err(e) if e.kind() == io::ErrorKind::WriteZero => {
|
||||||
if let State::Completed { remaining, .. } = &io.state {
|
if let State::Completed { .. } = &io.state {
|
||||||
assert!(rem.len() + new[written..].len() > cap);
|
assert!(rem.len() + new.len() > cap);
|
||||||
assert_eq!(remaining, &rem);
|
|
||||||
return TestResult::passed()
|
return TestResult::passed()
|
||||||
} else {
|
} else {
|
||||||
return TestResult::failed()
|
return TestResult::failed()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Err(e) => panic!("Unexpected error: {:?}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
quickcheck(prop as fn(_,_,_) -> _)
|
quickcheck(prop as fn(_,_,_,_) -> _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user