Browse Source

fix: handle missing idx file for empty volumes during copy (#7777) (#7778)

When copying/evacuating empty volumes, the .idx file may not exist on disk
(this is allowed by checkIdxFile for volumes with only super block in .dat).

This fix:
1. Uses os.IsNotExist() instead of err == os.ErrNotExist for proper
   wrapped error checking in CopyFile
2. Treats missing source file as success when StopOffset == 0 (empty file)
3. Allows checkCopyFiles to pass when idx file doesn't exist but
   IdxFileSize == 0 (empty volume)

Fixes volumeServer.evacuate and volume.fix.replication for empty volumes.
pull/7782/head
Chris Lu 2 days ago
committed by GitHub
parent
commit
4dcd33bbc8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 18
      weed/server/volume_grpc_copy.go

18
weed/server/volume_grpc_copy.go

@ -234,9 +234,13 @@ todo: maybe should check the received count and deleted count of the volume
func checkCopyFiles(originFileInf *volume_server_pb.ReadVolumeFileStatusResponse, hasRemoteDatFile bool, idxFileName, datFileName string) error {
stat, err := os.Stat(idxFileName)
if err != nil {
return fmt.Errorf("stat idx file %s failed: %v", idxFileName, err)
}
if originFileInf.IdxFileSize != uint64(stat.Size()) {
// If the idx file doesn't exist but the expected size is 0, that's OK (empty volume)
if os.IsNotExist(err) && originFileInf.IdxFileSize == 0 {
// empty volume, idx file not needed
} else {
return fmt.Errorf("stat idx file %s failed: %v", idxFileName, err)
}
} else if originFileInf.IdxFileSize != uint64(stat.Size()) {
return fmt.Errorf("idx file %s size [%v] is not same as origin file size [%v]",
idxFileName, stat.Size(), originFileInf.IdxFileSize)
}
@ -373,8 +377,12 @@ func (vs *VolumeServer) CopyFile(req *volume_server_pb.CopyFileRequest, stream v
file, err := os.Open(fileName)
if err != nil {
if req.IgnoreSourceFileNotFound && err == os.ErrNotExist {
return nil
if os.IsNotExist(err) {
// If file doesn't exist and we're asked to copy 0 bytes (empty file),
// or if IgnoreSourceFileNotFound is set, treat as success
if req.IgnoreSourceFileNotFound || req.StopOffset == 0 {
return nil
}
}
return err
}

Loading…
Cancel
Save