github.com/anacrolix/torrent@v1.61.0/conn-stats.go (about)

     1  package torrent
     2  
     3  import (
     4  	"io"
     5  
     6  	pp "github.com/anacrolix/torrent/peer_protocol"
     7  )
     8  
     9  // Various connection-level metrics. At the Torrent level these are aggregates. Chunks are messages
    10  // with data payloads. Data is actual torrent content without any overhead. Useful is something we
    11  // needed locally. Intended is something we were expecting (I think such as when we cancel a request
    12  // but it arrives anyway). Written is things sent to the peer, and Read is stuff received from them.
    13  // Due to the implementation of Count, must be aligned on some platforms: See
    14  // 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  
    20  	BytesRead                   Count
    21  	BytesReadData               Count
    22  	BytesReadUsefulData         Count
    23  	BytesReadUsefulIntendedData Count
    24  
    25  	ChunksWritten Count
    26  
    27  	ChunksRead       Count
    28  	ChunksReadUseful Count
    29  	ChunksReadWasted Count
    30  
    31  	MetadataChunksRead Count
    32  
    33  	// Number of pieces data was written to, that subsequently passed verification.
    34  	PiecesDirtiedGood Count
    35  	// Number of pieces data was written to, that subsequently failed verification. Note that a
    36  	// connection may not have been the sole dirtier of a piece.
    37  	PiecesDirtiedBad Count
    38  }
    39  
    40  func (me *ConnStats) Copy() (ret ConnStats) {
    41  	return copyCountFields(me)
    42  }
    43  
    44  func (cs *ConnStats) wroteMsg(msg *pp.Message) {
    45  	// TODO: Track messages and not just chunks.
    46  	switch msg.Type {
    47  	case pp.Piece:
    48  		cs.ChunksWritten.Add(1)
    49  		cs.BytesWrittenData.Add(int64(len(msg.Piece)))
    50  	}
    51  }
    52  
    53  func (cs *ConnStats) receivedChunk(size int64) {
    54  	cs.ChunksRead.Add(1)
    55  	cs.BytesReadData.Add(size)
    56  }
    57  
    58  func (cs *ConnStats) incrementPiecesDirtiedGood() bool {
    59  	cs.PiecesDirtiedGood.Add(1)
    60  	// This method is used as an iterator and should never return early.
    61  	return true
    62  }
    63  
    64  func (cs *ConnStats) incrementPiecesDirtiedBad() bool {
    65  	cs.PiecesDirtiedBad.Add(1)
    66  	// This method is used as an iterator and should never return early.
    67  	return true
    68  }
    69  
    70  func add(n int64, f func(*ConnStats) *Count) func(*ConnStats) {
    71  	return func(cs *ConnStats) {
    72  		p := f(cs)
    73  		p.Add(n)
    74  	}
    75  }
    76  
    77  type connStatsReadWriter struct {
    78  	rw io.ReadWriter
    79  	c  *PeerConn
    80  }
    81  
    82  func (me connStatsReadWriter) Write(b []byte) (n int, err error) {
    83  	n, err = me.rw.Write(b)
    84  	me.c.wroteBytes(int64(n))
    85  	return
    86  }
    87  
    88  func (me connStatsReadWriter) Read(b []byte) (n int, err error) {
    89  	n, err = me.rw.Read(b)
    90  	me.c.readBytes(int64(n))
    91  	return
    92  }