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.

122 lines
3.5 KiB

6 years ago
6 years ago
6 years ago
  1. package operation
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "google.golang.org/grpc"
  10. "github.com/chrislusf/seaweedfs/weed/glog"
  11. "github.com/chrislusf/seaweedfs/weed/pb/master_pb"
  12. "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
  13. "github.com/chrislusf/seaweedfs/weed/util"
  14. )
  15. var (
  16. connectionPool = make(map[string]*sync.Pool)
  17. connectionPoolLock sync.Mutex
  18. )
  19. func WithVolumeServerClient(volumeServer string, grpcDialOption grpc.DialOption, fn func(context.Context, volume_server_pb.VolumeServerClient) error) error {
  20. ctx := context.Background()
  21. grpcAddress, err := toVolumeServerGrpcAddress(volumeServer)
  22. if err != nil {
  23. return err
  24. }
  25. return util.WithCachedGrpcClient(ctx, func(ctx2 context.Context, grpcConnection *grpc.ClientConn) error {
  26. client := volume_server_pb.NewVolumeServerClient(grpcConnection)
  27. return fn(ctx2, client)
  28. }, grpcAddress, grpcDialOption)
  29. }
  30. func toVolumeServerGrpcAddress(volumeServer string) (grpcAddress string, err error) {
  31. sepIndex := strings.LastIndex(volumeServer, ":")
  32. port, err := strconv.Atoi(volumeServer[sepIndex+1:])
  33. if err != nil {
  34. glog.Errorf("failed to parse volume server address: %v", volumeServer)
  35. return "", err
  36. }
  37. return fmt.Sprintf("%s:%d", volumeServer[0:sepIndex], port+10000), nil
  38. }
  39. func WithVolumeServerTcpConnection(volumeServer string, fn func(conn net.Conn) error) error {
  40. tcpAddress, err := toVolumeServerTcpAddress(volumeServer)
  41. if err != nil {
  42. return err
  43. }
  44. conn := getConnection(tcpAddress)
  45. defer releaseConnection(conn, tcpAddress)
  46. err = fn(conn)
  47. return err
  48. }
  49. func getConnection(tcpAddress string) net.Conn {
  50. connectionPoolLock.Lock()
  51. defer connectionPoolLock.Unlock()
  52. pool, found := connectionPool[tcpAddress]
  53. if !found {
  54. pool = &sync.Pool{New: func() interface{} {
  55. conn, err := net.Dial("tcp", tcpAddress)
  56. if err != nil {
  57. glog.Errorf("failed to connect to %s: %v", tcpAddress, err)
  58. return conn
  59. }
  60. // println("connected", tcpAddress, "=>", conn.LocalAddr().String())
  61. return conn
  62. }}
  63. connectionPool[tcpAddress] = pool
  64. }
  65. conn := pool.Get().(net.Conn)
  66. // println("get connection", tcpAddress, "=>", conn.LocalAddr().String())
  67. return conn
  68. }
  69. func releaseConnection(conn net.Conn, tcpAddress string) {
  70. connectionPoolLock.Lock()
  71. defer connectionPoolLock.Unlock()
  72. pool, found := connectionPool[tcpAddress]
  73. if !found {
  74. // println("can not return connection", tcpAddress, "=>", conn.LocalAddr().String())
  75. return
  76. }
  77. pool.Put(conn)
  78. // println("returned connection", tcpAddress, "=>", conn.LocalAddr().String())
  79. }
  80. func toVolumeServerTcpAddress(volumeServer string) (grpcAddress string, err error) {
  81. sepIndex := strings.LastIndex(volumeServer, ":")
  82. port, err := strconv.Atoi(volumeServer[sepIndex+1:])
  83. if err != nil {
  84. glog.Errorf("failed to parse volume server address: %v", volumeServer)
  85. return "", err
  86. }
  87. return fmt.Sprintf("%s:%d", volumeServer[0:sepIndex], port+20000), nil
  88. }
  89. func WithMasterServerClient(masterServer string, grpcDialOption grpc.DialOption, fn func(ctx2 context.Context, masterClient master_pb.SeaweedClient) error) error {
  90. ctx := context.Background()
  91. masterGrpcAddress, parseErr := util.ParseServerToGrpcAddress(masterServer)
  92. if parseErr != nil {
  93. return fmt.Errorf("failed to parse master grpc %v: %v", masterServer, parseErr)
  94. }
  95. return util.WithCachedGrpcClient(ctx, func(ctx2 context.Context, grpcConnection *grpc.ClientConn) error {
  96. client := master_pb.NewSeaweedClient(grpcConnection)
  97. return fn(ctx2, client)
  98. }, masterGrpcAddress, grpcDialOption)
  99. }