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.

183 lines
5.6 KiB

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
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package filer
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/chrislusf/seaweedfs/weed/pb"
  6. "github.com/chrislusf/seaweedfs/weed/remote_storage"
  7. _ "github.com/chrislusf/seaweedfs/weed/remote_storage/s3"
  8. "github.com/chrislusf/seaweedfs/weed/util"
  9. "github.com/golang/protobuf/proto"
  10. "google.golang.org/grpc"
  11. "math"
  12. "strings"
  13. "github.com/chrislusf/seaweedfs/weed/glog"
  14. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  15. "github.com/viant/ptrie"
  16. )
  17. const REMOTE_STORAGE_CONF_SUFFIX = ".conf"
  18. const REMOTE_STORAGE_MOUNT_FILE = "mount.mapping"
  19. type FilerRemoteStorage struct {
  20. rules ptrie.Trie
  21. storageNameToConf map[string]*filer_pb.RemoteConf
  22. }
  23. func NewFilerRemoteStorage() (rs *FilerRemoteStorage) {
  24. rs = &FilerRemoteStorage{
  25. rules: ptrie.New(),
  26. storageNameToConf: make(map[string]*filer_pb.RemoteConf),
  27. }
  28. return rs
  29. }
  30. func (rs *FilerRemoteStorage) LoadRemoteStorageConfigurationsAndMapping(filer *Filer) (err error) {
  31. // execute this on filer
  32. entries, _, err := filer.ListDirectoryEntries(context.Background(), DirectoryEtcRemote, "", false, math.MaxInt64, "", "", "")
  33. if err != nil {
  34. if err == filer_pb.ErrNotFound {
  35. return nil
  36. }
  37. glog.Errorf("read remote storage %s: %v", DirectoryEtcRemote, err)
  38. return
  39. }
  40. for _, entry := range entries {
  41. if entry.Name() == REMOTE_STORAGE_MOUNT_FILE {
  42. if err := rs.loadRemoteStorageMountMapping(entry.Content); err != nil {
  43. return err
  44. }
  45. continue
  46. }
  47. if !strings.HasSuffix(entry.Name(), REMOTE_STORAGE_CONF_SUFFIX) {
  48. return nil
  49. }
  50. conf := &filer_pb.RemoteConf{}
  51. if err := proto.Unmarshal(entry.Content, conf); err != nil {
  52. return fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, entry.Name(), err)
  53. }
  54. rs.storageNameToConf[conf.Name] = conf
  55. }
  56. return nil
  57. }
  58. func (rs *FilerRemoteStorage) loadRemoteStorageMountMapping(data []byte) (err error) {
  59. mappings := &filer_pb.RemoteStorageMapping{}
  60. if err := proto.Unmarshal(data, mappings); err != nil {
  61. return fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, REMOTE_STORAGE_MOUNT_FILE, err)
  62. }
  63. for dir, storageLocation := range mappings.Mappings {
  64. rs.mapDirectoryToRemoteStorage(util.FullPath(dir), storageLocation)
  65. }
  66. return nil
  67. }
  68. func (rs *FilerRemoteStorage) mapDirectoryToRemoteStorage(dir util.FullPath, loc *filer_pb.RemoteStorageLocation) {
  69. rs.rules.Put([]byte(dir+"/"), loc)
  70. }
  71. func (rs *FilerRemoteStorage) FindMountDirectory(p util.FullPath) (mountDir util.FullPath, remoteLocation *filer_pb.RemoteStorageLocation) {
  72. rs.rules.MatchPrefix([]byte(p), func(key []byte, value interface{}) bool {
  73. mountDir = util.FullPath(string(key[:len(key)-1]))
  74. remoteLocation = value.(*filer_pb.RemoteStorageLocation)
  75. return true
  76. })
  77. return
  78. }
  79. func (rs *FilerRemoteStorage) FindRemoteStorageClient(p util.FullPath) (client remote_storage.RemoteStorageClient, remoteConf *filer_pb.RemoteConf, found bool) {
  80. var storageLocation *filer_pb.RemoteStorageLocation
  81. rs.rules.MatchPrefix([]byte(p), func(key []byte, value interface{}) bool {
  82. storageLocation = value.(*filer_pb.RemoteStorageLocation)
  83. return true
  84. })
  85. if storageLocation == nil {
  86. found = false
  87. return
  88. }
  89. return rs.GetRemoteStorageClient(storageLocation.Name)
  90. }
  91. func (rs *FilerRemoteStorage) GetRemoteStorageClient(storageName string) (client remote_storage.RemoteStorageClient, remoteConf *filer_pb.RemoteConf, found bool) {
  92. remoteConf, found = rs.storageNameToConf[storageName]
  93. if !found {
  94. return
  95. }
  96. var err error
  97. if client, err = remote_storage.GetRemoteStorage(remoteConf); err == nil {
  98. found = true
  99. return
  100. }
  101. return
  102. }
  103. func UnmarshalRemoteStorageMappings(oldContent []byte) (mappings *filer_pb.RemoteStorageMapping, err error) {
  104. mappings = &filer_pb.RemoteStorageMapping{
  105. Mappings: make(map[string]*filer_pb.RemoteStorageLocation),
  106. }
  107. if len(oldContent) > 0 {
  108. if err = proto.Unmarshal(oldContent, mappings); err != nil {
  109. glog.Warningf("unmarshal existing mappings: %v", err)
  110. }
  111. }
  112. return
  113. }
  114. func AddRemoteStorageMapping(oldContent []byte, dir string, storageLocation *filer_pb.RemoteStorageLocation) (newContent []byte, err error) {
  115. mappings, unmarshalErr := UnmarshalRemoteStorageMappings(oldContent)
  116. if unmarshalErr != nil {
  117. // skip
  118. }
  119. // set the new mapping
  120. mappings.Mappings[dir] = storageLocation
  121. if newContent, err = proto.Marshal(mappings); err != nil {
  122. return oldContent, fmt.Errorf("marshal mappings: %v", err)
  123. }
  124. return
  125. }
  126. func ReadMountMappings(grpcDialOption grpc.DialOption, filerAddress string) (mappings *filer_pb.RemoteStorageMapping, readErr error) {
  127. var oldContent []byte
  128. if readErr = pb.WithFilerClient(filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  129. oldContent, readErr = ReadInsideFiler(client, DirectoryEtcRemote, REMOTE_STORAGE_MOUNT_FILE)
  130. return readErr
  131. }); readErr != nil {
  132. return nil, readErr
  133. }
  134. mappings, readErr = UnmarshalRemoteStorageMappings(oldContent)
  135. if readErr != nil {
  136. return nil, fmt.Errorf("unmarshal mappings: %v", readErr)
  137. }
  138. return
  139. }
  140. func ReadRemoteStorageConf(grpcDialOption grpc.DialOption, filerAddress string, storageName string) (conf *filer_pb.RemoteConf, readErr error) {
  141. var oldContent []byte
  142. if readErr = pb.WithFilerClient(filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  143. oldContent, readErr = ReadInsideFiler(client, DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX)
  144. return readErr
  145. }); readErr != nil {
  146. return nil, readErr
  147. }
  148. // unmarshal storage configuration
  149. conf = &filer_pb.RemoteConf{}
  150. if unMarshalErr := proto.Unmarshal(oldContent, conf); unMarshalErr != nil {
  151. readErr = fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX, unMarshalErr)
  152. return
  153. }
  154. return
  155. }