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.

114 lines
2.5 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
  1. package wdclient
  2. import (
  3. "bufio"
  4. "bytes"
  5. "fmt"
  6. "github.com/chrislusf/seaweedfs/weed/glog"
  7. "github.com/chrislusf/seaweedfs/weed/pb"
  8. "github.com/chrislusf/seaweedfs/weed/udptransfer"
  9. "github.com/chrislusf/seaweedfs/weed/util"
  10. "github.com/chrislusf/seaweedfs/weed/wdclient/net2"
  11. "io"
  12. "net"
  13. "time"
  14. )
  15. // VolumeUdpClient put/get/delete file chunks directly on volume servers without replication
  16. type VolumeUdpClient struct {
  17. cp net2.ConnectionPool
  18. }
  19. type VolumeUdpConn struct {
  20. net.Conn
  21. bufWriter *bufio.Writer
  22. bufReader *bufio.Reader
  23. }
  24. func NewVolumeUdpClient() *VolumeUdpClient {
  25. MaxIdleTime := 10 * time.Second
  26. return &VolumeUdpClient{
  27. cp: net2.NewMultiConnectionPool(net2.ConnectionOptions{
  28. MaxActiveConnections: 16,
  29. MaxIdleConnections: 1,
  30. MaxIdleTime: &MaxIdleTime,
  31. DialMaxConcurrency: 0,
  32. Dial: func(network string, address string) (net.Conn, error) {
  33. listener, err := udptransfer.NewEndpoint(&udptransfer.Params{
  34. LocalAddr: "",
  35. Bandwidth: 100,
  36. FastRetransmit: true,
  37. FlatTraffic: true,
  38. IsServ: false,
  39. })
  40. if err != nil {
  41. return nil, err
  42. }
  43. conn, err := listener.Dial(address)
  44. if err != nil {
  45. return nil, err
  46. }
  47. return &VolumeUdpConn{
  48. conn,
  49. bufio.NewWriter(conn),
  50. bufio.NewReader(conn),
  51. }, err
  52. },
  53. NowFunc: nil,
  54. ReadTimeout: 0,
  55. WriteTimeout: 0,
  56. }),
  57. }
  58. }
  59. func (c *VolumeUdpClient) PutFileChunk(volumeServerAddress string, fileId string, fileSize uint32, fileReader io.Reader) (err error) {
  60. udpAddress, parseErr := pb.ParseServerAddress(volumeServerAddress, 20001)
  61. if parseErr != nil {
  62. return parseErr
  63. }
  64. c.cp.Register("udp", udpAddress)
  65. udpConn, getErr := c.cp.Get("udp", udpAddress)
  66. if getErr != nil {
  67. return fmt.Errorf("get connection to %s: %v", udpAddress, getErr)
  68. }
  69. conn := udpConn.RawConn().(*VolumeUdpConn)
  70. defer func() {
  71. if err != nil {
  72. udpConn.DiscardConnection()
  73. } else {
  74. udpConn.ReleaseConnection()
  75. }
  76. }()
  77. buf := []byte("+" + fileId + "\n")
  78. _, err = conn.bufWriter.Write([]byte(buf))
  79. if err != nil {
  80. return
  81. }
  82. util.Uint32toBytes(buf[0:4], fileSize)
  83. _, err = conn.bufWriter.Write(buf[0:4])
  84. if err != nil {
  85. return
  86. }
  87. _, err = io.Copy(conn.bufWriter, fileReader)
  88. if err != nil {
  89. return
  90. }
  91. conn.bufWriter.Write([]byte("!\n"))
  92. conn.bufWriter.Flush()
  93. ret, _, err := conn.bufReader.ReadLine()
  94. if err != nil {
  95. glog.V(0).Infof("upload by udp: %v", err)
  96. return
  97. }
  98. if !bytes.HasPrefix(ret, []byte("+OK")) {
  99. glog.V(0).Infof("upload by udp: %v", string(ret))
  100. }
  101. return nil
  102. }