Browse Source

Match Go ReceiveFile: prefer HardDrive location for EC and use response-level write errors

Two fixes: (1) Go prefers HardDriveType disk location for EC volumes,
falling back to first location. Returns "no storage location available"
when no locations exist. (2) Write failures are now response-level
errors (in response body) instead of gRPC status errors, matching Go.
rust-volume-server
Chris Lu 5 days ago
parent
commit
c5e7cc94fe
  1. 27
      seaweed-volume/src/server/grpc_server.rs

27
seaweed-volume/src/server/grpc_server.rs

@ -1332,12 +1332,21 @@ impl VolumeServer for VolumeGrpcService {
// Determine file path // Determine file path
let path = if info.is_ec_volume { let path = if info.is_ec_volume {
let store = self.state.store.read().unwrap(); let store = self.state.store.read().unwrap();
// Go prefers a HardDriveType location, then falls back to first
let dir = store let dir = store
.locations .locations
.first()
.map(|loc| loc.directory.clone())
.unwrap_or_default();
.iter()
.find(|loc| loc.disk_type == DiskType::HardDrive)
.or_else(|| store.locations.first())
.map(|loc| loc.directory.clone());
drop(store); drop(store);
let dir = match dir {
Some(d) => d,
None => {
resp_error = Some("no storage location available".to_string());
break;
}
};
let ec_base = if info.collection.is_empty() { let ec_base = if info.collection.is_empty() {
format!("{}", info.volume_id) format!("{}", info.volume_id)
} else { } else {
@ -1367,10 +1376,14 @@ impl VolumeServer for VolumeGrpcService {
Some(volume_server_pb::receive_file_request::Data::FileContent(content)) => { Some(volume_server_pb::receive_file_request::Data::FileContent(content)) => {
if let Some(ref mut f) = target_file { if let Some(ref mut f) = target_file {
use std::io::Write; use std::io::Write;
let n = f.write(&content).map_err(|e| {
Status::internal(format!("failed to write file: {}", e))
})?;
bytes_written += n as u64;
match f.write(&content) {
Ok(n) => bytes_written += n as u64,
Err(e) => {
// Match Go: write failures are response-level errors, not gRPC errors
resp_error = Some(format!("failed to write file: {}", e));
break;
}
}
} else { } else {
// Go returns protocol violations as response-level errors // Go returns protocol violations as response-level errors
resp_error = Some("file info must be sent first".to_string()); resp_error = Some("file info must be sent first".to_string());

Loading…
Cancel
Save