source: trunk/libtransmission/stats.c @ 7126

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

#1476: crash on exit when stats window is open

  • Property svn:keywords set to Date Rev Author Id
File size: 5.7 KB
Line 
1/*
2 * This file Copyright (C) 2007-2008 Charles Kerr <charles@rebelbase.com>
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 7126 2008-11-17 05:05:11Z charles $
11 */
12
13#include "transmission.h"
14#include "bencode.h"
15#include "platform.h" /* tr_sessionGetConfigDir() */
16#include "stats.h"
17#include "utils.h" /* tr_buildPath */
18
19/***
20****
21***/
22
23struct tr_stats_handle
24{
25    tr_session_stats    single;
26    tr_session_stats    old;
27    time_t              startTime;
28};
29
30static char*
31getOldFilename( const tr_handle * handle )
32{
33    return tr_buildPath( tr_sessionGetConfigDir( handle ), "stats.benc", NULL );
34}
35
36static char*
37getFilename( const tr_handle * handle )
38{
39    return tr_buildPath( tr_sessionGetConfigDir( handle ), "stats.json", NULL );
40}
41
42static void
43loadCumulativeStats( const tr_handle *  handle,
44                     tr_session_stats * setme )
45{
46    int     loaded = FALSE;
47    char   * filename;
48    tr_benc top;
49
50    filename = getFilename( handle );
51    loaded = !tr_bencLoadJSONFile( filename, &top );
52    tr_free( filename );
53
54    if( !loaded )
55    {
56        filename = getOldFilename( handle );
57        loaded = !tr_bencLoadFile( filename, &top );
58        tr_free( filename );
59    }
60
61    if( loaded )
62    {
63        int64_t i;
64
65        if( tr_bencDictFindInt( &top, "downloaded-bytes", &i ) )
66            setme->downloadedBytes = (uint64_t) i;
67        if( tr_bencDictFindInt( &top, "files-added", &i ) )
68            setme->filesAdded = (uint64_t) i;
69        if( tr_bencDictFindInt( &top, "seconds-active", &i ) )
70            setme->secondsActive = (uint64_t) i;
71        if( tr_bencDictFindInt( &top, "session-count", &i ) )
72            setme->sessionCount = (uint64_t) i;
73        if( tr_bencDictFindInt( &top, "uploaded-bytes", &i ) )
74            setme->uploadedBytes = (uint64_t) i;
75
76        tr_bencFree( &top );
77    }
78}
79
80static void
81saveCumulativeStats( const tr_handle *        handle,
82                     const tr_session_stats * s )
83{
84    char * filename;
85    tr_benc top;
86
87    tr_bencInitDict( &top, 5 );
88    tr_bencDictAddInt( &top, "downloaded-bytes", s->downloadedBytes );
89    tr_bencDictAddInt( &top, "files-added",      s->filesAdded );
90    tr_bencDictAddInt( &top, "seconds-active",   s->secondsActive );
91    tr_bencDictAddInt( &top, "session-count",    s->sessionCount );
92    tr_bencDictAddInt( &top, "uploaded-bytes",   s->uploadedBytes );
93
94    filename = getFilename( handle );
95    tr_deepLog( __FILE__, __LINE__, NULL, "Saving stats to \"%s\"", filename );
96    tr_bencSaveJSONFile( filename, &top );
97
98    tr_free( filename );
99    tr_bencFree( &top );
100}
101
102/***
103****
104***/
105
106void
107tr_statsInit( tr_handle * handle )
108{
109    struct tr_stats_handle * stats = tr_new0( struct tr_stats_handle, 1 );
110
111    loadCumulativeStats( handle, &stats->old );
112    stats->single.sessionCount = 1;
113    stats->startTime = time( NULL );
114    handle->sessionStats = stats;
115}
116
117void
118tr_statsClose( tr_handle * handle )
119{
120    tr_session_stats cumulative;
121
122    tr_sessionGetCumulativeStats( handle, &cumulative );
123    saveCumulativeStats( handle, &cumulative );
124
125    tr_free( handle->sessionStats );
126    handle->sessionStats = NULL;
127}
128
129static struct tr_stats_handle *
130getStats( const tr_handle * handle )
131{
132    return handle ? handle->sessionStats : NULL;
133}
134
135/***
136****
137***/
138
139static void
140updateRatio( tr_session_stats * setme )
141{
142    setme->ratio = tr_getRatio( setme->uploadedBytes,
143                                setme->downloadedBytes );
144}
145
146static void
147addStats( tr_session_stats *       setme,
148          const tr_session_stats * a,
149          const tr_session_stats * b )
150{
151    setme->uploadedBytes   = a->uploadedBytes   + b->uploadedBytes;
152    setme->downloadedBytes = a->downloadedBytes + b->downloadedBytes;
153    setme->filesAdded      = a->filesAdded      + b->filesAdded;
154    setme->sessionCount    = a->sessionCount    + b->sessionCount;
155    setme->secondsActive   = a->secondsActive   + b->secondsActive;
156    updateRatio( setme );
157}
158
159void
160tr_sessionGetStats( const tr_handle *  handle,
161                    tr_session_stats * setme )
162{
163    const struct tr_stats_handle * stats = getStats( handle );
164    if( stats )
165    {
166        *setme = stats->single;
167        setme->secondsActive = time( NULL ) - stats->startTime;
168        updateRatio( setme );
169    }
170}
171
172void
173tr_sessionGetCumulativeStats( const tr_handle *  handle,
174                              tr_session_stats * setme )
175{
176    const struct tr_stats_handle * stats = getStats( handle );
177    tr_session_stats current;
178
179    if( stats )
180    {
181        tr_sessionGetStats( handle, &current );
182        addStats( setme, &stats->old, &current );
183    }
184}
185
186void
187tr_sessionClearStats( tr_handle * handle )
188{
189    tr_session_stats zero;
190
191    zero.uploadedBytes = 0;
192    zero.downloadedBytes = 0;
193    zero.ratio = TR_RATIO_NA;
194    zero.filesAdded = 0;
195    zero.sessionCount = 0;
196    zero.secondsActive = 0;
197    handle->sessionStats->single = handle->sessionStats->old = zero;
198
199    handle->sessionStats->startTime = time( NULL );
200}
201
202/**
203***
204**/
205
206void
207tr_statsAddUploaded( tr_handle * handle,
208                     uint32_t    bytes )
209{
210    struct tr_stats_handle * s;
211
212    if( ( s = getStats( handle ) ) )
213        s->single.uploadedBytes += bytes;
214}
215
216void
217tr_statsAddDownloaded( tr_handle * handle,
218                       uint32_t    bytes )
219{
220    struct tr_stats_handle * s;
221
222    if( ( s = getStats( handle ) ) )
223        s->single.downloadedBytes += bytes;
224}
225
226void
227tr_statsFileCreated( tr_handle * handle )
228{
229    struct tr_stats_handle * s;
230
231    if( ( s = getStats( handle ) ) )
232        s->single.filesAdded++;
233}
234
Note: See TracBrowser for help on using the repository browser.