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.

138 lines
2.8 KiB

  1. package weed_server
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "net"
  7. "strings"
  8. "github.com/seaweedfs/seaweedfs/weed/glog"
  9. "github.com/seaweedfs/seaweedfs/weed/storage/needle"
  10. "github.com/seaweedfs/seaweedfs/weed/util"
  11. )
  12. func (vs *VolumeServer) HandleTcpConnection(c net.Conn) {
  13. defer c.Close()
  14. glog.V(0).Infof("Serving writes from %s", c.RemoteAddr().String())
  15. bufReader := bufio.NewReaderSize(c, 1024*1024)
  16. bufWriter := bufio.NewWriterSize(c, 1024*1024)
  17. for {
  18. cmd, err := bufReader.ReadString('\n')
  19. if err != nil {
  20. if err != io.EOF {
  21. glog.Errorf("read command from %s: %v", c.RemoteAddr().String(), err)
  22. }
  23. return
  24. }
  25. cmd = cmd[:len(cmd)-1]
  26. switch cmd[0] {
  27. case '+':
  28. fileId := cmd[1:]
  29. err = vs.handleTcpPut(fileId, bufReader)
  30. if err == nil {
  31. bufWriter.Write([]byte("+OK\n"))
  32. } else {
  33. bufWriter.Write([]byte("-ERR " + string(err.Error()) + "\n"))
  34. }
  35. case '-':
  36. fileId := cmd[1:]
  37. err = vs.handleTcpDelete(fileId)
  38. if err == nil {
  39. bufWriter.Write([]byte("+OK\n"))
  40. } else {
  41. bufWriter.Write([]byte("-ERR " + string(err.Error()) + "\n"))
  42. }
  43. case '?':
  44. fileId := cmd[1:]
  45. err = vs.handleTcpGet(fileId, bufWriter)
  46. case '!':
  47. bufWriter.Flush()
  48. }
  49. }
  50. }
  51. func (vs *VolumeServer) handleTcpGet(fileId string, writer *bufio.Writer) (err error) {
  52. volumeId, n, err2 := vs.parseFileId(fileId)
  53. if err2 != nil {
  54. return err2
  55. }
  56. volume := vs.store.GetVolume(volumeId)
  57. if volume == nil {
  58. return fmt.Errorf("volume %d not found", volumeId)
  59. }
  60. err = volume.StreamRead(n, writer)
  61. if err != nil {
  62. return err
  63. }
  64. return nil
  65. }
  66. func (vs *VolumeServer) handleTcpPut(fileId string, bufReader *bufio.Reader) (err error) {
  67. volumeId, n, err2 := vs.parseFileId(fileId)
  68. if err2 != nil {
  69. return err2
  70. }
  71. volume := vs.store.GetVolume(volumeId)
  72. if volume == nil {
  73. return fmt.Errorf("volume %d not found", volumeId)
  74. }
  75. sizeBuf := make([]byte, 4)
  76. if _, err = bufReader.Read(sizeBuf); err != nil {
  77. return err
  78. }
  79. dataSize := util.BytesToUint32(sizeBuf)
  80. err = volume.StreamWrite(n, bufReader, dataSize)
  81. if err != nil {
  82. return err
  83. }
  84. return nil
  85. }
  86. func (vs *VolumeServer) handleTcpDelete(fileId string) (err error) {
  87. volumeId, n, err2 := vs.parseFileId(fileId)
  88. if err2 != nil {
  89. return err2
  90. }
  91. _, err = vs.store.DeleteVolumeNeedle(volumeId, n)
  92. if err != nil {
  93. return err
  94. }
  95. return nil
  96. }
  97. func (vs *VolumeServer) parseFileId(fileId string) (needle.VolumeId, *needle.Needle, error) {
  98. commaIndex := strings.LastIndex(fileId, ",")
  99. if commaIndex <= 0 {
  100. return 0, nil, fmt.Errorf("unknown fileId %s", fileId)
  101. }
  102. vid, fid := fileId[0:commaIndex], fileId[commaIndex+1:]
  103. volumeId, ve := needle.NewVolumeId(vid)
  104. if ve != nil {
  105. return 0, nil, fmt.Errorf("unknown volume id in fileId %s", fileId)
  106. }
  107. n := new(needle.Needle)
  108. n.ParsePath(fid)
  109. return volumeId, n, nil
  110. }