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