You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2024/03/14 13:22:34 UTC

(opendal) 02/07: Refactor exact buf write

This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch cleanup
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit 48eb515fecfc755be00c18d6f5f734fd371f7197
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Thu Mar 14 21:10:47 2024 +0800

    Refactor exact buf write
    
    Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
 core/src/raw/oio/write/exact_buf_write.rs | 65 +++++++++++++++++++++++--------
 1 file changed, 49 insertions(+), 16 deletions(-)

diff --git a/core/src/raw/oio/write/exact_buf_write.rs b/core/src/raw/oio/write/exact_buf_write.rs
index cd95055c83..f1097ab140 100644
--- a/core/src/raw/oio/write/exact_buf_write.rs
+++ b/core/src/raw/oio/write/exact_buf_write.rs
@@ -15,10 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use bytes::Bytes;
-use std::cmp::min;
+use bytes::{Buf, BufMut, Bytes};
+use std::mem;
 
-use crate::raw::oio::WriteBuf;
 use crate::raw::*;
 use crate::*;
 
@@ -38,7 +37,8 @@ pub struct ExactBufWriter<W: oio::Write> {
 
     /// The size for buffer, we will flush the underlying storage at the size of this buffer.
     buffer_size: usize,
-    buffer: oio::ChunkedBytes,
+    buffer: Vec<u8>,
+    frozen: Option<Bytes>,
 }
 
 impl<W: oio::Write> ExactBufWriter<W> {
@@ -47,35 +47,68 @@ impl<W: oio::Write> ExactBufWriter<W> {
         Self {
             inner,
             buffer_size,
-            buffer: oio::ChunkedBytes::default(),
+            buffer: Vec::new(),
+            frozen: None,
         }
     }
 }
 
 impl<W: oio::Write> oio::Write for ExactBufWriter<W> {
     async fn write(&mut self, bs: Bytes) -> Result<usize> {
-        if self.buffer.len() >= self.buffer_size {
-            let bs = self.buffer.bytes(self.buffer.remaining());
-            let written = self.inner.write(bs).await?;
-            self.buffer.advance(written);
+        if let Some(bs) = self.frozen.as_mut() {
+            let written = self.inner.write(bs.clone()).await?;
+            bs.advance(written);
+            if bs.is_empty() {
+                self.frozen = None;
+            } else {
+                // Return remaining bytes back to buffer
+                self.buffer = bs.to_vec();
+            }
+        }
+
+        // Quick Path
+        //
+        // if buffer is empty and bs is larger than buffer_size, we can directly
+        // freeze the first buffer_size bytes.
+        if self.buffer.is_empty() {
+            if bs.len() >= self.buffer_size {
+                self.frozen = Some(bs.slice(0..self.buffer_size));
+                return Ok(self.buffer_size);
+            }
         }
 
-        let remaining = min(self.buffer_size - self.buffer.len(), bs.len());
-        self.buffer.push(bs.slice(0..remaining));
-        Ok(remaining)
+        let remaining = self.buffer_size - self.buffer.len();
+        if bs.len() >= remaining {
+            self.buffer.put_slice(&bs[0..remaining]);
+            self.frozen = Some(Bytes::from(mem::take(&mut self.buffer)));
+            Ok(remaining)
+        } else {
+            self.buffer.put_slice(&bs);
+            Ok(bs.len())
+        }
     }
 
     async fn close(&mut self) -> Result<()> {
-        while !self.buffer.is_empty() {
-            let bs = self.buffer.bytes(self.buffer.remaining());
-            let n = self.inner.write(bs).await?;
-            self.buffer.advance(n);
+        loop {
+            if let Some(bs) = self.frozen.as_mut() {
+                let written = self.inner.write(bs.clone()).await?;
+                bs.advance(written);
+                if bs.is_empty() {
+                    self.frozen = None;
+                }
+            } else if !self.buffer.is_empty() {
+                // freeze the remaining buffer
+                self.frozen = Some(Bytes::from(mem::take(&mut self.buffer)));
+            } else {
+                break;
+            }
         }
 
         self.inner.close().await
     }
 
     async fn abort(&mut self) -> Result<()> {
+        self.frozen = None;
         self.buffer.clear();
         self.inner.abort().await
     }