You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
4.1 KiB

4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package remote_storage
  2. import (
  3. "fmt"
  4. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  5. "github.com/chrislusf/seaweedfs/weed/pb/remote_pb"
  6. "github.com/golang/protobuf/proto"
  7. "io"
  8. "strings"
  9. "sync"
  10. )
  11. func ParseLocationName(remote string) (locationName string) {
  12. if strings.HasSuffix(string(remote), "/") {
  13. remote = remote[:len(remote)-1]
  14. }
  15. parts := strings.SplitN(string(remote), "/", 2)
  16. if len(parts) >= 1 {
  17. return parts[0]
  18. }
  19. return
  20. }
  21. func parseBucketLocation(remote string) (loc *remote_pb.RemoteStorageLocation) {
  22. loc = &remote_pb.RemoteStorageLocation{}
  23. if strings.HasSuffix(string(remote), "/") {
  24. remote = remote[:len(remote)-1]
  25. }
  26. parts := strings.SplitN(string(remote), "/", 3)
  27. if len(parts) >= 1 {
  28. loc.Name = parts[0]
  29. }
  30. if len(parts) >= 2 {
  31. loc.Bucket = parts[1]
  32. }
  33. loc.Path = string(remote[len(loc.Name)+1+len(loc.Bucket):])
  34. if loc.Path == "" {
  35. loc.Path = "/"
  36. }
  37. return
  38. }
  39. func parseNoBucketLocation(remote string) (loc *remote_pb.RemoteStorageLocation) {
  40. loc = &remote_pb.RemoteStorageLocation{}
  41. if strings.HasSuffix(string(remote), "/") {
  42. remote = remote[:len(remote)-1]
  43. }
  44. parts := strings.SplitN(string(remote), "/", 2)
  45. if len(parts) >= 1 {
  46. loc.Name = parts[0]
  47. }
  48. loc.Path = string(remote[len(loc.Name):])
  49. if loc.Path == "" {
  50. loc.Path = "/"
  51. }
  52. return
  53. }
  54. func FormatLocation(loc *remote_pb.RemoteStorageLocation) string {
  55. if loc.Bucket == "" {
  56. return fmt.Sprintf("%s%s", loc.Name, loc.Path)
  57. }
  58. return fmt.Sprintf("%s/%s%s", loc.Name, loc.Bucket, loc.Path)
  59. }
  60. type VisitFunc func(dir string, name string, isDirectory bool, remoteEntry *filer_pb.RemoteEntry) error
  61. type RemoteStorageClient interface {
  62. Traverse(loc *remote_pb.RemoteStorageLocation, visitFn VisitFunc) error
  63. ReadFile(loc *remote_pb.RemoteStorageLocation, offset int64, size int64) (data []byte, err error)
  64. WriteDirectory(loc *remote_pb.RemoteStorageLocation, entry *filer_pb.Entry) (err error)
  65. RemoveDirectory(loc *remote_pb.RemoteStorageLocation) (err error)
  66. WriteFile(loc *remote_pb.RemoteStorageLocation, entry *filer_pb.Entry, reader io.Reader) (remoteEntry *filer_pb.RemoteEntry, err error)
  67. UpdateFileMetadata(loc *remote_pb.RemoteStorageLocation, oldEntry *filer_pb.Entry, newEntry *filer_pb.Entry) (err error)
  68. DeleteFile(loc *remote_pb.RemoteStorageLocation) (err error)
  69. }
  70. type RemoteStorageClientMaker interface {
  71. Make(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error)
  72. HasBucket() bool
  73. }
  74. type CachedRemoteStorageClient struct {
  75. *remote_pb.RemoteConf
  76. RemoteStorageClient
  77. }
  78. var (
  79. RemoteStorageClientMakers = make(map[string]RemoteStorageClientMaker)
  80. remoteStorageClients = make(map[string]CachedRemoteStorageClient)
  81. remoteStorageClientsLock sync.Mutex
  82. )
  83. func ParseRemoteLocation(remoteConfType string, remote string) (remoteStorageLocation *remote_pb.RemoteStorageLocation, err error) {
  84. maker, found := RemoteStorageClientMakers[remoteConfType]
  85. if !found {
  86. return nil, fmt.Errorf("remote storage type %s not found", remoteConfType)
  87. }
  88. if !maker.HasBucket() {
  89. return parseNoBucketLocation(remote), nil
  90. }
  91. return parseBucketLocation(remote), nil
  92. }
  93. func makeRemoteStorageClient(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error) {
  94. maker, found := RemoteStorageClientMakers[remoteConf.Type]
  95. if !found {
  96. return nil, fmt.Errorf("remote storage type %s not found", remoteConf.Type)
  97. }
  98. return maker.Make(remoteConf)
  99. }
  100. func GetRemoteStorage(remoteConf *remote_pb.RemoteConf) (RemoteStorageClient, error) {
  101. remoteStorageClientsLock.Lock()
  102. defer remoteStorageClientsLock.Unlock()
  103. existingRemoteStorageClient, found := remoteStorageClients[remoteConf.Name]
  104. if found && proto.Equal(existingRemoteStorageClient.RemoteConf, remoteConf) {
  105. return existingRemoteStorageClient.RemoteStorageClient, nil
  106. }
  107. newRemoteStorageClient, err := makeRemoteStorageClient(remoteConf)
  108. if err != nil {
  109. return nil, fmt.Errorf("make remote storage client %s: %v", remoteConf.Name, err)
  110. }
  111. remoteStorageClients[remoteConf.Name] = CachedRemoteStorageClient{
  112. RemoteConf: remoteConf,
  113. RemoteStorageClient: newRemoteStorageClient,
  114. }
  115. return newRemoteStorageClient, nil
  116. }