source: trunk/libtransmission/stats.c @ 9965

Last change on this file since 9965 was 9965, checked in by charles, 12 years ago

(trunk) No code changes here... filling in some of the blanks in the "peers" and "utils" doxygen groups' documentation.

  • Property svn:keywords set to Date Rev Author Id
File size: 6.2 KB
Line 
1/*
2 * This file Copyright (C) 2007-2010 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 9965 2010-01-19 19:37:00Z charles $
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 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    tr_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    int     loaded = FALSE;
52    char   * filename;
53    tr_benc top;
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->single = session->sessionStats->old = zero;
214    session->sessionStats->startTime = tr_time( );
215}
216
217/**
218***
219**/
220
221void
222tr_statsAddUploaded( tr_session * session,
223                     uint32_t    bytes )
224{
225    struct tr_stats_handle * s;
226
227    if( ( s = getStats( session ) ) )
228    {
229        s->single.uploadedBytes += bytes;
230        s->isDirty = TRUE;
231    }
232}
233
234void
235tr_statsAddDownloaded( tr_session * session,
236                       uint32_t     bytes )
237{
238    struct tr_stats_handle * s;
239
240    if( ( s = getStats( session ) ) )
241    {
242        s->single.downloadedBytes += bytes;
243        s->isDirty = TRUE;
244    }
245}
246
247void
248tr_statsFileCreated( tr_session * session )
249{
250    struct tr_stats_handle * s;
251
252    if( ( s = getStats( session ) ) )
253        s->single.filesAdded++;
254}
255
Note: See TracBrowser for help on using the repository browser.