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.

88 lines
2.1 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. package operation
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "google.golang.org/grpc"
  7. "github.com/chrislusf/seaweedfs/weed/pb/volume_server_pb"
  8. "github.com/chrislusf/seaweedfs/weed/storage/needle"
  9. )
  10. func TailVolume(masterFn GetMasterFn, grpcDialOption grpc.DialOption, vid needle.VolumeId, sinceNs uint64, timeoutSeconds int, fn func(n *needle.Needle) error) error {
  11. // find volume location, replication, ttl info
  12. lookup, err := LookupVolumeId(masterFn, grpcDialOption, vid.String())
  13. if err != nil {
  14. return fmt.Errorf("look up volume %d: %v", vid, err)
  15. }
  16. if len(lookup.Locations) == 0 {
  17. return fmt.Errorf("unable to locate volume %d", vid)
  18. }
  19. volumeServer := lookup.Locations[0].Url
  20. return TailVolumeFromSource(volumeServer, grpcDialOption, vid, sinceNs, timeoutSeconds, fn)
  21. }
  22. func TailVolumeFromSource(volumeServer string, grpcDialOption grpc.DialOption, vid needle.VolumeId, sinceNs uint64, idleTimeoutSeconds int, fn func(n *needle.Needle) error) error {
  23. return WithVolumeServerClient(volumeServer, grpcDialOption, func(client volume_server_pb.VolumeServerClient) error {
  24. ctx, cancel := context.WithCancel(context.Background())
  25. defer cancel()
  26. stream, err := client.VolumeTailSender(ctx, &volume_server_pb.VolumeTailSenderRequest{
  27. VolumeId: uint32(vid),
  28. SinceNs: sinceNs,
  29. IdleTimeoutSeconds: uint32(idleTimeoutSeconds),
  30. })
  31. if err != nil {
  32. return err
  33. }
  34. for {
  35. resp, recvErr := stream.Recv()
  36. if recvErr != nil {
  37. if recvErr == io.EOF {
  38. break
  39. } else {
  40. return recvErr
  41. }
  42. }
  43. needleHeader := resp.NeedleHeader
  44. needleBody := resp.NeedleBody
  45. if len(needleHeader) == 0 {
  46. continue
  47. }
  48. for !resp.IsLastChunk {
  49. resp, recvErr = stream.Recv()
  50. if recvErr != nil {
  51. if recvErr == io.EOF {
  52. break
  53. } else {
  54. return recvErr
  55. }
  56. }
  57. needleBody = append(needleBody, resp.NeedleBody...)
  58. }
  59. n := new(needle.Needle)
  60. n.ParseNeedleHeader(needleHeader)
  61. err = n.ReadNeedleBodyBytes(needleBody, needle.CurrentVersion)
  62. if err != nil {
  63. return err
  64. }
  65. err = fn(n)
  66. if err != nil {
  67. return err
  68. }
  69. }
  70. return nil
  71. })
  72. }