seaweedfs/weed/remote_storage/remote_storage.go

161 lines
4.6 KiB
Go
Raw Permalink Normal View History

2021-07-27 05:53:44 +00:00
package remote_storage
import (
"fmt"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/pb/remote_pb"
2022-08-17 19:05:07 +00:00
"google.golang.org/protobuf/proto"
2021-08-08 08:21:42 +00:00
"io"
2021-09-04 07:18:21 +00:00
"sort"
2021-07-27 10:26:35 +00:00
"strings"
2021-07-27 05:53:44 +00:00
"sync"
2021-09-04 03:42:02 +00:00
"time"
2021-07-27 05:53:44 +00:00
)
const slash = "/"
func ParseLocationName(remote string) (locationName string) {
remote = strings.TrimSuffix(remote, slash)
parts := strings.SplitN(remote, slash, 2)
if len(parts) >= 1 {
return parts[0]
}
return
}
func parseBucketLocation(remote string) (loc *remote_pb.RemoteStorageLocation) {
2021-08-26 22:18:34 +00:00
loc = &remote_pb.RemoteStorageLocation{}
remote = strings.TrimSuffix(remote, slash)
parts := strings.SplitN(remote, slash, 3)
if len(parts) >= 1 {
loc.Name = parts[0]
2021-07-27 10:26:35 +00:00
}
if len(parts) >= 2 {
loc.Bucket = parts[1]
2021-07-27 10:26:35 +00:00
}
loc.Path = remote[len(loc.Name)+1+len(loc.Bucket):]
if loc.Path == "" {
loc.Path = slash
2021-07-27 10:26:35 +00:00
}
return
}
func parseNoBucketLocation(remote string) (loc *remote_pb.RemoteStorageLocation) {
loc = &remote_pb.RemoteStorageLocation{}
remote = strings.TrimSuffix(remote, slash)
parts := strings.SplitN(remote, slash, 2)
if len(parts) >= 1 {
loc.Name = parts[0]
}
loc.Path = remote[len(loc.Name):]
if loc.Path == "" {
loc.Path = slash
}
return
}
2021-08-26 22:18:34 +00:00
func FormatLocation(loc *remote_pb.RemoteStorageLocation) string {
2021-09-04 01:52:37 +00:00
if loc.Bucket == "" {
return fmt.Sprintf("%s%s", loc.Name, loc.Path)
}
2021-08-16 03:07:13 +00:00
return fmt.Sprintf("%s/%s%s", loc.Name, loc.Bucket, loc.Path)
}
2021-07-27 05:53:44 +00:00
type VisitFunc func(dir string, name string, isDirectory bool, remoteEntry *filer_pb.RemoteEntry) error
2021-09-04 03:42:02 +00:00
type Bucket struct {
Name string
CreatedAt time.Time
}
2021-07-27 05:53:44 +00:00
type RemoteStorageClient interface {
2021-08-26 22:18:34 +00:00
Traverse(loc *remote_pb.RemoteStorageLocation, visitFn VisitFunc) error
ReadFile(loc *remote_pb.RemoteStorageLocation, offset int64, size int64) (data []byte, err error)
WriteDirectory(loc *remote_pb.RemoteStorageLocation, entry *filer_pb.Entry) (err error)
RemoveDirectory(loc *remote_pb.RemoteStorageLocation) (err error)
2021-08-26 22:18:34 +00:00
WriteFile(loc *remote_pb.RemoteStorageLocation, entry *filer_pb.Entry, reader io.Reader) (remoteEntry *filer_pb.RemoteEntry, err error)
UpdateFileMetadata(loc *remote_pb.RemoteStorageLocation, oldEntry *filer_pb.Entry, newEntry *filer_pb.Entry) (err error)
DeleteFile(loc *remote_pb.RemoteStorageLocation) (err error)
2021-09-04 03:42:02 +00:00
ListBuckets() ([]*Bucket, error)
CreateBucket(name string) (err error)
DeleteBucket(name string) (err error)
2021-07-27 05:53:44 +00:00
}
type RemoteStorageClientMaker interface {
2021-08-26 22:18:34 +00:00
Make(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error)
HasBucket() bool
2021-07-27 05:53:44 +00:00
}
type CachedRemoteStorageClient struct {
*remote_pb.RemoteConf
RemoteStorageClient
}
2021-07-27 05:53:44 +00:00
var (
RemoteStorageClientMakers = make(map[string]RemoteStorageClientMaker)
remoteStorageClients = make(map[string]CachedRemoteStorageClient)
2021-07-27 05:53:44 +00:00
remoteStorageClientsLock sync.Mutex
)
2021-09-04 07:18:21 +00:00
func GetAllRemoteStorageNames() string {
var storageNames []string
for k := range RemoteStorageClientMakers {
storageNames = append(storageNames, k)
}
sort.Strings(storageNames)
return strings.Join(storageNames, "|")
}
func GetRemoteStorageNamesHasBucket() string {
var storageNames []string
for k, m := range RemoteStorageClientMakers {
if m.HasBucket() {
storageNames = append(storageNames, k)
}
}
sort.Strings(storageNames)
return strings.Join(storageNames, "|")
}
func ParseRemoteLocation(remoteConfType string, remote string) (remoteStorageLocation *remote_pb.RemoteStorageLocation, err error) {
maker, found := RemoteStorageClientMakers[remoteConfType]
if !found {
return nil, fmt.Errorf("remote storage type %s not found", remoteConfType)
}
if !maker.HasBucket() {
return parseNoBucketLocation(remote), nil
}
return parseBucketLocation(remote), nil
}
2021-08-26 22:18:34 +00:00
func makeRemoteStorageClient(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error) {
2021-07-27 05:53:44 +00:00
maker, found := RemoteStorageClientMakers[remoteConf.Type]
if !found {
return nil, fmt.Errorf("remote storage type %s not found", remoteConf.Type)
}
return maker.Make(remoteConf)
}
2021-08-26 22:18:34 +00:00
func GetRemoteStorage(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error) {
2021-07-27 05:53:44 +00:00
remoteStorageClientsLock.Lock()
defer remoteStorageClientsLock.Unlock()
existingRemoteStorageClient, found := remoteStorageClients[remoteConf.Name]
if found && proto.Equal(existingRemoteStorageClient.RemoteConf, remoteConf) {
return existingRemoteStorageClient.RemoteStorageClient, nil
2021-07-27 05:53:44 +00:00
}
newRemoteStorageClient, err := makeRemoteStorageClient(remoteConf)
if err != nil {
return nil, fmt.Errorf("make remote storage client %s: %v", remoteConf.Name, err)
}
remoteStorageClients[remoteConf.Name] = CachedRemoteStorageClient{
RemoteConf: remoteConf,
RemoteStorageClient: newRemoteStorageClient,
}
2021-07-27 05:53:44 +00:00
return newRemoteStorageClient, nil
}