conn_stats.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package torrent
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. "sync/atomic"
  8. pp "github.com/anacrolix/torrent/peer_protocol"
  9. )
  10. // Various connection-level metrics. At the Torrent level these are aggregates. Chunks are messages
  11. // with data payloads. Data is actual torrent content without any overhead. Useful is something we
  12. // needed locally. Unwanted is something we didn't ask for (but may still be useful). Written is
  13. // things sent to the peer, and Read is stuff received from them. Due to the implementation of
  14. // Count, must be aligned on some platforms: See https://github.com/anacrolix/torrent/issues/262.
  15. type ConnStats struct {
  16. // Total bytes on the wire. Includes handshakes and encryption.
  17. BytesWritten Count
  18. BytesWrittenData Count
  19. BytesRead Count
  20. BytesReadData Count
  21. BytesReadUsefulData Count
  22. BytesReadUsefulIntendedData Count
  23. ChunksWritten Count
  24. ChunksRead Count
  25. ChunksReadUseful Count
  26. ChunksReadWasted Count
  27. MetadataChunksRead Count
  28. // Number of pieces data was written to, that subsequently passed verification.
  29. PiecesDirtiedGood Count
  30. // Number of pieces data was written to, that subsequently failed verification. Note that a
  31. // connection may not have been the sole dirtier of a piece.
  32. PiecesDirtiedBad Count
  33. }
  34. func (me *ConnStats) Copy() (ret ConnStats) {
  35. for i := 0; i < reflect.TypeOf(ConnStats{}).NumField(); i++ {
  36. n := reflect.ValueOf(me).Elem().Field(i).Addr().Interface().(*Count).Int64()
  37. reflect.ValueOf(&ret).Elem().Field(i).Addr().Interface().(*Count).Add(n)
  38. }
  39. return
  40. }
  41. type Count struct {
  42. n int64
  43. }
  44. var _ fmt.Stringer = (*Count)(nil)
  45. func (me *Count) Add(n int64) {
  46. atomic.AddInt64(&me.n, n)
  47. }
  48. func (me *Count) Int64() int64 {
  49. return atomic.LoadInt64(&me.n)
  50. }
  51. func (me *Count) String() string {
  52. return fmt.Sprintf("%v", me.Int64())
  53. }
  54. func (me *Count) MarshalJSON() ([]byte, error) {
  55. return json.Marshal(me.n)
  56. }
  57. func (cs *ConnStats) wroteMsg(msg *pp.Message) {
  58. // TODO: Track messages and not just chunks.
  59. switch msg.Type {
  60. case pp.Piece:
  61. cs.ChunksWritten.Add(1)
  62. cs.BytesWrittenData.Add(int64(len(msg.Piece)))
  63. }
  64. }
  65. func (cs *ConnStats) receivedChunk(size int64) {
  66. cs.ChunksRead.Add(1)
  67. cs.BytesReadData.Add(size)
  68. }
  69. func (cs *ConnStats) incrementPiecesDirtiedGood() {
  70. cs.PiecesDirtiedGood.Add(1)
  71. }
  72. func (cs *ConnStats) incrementPiecesDirtiedBad() {
  73. cs.PiecesDirtiedBad.Add(1)
  74. }
  75. func add(n int64, f func(*ConnStats) *Count) func(*ConnStats) {
  76. return func(cs *ConnStats) {
  77. p := f(cs)
  78. p.Add(n)
  79. }
  80. }
  81. type connStatsReadWriter struct {
  82. rw io.ReadWriter
  83. c *PeerConn
  84. }
  85. func (me connStatsReadWriter) Write(b []byte) (n int, err error) {
  86. n, err = me.rw.Write(b)
  87. me.c.wroteBytes(int64(n))
  88. return
  89. }
  90. func (me connStatsReadWriter) Read(b []byte) (n int, err error) {
  91. n, err = me.rw.Read(b)
  92. me.c.readBytes(int64(n))
  93. return
  94. }