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.

144 lines
4.2 KiB

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