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.

96 lines
2.3 KiB

6 years ago
6 years ago
6 years ago
6 years ago
  1. package source
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "strings"
  8. "github.com/chrislusf/seaweedfs/weed/glog"
  9. "github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
  10. "github.com/chrislusf/seaweedfs/weed/util"
  11. )
  12. type ReplicationSource interface {
  13. ReadPart(part string) io.ReadCloser
  14. }
  15. type FilerSource struct {
  16. grpcAddress string
  17. Dir string
  18. }
  19. func (fs *FilerSource) Initialize(configuration util.Configuration) error {
  20. return fs.initialize(
  21. configuration.GetString("grpcAddress"),
  22. configuration.GetString("directory"),
  23. )
  24. }
  25. func (fs *FilerSource) initialize(grpcAddress string, dir string) (err error) {
  26. fs.grpcAddress = grpcAddress
  27. fs.Dir = dir
  28. return nil
  29. }
  30. func (fs *FilerSource) ReadPart(part string) (filename string, header http.Header, readCloser io.ReadCloser, err error) {
  31. vid2Locations := make(map[string]*filer_pb.Locations)
  32. vid := volumeId(part)
  33. err = fs.withFilerClient(func(client filer_pb.SeaweedFilerClient) error {
  34. glog.V(4).Infof("read lookup volume id locations: %v", vid)
  35. resp, err := client.LookupVolume(context.Background(), &filer_pb.LookupVolumeRequest{
  36. VolumeIds: []string{vid},
  37. })
  38. if err != nil {
  39. return err
  40. }
  41. vid2Locations = resp.LocationsMap
  42. return nil
  43. })
  44. if err != nil {
  45. glog.V(1).Infof("replication lookup volume id %s: %v", vid, err)
  46. return "", nil, nil, fmt.Errorf("replication lookup volume id %s: %v", vid, err)
  47. }
  48. locations := vid2Locations[vid]
  49. if locations == nil || len(locations.Locations) == 0 {
  50. glog.V(1).Infof("replication locate volume id %s: %v", vid, err)
  51. return "", nil, nil, fmt.Errorf("replication locate volume id %s: %v", vid, err)
  52. }
  53. fileUrl := fmt.Sprintf("http://%s/%s", locations.Locations[0].Url, part)
  54. filename, header, readCloser, err = util.DownloadFile(fileUrl)
  55. return filename, header, readCloser, err
  56. }
  57. func (fs *FilerSource) withFilerClient(fn func(filer_pb.SeaweedFilerClient) error) error {
  58. grpcConnection, err := util.GrpcDial(fs.grpcAddress)
  59. if err != nil {
  60. return fmt.Errorf("fail to dial %s: %v", fs.grpcAddress, err)
  61. }
  62. defer grpcConnection.Close()
  63. client := filer_pb.NewSeaweedFilerClient(grpcConnection)
  64. return fn(client)
  65. }
  66. func volumeId(fileId string) string {
  67. lastCommaIndex := strings.LastIndex(fileId, ",")
  68. if lastCommaIndex > 0 {
  69. return fileId[:lastCommaIndex]
  70. }
  71. return fileId
  72. }