You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by tu...@apache.org on 2023/04/28 18:15:15 UTC
[arrow-rs] branch master updated: InMemory append API (#4153)
This is an automated email from the ASF dual-hosted git repository.
tustvold pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push:
new 521fdb993 InMemory append API (#4153)
521fdb993 is described below
commit 521fdb99374cfe856fdb03e84bb56f09b020d785
Author: Berkay Şahin <12...@users.noreply.github.com>
AuthorDate: Fri Apr 28 21:15:09 2023 +0300
InMemory append API (#4153)
* ready to review
* clippy fix
* Refactor code to remove byte duplication
* simplify shutdown
Co-authored-by: Raphael Taylor-Davies <17...@users.noreply.github.com>
---------
Co-authored-by: metesynnada <10...@users.noreply.github.com>
Co-authored-by: Raphael Taylor-Davies <17...@users.noreply.github.com>
---
object_store/src/memory.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 104 insertions(+)
diff --git a/object_store/src/memory.rs b/object_store/src/memory.rs
index 057a260f7..b01ffbb02 100644
--- a/object_store/src/memory.rs
+++ b/object_store/src/memory.rs
@@ -117,6 +117,17 @@ impl ObjectStore for InMemory {
Ok(())
}
+ async fn append(
+ &self,
+ location: &Path,
+ ) -> Result<Box<dyn AsyncWrite + Unpin + Send>> {
+ Ok(Box::new(InMemoryAppend {
+ location: location.clone(),
+ data: Vec::<u8>::new(),
+ storage: StorageType::clone(&self.storage),
+ }))
+ }
+
async fn get(&self, location: &Path) -> Result<GetResult> {
let data = self.entry(location).await?;
@@ -329,8 +340,55 @@ impl AsyncWrite for InMemoryUpload {
}
}
+struct InMemoryAppend {
+ location: Path,
+ data: Vec<u8>,
+ storage: StorageType,
+}
+
+impl AsyncWrite for InMemoryAppend {
+ fn poll_write(
+ mut self: Pin<&mut Self>,
+ _cx: &mut std::task::Context<'_>,
+ buf: &[u8],
+ ) -> std::task::Poll<Result<usize, io::Error>> {
+ self.data.extend_from_slice(buf);
+ Poll::Ready(Ok(buf.len()))
+ }
+
+ fn poll_flush(
+ mut self: Pin<&mut Self>,
+ _cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Result<(), io::Error>> {
+ let storage = StorageType::clone(&self.storage);
+
+ let mut writer = storage.write();
+
+ if let Some((bytes, _)) = writer.remove(&self.location) {
+ let buf = std::mem::take(&mut self.data);
+ let concat = Bytes::from_iter(bytes.into_iter().chain(buf.into_iter()));
+ writer.insert(self.location.clone(), (concat, Utc::now()));
+ } else {
+ writer.insert(
+ self.location.clone(),
+ (Bytes::from(std::mem::take(&mut self.data)), Utc::now()),
+ );
+ };
+ Poll::Ready(Ok(()))
+ }
+
+ fn poll_shutdown(
+ self: Pin<&mut Self>,
+ cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Result<(), io::Error>> {
+ self.poll_flush(cx)
+ }
+}
+
#[cfg(test)]
mod tests {
+ use tokio::io::AsyncWriteExt;
+
use super::*;
use crate::{
@@ -396,4 +454,50 @@ mod tests {
panic!("unexpected error type: {err:?}");
}
}
+
+ #[tokio::test]
+ async fn test_append_new() {
+ let in_memory = InMemory::new();
+ let location = Path::from("some_file");
+ let data = Bytes::from("arbitrary data");
+ let expected_data = data.clone();
+
+ let mut writer = in_memory.append(&location).await.unwrap();
+ writer.write_all(&data).await.unwrap();
+ writer.flush().await.unwrap();
+
+ let read_data = in_memory
+ .get(&location)
+ .await
+ .unwrap()
+ .bytes()
+ .await
+ .unwrap();
+ assert_eq!(&*read_data, expected_data);
+ }
+
+ #[tokio::test]
+ async fn test_append_existing() {
+ let in_memory = InMemory::new();
+ let location = Path::from("some_file");
+ let data = Bytes::from("arbitrary");
+ let data_appended = Bytes::from(" data");
+ let expected_data = Bytes::from("arbitrary data");
+
+ let mut writer = in_memory.append(&location).await.unwrap();
+ writer.write_all(&data).await.unwrap();
+ writer.flush().await.unwrap();
+
+ writer.write_all(&data_appended).await.unwrap();
+ writer.flush().await.unwrap();
+
+ let read_data = in_memory
+ .get(&location)
+ .await
+ .unwrap()
+ .bytes()
+ .await
+ .unwrap();
+ assert_eq!(&*read_data, expected_data);
+ }
}