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.

143 lines
4.2 KiB

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