Files
seaweedfs/weed/storage/volume_info/volume_info.go
T
Chris Lu 5e8152b81c storage: register tier backends at the binary composition root (#9989)
The s3 and rclone tiered-storage backends were registered via blank imports
in weed/storage (volume_tier.go and volume_info/volume_info.go). That forced
every library consumer of weed/storage -- weed/shell, and through it external
tools -- to link aws-sdk-go and, under the rclone build tag, the full rclone
backend set and its cloud-storage SDKs, even though those consumers never tier
volumes.

Move the registrations into a new weed/storage/backend/all aggregator and
blank-import it once from weed/command, the binary's composition root. The weed
binary still registers both backends; weed/storage and its library consumers no
longer pull the backend SDKs into their dependency graph.
2026-06-16 11:47:32 -07:00

110 lines
3.2 KiB
Go

package volume_info
import (
"fmt"
"os"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
"github.com/seaweedfs/seaweedfs/weed/util"
jsonpb "google.golang.org/protobuf/encoding/protojson"
)
// MaybeLoadVolumeInfo load the file data as *volume_server_pb.VolumeInfo, the returned volumeInfo will not be nil
func MaybeLoadVolumeInfo(fileName string) (volumeInfo *volume_server_pb.VolumeInfo, hasRemoteFile bool, hasVolumeInfoFile bool, err error) {
volumeInfo = &volume_server_pb.VolumeInfo{}
glog.V(1).Infof("maybeLoadVolumeInfo checks %s", fileName)
if exists, canRead, _, _, _ := util.CheckFile(fileName); !exists || !canRead {
if !exists {
return
}
hasVolumeInfoFile = true
if !canRead {
glog.Warningf("can not read %s", fileName)
err = fmt.Errorf("can not read %s", fileName)
return
}
return
}
hasVolumeInfoFile = true
glog.V(1).Infof("maybeLoadVolumeInfo reads %s", fileName)
fileData, readErr := os.ReadFile(fileName)
if readErr != nil {
glog.Warningf("fail to read %s : %v", fileName, readErr)
err = fmt.Errorf("fail to read %s : %v", fileName, readErr)
return
}
// Handle empty .vif files gracefully - treat as if file doesn't exist
// This can happen when ec.decode copies from a source that doesn't have a .vif file
if len(fileData) == 0 {
glog.Warningf("empty volume info file %s, treating as non-existent", fileName)
hasVolumeInfoFile = false
return
}
glog.V(1).Infof("maybeLoadVolumeInfo Unmarshal volume info %v", fileName)
if err = jsonpb.Unmarshal(fileData, volumeInfo); err != nil {
if oldVersionErr := tryOldVersionVolumeInfo(fileData, volumeInfo); oldVersionErr != nil {
glog.Warningf("unmarshal error: %v oldFormat: %v", err, oldVersionErr)
err = fmt.Errorf("unmarshal error: %w oldFormat: %v", err, oldVersionErr)
return
} else {
err = nil
}
}
if len(volumeInfo.GetFiles()) == 0 {
return
}
hasRemoteFile = true
return
}
func SaveVolumeInfo(fileName string, volumeInfo *volume_server_pb.VolumeInfo) error {
if exists, _, canWrite, _, _ := util.CheckFile(fileName); exists && !canWrite {
return fmt.Errorf("failed to check %s not writable", fileName)
}
m := jsonpb.MarshalOptions{
AllowPartial: true,
EmitUnpopulated: true,
Indent: " ",
}
text, marshalErr := m.Marshal(volumeInfo)
if marshalErr != nil {
return fmt.Errorf("failed to marshal %s: %v", fileName, marshalErr)
}
if err := util.WriteFile(fileName, text, 0644); err != nil {
return fmt.Errorf("failed to write %s: %v", fileName, err)
}
return nil
}
func tryOldVersionVolumeInfo(data []byte, volumeInfo *volume_server_pb.VolumeInfo) error {
oldVersionVolumeInfo := &volume_server_pb.OldVersionVolumeInfo{}
if err := jsonpb.Unmarshal(data, oldVersionVolumeInfo); err != nil {
return fmt.Errorf("failed to unmarshal old version volume info: %w", err)
}
volumeInfo.Files = oldVersionVolumeInfo.Files
volumeInfo.Version = oldVersionVolumeInfo.Version
volumeInfo.Replication = oldVersionVolumeInfo.Replication
volumeInfo.BytesOffset = oldVersionVolumeInfo.BytesOffset
volumeInfo.DatFileSize = oldVersionVolumeInfo.DatFileSize
volumeInfo.ExpireAtSec = oldVersionVolumeInfo.DestroyTime
volumeInfo.ReadOnly = oldVersionVolumeInfo.ReadOnly
return nil
}