Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/raw/adapters/kv/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl<S: Adapter> Accessor for Backend<S> {
}

if cap.write {
cap.write_can_empty = true;
cap.create_dir = true;
cap.delete = true;
}
Expand Down
1 change: 1 addition & 0 deletions core/src/raw/adapters/typed_kv/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ impl<S: Adapter> Accessor for Backend<S> {

if kv_cap.set {
cap.write = true;
cap.write_can_empty = true;
cap.create_dir = true;
}

Expand Down
8 changes: 7 additions & 1 deletion core/src/raw/oio/write/multipart_upload_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,13 @@ where
(w, res)
}));
}
None => return Poll::Ready(Ok(())),
None => {
// Call write_once if there is no data in cache and no upload_id.
self.state = State::Close(Box::pin(async move {
let res = w.write_once(0, AsyncBody::Empty).await;
(w, res)
}));
}
},
}
}
Expand Down
8 changes: 7 additions & 1 deletion core/src/raw/oio/write/range_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,13 @@ impl<W: RangeWrite> oio::Write for RangeWriter<W> {
(w, res)
}));
}
None => return Poll::Ready(Ok(())),
None => {
// Call write_once if there is no data in buffer and no location.
self.state = State::Complete(Box::pin(async move {
let res = w.write_once(0, AsyncBody::Empty).await;
(w, res)
}));
}
},
}
}
Expand Down
1 change: 1 addition & 0 deletions core/src/services/azblob/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ impl Accessor for AzblobBackend {
read_with_override_content_disposition: true,

write: true,
write_can_empty: true,
write_can_append: true,
write_with_cache_control: true,
write_with_content_type: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/cos/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ impl Accessor for CosBackend {
read_with_if_none_match: true,

write: true,
write_can_empty: true,
write_can_append: true,
write_can_multi: true,
write_with_content_type: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/fs/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ impl Accessor for FsBackend {
read_with_range: true,

write: true,
write_can_empty: true,
write_can_append: true,
write_can_multi: true,
create_dir: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/gcs/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ impl Accessor for GcsBackend {
read_with_if_none_match: true,

write: true,
write_can_empty: true,
write_can_multi: true,
write_with_content_type: true,
// The buffer size should be a multiple of 256 KiB (256 x 1024 bytes), unless it's the last chunk that completes the upload.
Expand Down
1 change: 1 addition & 0 deletions core/src/services/obs/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ impl Accessor for ObsBackend {
read_with_if_none_match: true,

write: true,
write_can_empty: true,
write_can_append: true,
write_can_multi: true,
write_with_content_type: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/oss/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ impl Accessor for OssBackend {
read_with_if_none_match: true,

write: true,
write_can_empty: true,
write_can_append: true,
write_can_multi: true,
write_with_cache_control: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/s3/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,7 @@ impl Accessor for S3Backend {
read_with_override_content_type: true,

write: true,
write_can_empty: true,
write_can_multi: true,
write_with_cache_control: true,
write_with_content_type: true,
Expand Down
1 change: 1 addition & 0 deletions core/src/services/webdav/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ impl Accessor for WebdavBackend {
read_with_range: true,

write: true,
write_can_empty: true,

create_dir: true,
delete: true,
Expand Down
2 changes: 2 additions & 0 deletions core/src/types/capability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub struct Capability {
pub write: bool,
/// If operator supports write can be called in multi times.
pub write_can_multi: bool,
/// If operator supports write with empty content.
pub write_can_empty: bool,
/// If operator supports write by append.
pub write_can_append: bool,
/// If operator supports write with content type.
Expand Down
18 changes: 18 additions & 0 deletions core/tests/behavior/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub fn behavior_write_tests(op: &Operator) -> Vec<Trial> {
test_create_dir,
test_create_dir_existing,
test_write_only,
test_write_with_empty_content,
test_write_with_dir_path,
test_write_with_special_chars,
test_write_with_cache_control,
Expand Down Expand Up @@ -136,6 +137,23 @@ pub async fn test_write_only(op: Operator) -> Result<()> {
Ok(())
}

/// Write a file with empty content.
pub async fn test_write_with_empty_content(op: Operator) -> Result<()> {
if !op.info().full_capability().write_can_empty {
return Ok(());
}

let path = uuid::Uuid::new_v4().to_string();

op.write(&path, vec![]).await?;

let meta = op.stat(&path).await.expect("stat must succeed");
assert_eq!(meta.content_length(), 0);

op.delete(&path).await.expect("delete must succeed");
Ok(())
}

/// Write file with dir path should return an error
pub async fn test_write_with_dir_path(op: Operator) -> Result<()> {
let path = format!("{}/", uuid::Uuid::new_v4());
Expand Down