• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/libtransmission/
1/*
2 * This file Copyright (C) Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: stats.c 13363 2012-07-01 04:00:27Z jordan $
11 */
12
13#include "transmission.h"
14#include "session.h"
15#include "bencode.h"
16#include "platform.h" /* tr_sessionGetConfigDir() */
17#include "stats.h"
18#include "utils.h" /* tr_buildPath */
19
20/***
21****
22***/
23
24static const struct tr_session_stats STATS_INIT = { 0.0f, 0, 0, 0, 0, 0 };
25
26/** @brief Opaque, per-session data structure for bandwidth use statistics */
27struct tr_stats_handle
28{
29    tr_session_stats    single;
30    tr_session_stats    old;
31    time_t              startTime;
32    bool                isDirty;
33};
34
35static char*
36getOldFilename( const tr_session * session )
37{
38    return tr_buildPath( tr_sessionGetConfigDir( session ), "stats.benc", NULL );
39}
40
41static char*
42getFilename( const tr_session * session )
43{
44    return tr_buildPath( tr_sessionGetConfigDir( session ), "stats.json", NULL );
45}
46
47static void
48loadCumulativeStats( const tr_session * session,
49                     tr_session_stats * setme )
50{
51    tr_benc top;
52    char * filename;
53    bool loaded = false;
54
55    filename = getFilename( session );
56    loaded = !tr_bencLoadFile( &top, TR_FMT_JSON, filename );
57    tr_free( filename );
58
59    if( !loaded )
60    {
61        filename = getOldFilename( session );
62        loaded = !tr_bencLoadFile( &top, TR_FMT_BENC, filename );
63        tr_free( filename );
64    }
65
66    if( loaded )
67    {
68        int64_t i;
69
70        if( tr_bencDictFindInt( &top, "downloaded-bytes", &i ) )
71            setme->downloadedBytes = (uint64_t) i;
72        if( tr_bencDictFindInt( &top, "files-added", &i ) )
73            setme->filesAdded = (uint64_t) i;
74        if( tr_bencDictFindInt( &top, "seconds-active", &i ) )
75            setme->secondsActive = (uint64_t) i;
76        if( tr_bencDictFindInt( &top, "session-count", &i ) )
77            setme->sessionCount = (uint64_t) i;
78        if( tr_bencDictFindInt( &top, "uploaded-bytes", &i ) )
79            setme->uploadedBytes = (uint64_t) i;
80
81        tr_bencFree( &top );
82    }
83}
84
85static void
86saveCumulativeStats( const tr_session * session,
87                     const tr_session_stats * s )
88{
89    char * filename;
90    tr_benc top;
91
92    tr_bencInitDict( &top, 5 );
93    tr_bencDictAddInt( &top, "downloaded-bytes", s->downloadedBytes );
94    tr_bencDictAddInt( &top, "files-added",      s->filesAdded );
95    tr_bencDictAddInt( &top, "seconds-active",   s->secondsActive );
96    tr_bencDictAddInt( &top, "session-count",    s->sessionCount );
97    tr_bencDictAddInt( &top, "uploaded-bytes",   s->uploadedBytes );
98
99    filename = getFilename( session );
100    tr_deepLog( __FILE__, __LINE__, NULL, "Saving stats to \"%s\"", filename );
101    tr_bencToFile( &top, TR_FMT_JSON, filename );
102
103    tr_free( filename );
104    tr_bencFree( &top );
105}
106
107/***
108****
109***/
110
111void
112tr_statsInit( tr_session * session )
113{
114    struct tr_stats_handle * stats = tr_new0( struct tr_stats_handle, 1 );
115
116    loadCumulativeStats( session, &stats->old );
117    stats->single.sessionCount = 1;
118    stats->startTime = tr_time( );
119    session->sessionStats = stats;
120}
121
122static struct tr_stats_handle *
123getStats( const tr_session * session )
124{
125    return session ? session->sessionStats : NULL;
126}
127
128void
129tr_statsSaveDirty( tr_session * session )
130{
131    struct tr_stats_handle * h = getStats( session );
132    if( ( h != NULL ) && h->isDirty )
133    {
134        tr_session_stats cumulative = STATS_INIT;
135        tr_sessionGetCumulativeStats( session, &cumulative );
136        saveCumulativeStats( session, &cumulative );
137        h->isDirty = false;
138    }
139}
140
141void
142tr_statsClose( tr_session * session )
143{
144    tr_statsSaveDirty( session );
145
146    tr_free( session->sessionStats );
147    session->sessionStats = NULL;
148}
149
150/***
151****
152***/
153
154static void
155updateRatio( tr_session_stats * setme )
156{
157    setme->ratio = tr_getRatio( setme->uploadedBytes,
158                                setme->downloadedBytes );
159}
160
161static void
162addStats( tr_session_stats *       setme,
163          const tr_session_stats * a,
164          const tr_session_stats * b )
165{
166    setme->uploadedBytes   = a->uploadedBytes   + b->uploadedBytes;
167    setme->downloadedBytes = a->downloadedBytes + b->downloadedBytes;
168    setme->filesAdded      = a->filesAdded      + b->filesAdded;
169    setme->sessionCount    = a->sessionCount    + b->sessionCount;
170    setme->secondsActive   = a->secondsActive   + b->secondsActive;
171    updateRatio( setme );
172}
173
174void
175tr_sessionGetStats( const tr_session * session,
176                    tr_session_stats * setme )
177{
178    const struct tr_stats_handle * stats = getStats( session );
179    if( stats )
180    {
181        *setme = stats->single;
182        setme->secondsActive = tr_time( ) - stats->startTime;
183        updateRatio( setme );
184    }
185}
186
187void
188tr_sessionGetCumulativeStats( const tr_session * session,
189                              tr_session_stats * setme )
190{
191    const struct tr_stats_handle * stats = getStats( session );
192    tr_session_stats current = STATS_INIT;
193
194    if( stats )
195    {
196        tr_sessionGetStats( session, &current );
197        addStats( setme, &stats->old, &current );
198    }
199}
200
201void
202tr_sessionClearStats( tr_session * session )
203{
204    tr_session_stats zero;
205
206    zero.uploadedBytes = 0;
207    zero.downloadedBytes = 0;
208    zero.ratio = TR_RATIO_NA;
209    zero.filesAdded = 0;
210    zero.sessionCount = 0;
211    zero.secondsActive = 0;
212
213    session->sessionStats->isDirty = true;
214    session->sessionStats->single = session->sessionStats->old = zero;
215    session->sessionStats->startTime = tr_time( );
216}
217
218/**
219***
220**/
221
222void
223tr_statsAddUploaded( tr_session * session,
224                     uint32_t    bytes )
225{
226    struct tr_stats_handle * s;
227
228    if( ( s = getStats( session ) ) )
229    {
230        s->single.uploadedBytes += bytes;
231        s->isDirty = true;
232    }
233}
234
235void
236tr_statsAddDownloaded( tr_session * session,
237                       uint32_t     bytes )
238{
239    struct tr_stats_handle * s;
240
241    if( ( s = getStats( session ) ) )
242    {
243        s->single.downloadedBytes += bytes;
244        s->isDirty = true;
245    }
246}
247
248void
249tr_statsFileCreated( tr_session * session )
250{
251    struct tr_stats_handle * s;
252
253    if( ( s = getStats( session ) ) )
254        s->single.filesAdded++;
255}
256
257