Browse Source

fix: correctly detect missing source file during volume copy (#7784)

* fix: correctly detect missing source file during volume copy

The previous fix (commit 5c27522) incorrectly used progressedBytes == 0 to
detect if the source file didn't exist. This was wrong because it would also
delete files when the source file exists but is empty.

This fix:
1. Server side: Send ModifiedTsNs even for empty files, so the client knows
   the source file exists
2. Client side: Check modifiedTsNs == 0 instead of progressedBytes == 0 to
   determine if source file didn't exist

Now the logic correctly handles:
- Source file doesn't exist → No ModifiedTsNs sent → Remove empty file
- Source file exists but is empty → ModifiedTsNs sent → Keep empty file
- Source file exists with content → ModifiedTsNs sent → Keep file with content

Fixes #7777

* Update weed/server/volume_grpc_copy.go

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
pull/7786/head
Chris Lu 4 days ago
committed by GitHub
parent
commit
ef28f49ec3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 21
      weed/server/volume_grpc_copy.go

21
weed/server/volume_grpc_copy.go

@ -295,9 +295,11 @@ func writeToFile(client volume_server_pb.VolumeServer_CopyFileClient, fileName s
} }
wt.MaybeSlowdown(int64(len(resp.FileContent))) wt.MaybeSlowdown(int64(len(resp.FileContent)))
} }
// If no data was written (source file was not found), remove the empty file
// to avoid leaving corrupted empty files that cause parse errors later
if progressedBytes == 0 && !isAppend {
// If we never received a modifiedTsNs, it means the source file did not exist.
// Remove the empty file we created to avoid leaving corrupted empty files.
// Note: We check modifiedTsNs (not progressedBytes) because an empty source file
// is valid and should result in an empty destination file.
if modifiedTsNs == 0 && !isAppend {
if removeErr := os.Remove(fileName); removeErr != nil { if removeErr := os.Remove(fileName); removeErr != nil {
glog.V(1).Infof("failed to remove empty file %s: %v", fileName, removeErr) glog.V(1).Infof("failed to remove empty file %s: %v", fileName, removeErr)
} else { } else {
@ -426,6 +428,19 @@ func (vs *VolumeServer) CopyFile(req *volume_server_pb.CopyFileRequest, stream v
} }
// If no data has been sent in the loop (e.g. for an empty file, or when stopOffset is 0),
// we still need to send the ModifiedTsNs so the client knows the source file exists.
// fileModTsNs is set to 0 after the first send, so if it's still non-zero,
// we haven't sent anything yet.
if fileModTsNs != 0 {
err = stream.Send(&volume_server_pb.CopyFileResponse{
ModifiedTsNs: fileModTsNs,
})
if err != nil {
return err
}
}
return nil return nil
} }

Loading…
Cancel
Save