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.

199 lines
6.0 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
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/pb"
  6. "github.com/chrislusf/seaweedfs/weed/remote_storage"
  7. "github.com/chrislusf/seaweedfs/weed/util"
  8. "github.com/golang/protobuf/proto"
  9. "google.golang.org/grpc"
  10. "math"
  11. "strings"
  12. "github.com/chrislusf/seaweedfs/weed/glog"
  13. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  14. "github.com/viant/ptrie"
  15. )
  16. const REMOTE_STORAGE_CONF_SUFFIX = ".conf"
  17. const REMOTE_STORAGE_MOUNT_FILE = "mount.mapping"
  18. type FilerRemoteStorage struct {
  19. rules ptrie.Trie
  20. storageNameToConf map[string]*filer_pb.RemoteConf
  21. }
  22. func NewFilerRemoteStorage() (rs *FilerRemoteStorage) {
  23. rs = &FilerRemoteStorage{
  24. rules: ptrie.New(),
  25. storageNameToConf: make(map[string]*filer_pb.RemoteConf),
  26. }
  27. return rs
  28. }
  29. func (rs *FilerRemoteStorage) LoadRemoteStorageConfigurationsAndMapping(filer *Filer) (err error) {
  30. // execute this on filer
  31. limit := int64(math.MaxInt32)
  32. entries, _, err := filer.ListDirectoryEntries(context.Background(), DirectoryEtcRemote, "", false, limit, "", "", "")
  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 RemoveRemoteStorageMapping(oldContent []byte, dir string) (newContent []byte, err error) {
  127. mappings, unmarshalErr := UnmarshalRemoteStorageMappings(oldContent)
  128. if unmarshalErr != nil {
  129. return nil, unmarshalErr
  130. }
  131. // set the new mapping
  132. delete(mappings.Mappings, dir)
  133. if newContent, err = proto.Marshal(mappings); err != nil {
  134. return oldContent, fmt.Errorf("marshal mappings: %v", err)
  135. }
  136. return
  137. }
  138. func ReadMountMappings(grpcDialOption grpc.DialOption, filerAddress string) (mappings *filer_pb.RemoteStorageMapping, readErr error) {
  139. var oldContent []byte
  140. if readErr = pb.WithFilerClient(filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  141. oldContent, readErr = ReadInsideFiler(client, DirectoryEtcRemote, REMOTE_STORAGE_MOUNT_FILE)
  142. return readErr
  143. }); readErr != nil {
  144. return nil, readErr
  145. }
  146. mappings, readErr = UnmarshalRemoteStorageMappings(oldContent)
  147. if readErr != nil {
  148. return nil, fmt.Errorf("unmarshal mappings: %v", readErr)
  149. }
  150. return
  151. }
  152. func ReadRemoteStorageConf(grpcDialOption grpc.DialOption, filerAddress string, storageName string) (conf *filer_pb.RemoteConf, readErr error) {
  153. var oldContent []byte
  154. if readErr = pb.WithFilerClient(filerAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
  155. oldContent, readErr = ReadInsideFiler(client, DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX)
  156. return readErr
  157. }); readErr != nil {
  158. return nil, readErr
  159. }
  160. // unmarshal storage configuration
  161. conf = &filer_pb.RemoteConf{}
  162. if unMarshalErr := proto.Unmarshal(oldContent, conf); unMarshalErr != nil {
  163. readErr = fmt.Errorf("unmarshal %s/%s: %v", DirectoryEtcRemote, storageName+REMOTE_STORAGE_CONF_SUFFIX, unMarshalErr)
  164. return
  165. }
  166. return
  167. }