source: trunk/libtransmission/stats.c

Last change on this file was 14491, checked in by mikedld, 6 years ago

#5908: Check for tr_loadFile return value instead of errno in tr_variantFromFile

Seems like there could be a defect in uClibc making errno not
thread-local. Don't rely on errno value but check function return value
instead which is a better failure indicator.

Return errors from tr_loadFile and tr_variantFromFile via tr_error.
Fix tr_sessionLoadSettings to not fail on Windows if settings.json
does not exist.

  • Property svn:keywords set to Date Rev Author Id
File size: 5.8 KB
Line 
1/*
2 * This file Copyright (C) 2007-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: stats.c 14491 2015-04-11 10:51:59Z mikedld $
8 */
9
10#include "transmission.h"
11#include "session.h"
12#include "log.h"
13#include "platform.h" /* tr_sessionGetConfigDir () */
14#include "stats.h"
15#include "utils.h" /* tr_buildPath */
16#include "variant.h"
17
18/***
19****
20***/
21
22static const struct tr_session_stats STATS_INIT = { 0.0f, 0, 0, 0, 0, 0 };
23
24/** @brief Opaque, per-session data structure for bandwidth use statistics */
25struct tr_stats_handle
26{
27  tr_session_stats  single;
28  tr_session_stats  old;
29  time_t            startTime;
30  bool              isDirty;
31};
32
33static char*
34getOldFilename (const tr_session * session)
35{
36  return tr_buildPath (tr_sessionGetConfigDir (session), "stats.benc", NULL);
37}
38
39static char*
40getFilename (const tr_session * session)
41{
42  return tr_buildPath (tr_sessionGetConfigDir (session), "stats.json", NULL);
43}
44
45static void
46loadCumulativeStats (const tr_session * session, tr_session_stats * setme)
47{
48  tr_variant top;
49  char * filename;
50  bool loaded = false;
51
52  filename = getFilename (session);
53  loaded = tr_variantFromFile (&top, TR_VARIANT_FMT_JSON, filename, NULL);
54  tr_free (filename);
55
56  if (!loaded)
57    {
58      filename = getOldFilename (session);
59      loaded = tr_variantFromFile (&top, TR_VARIANT_FMT_BENC, filename, NULL);
60      tr_free (filename);
61    }
62
63  if (loaded)
64    {
65      int64_t i;
66
67      if (tr_variantDictFindInt (&top, TR_KEY_downloaded_bytes, &i))
68        setme->downloadedBytes = (uint64_t) i;
69      if (tr_variantDictFindInt (&top, TR_KEY_files_added, &i))
70        setme->filesAdded = (uint64_t) i;
71      if (tr_variantDictFindInt (&top, TR_KEY_seconds_active, &i))
72        setme->secondsActive = (uint64_t) i;
73      if (tr_variantDictFindInt (&top, TR_KEY_session_count, &i))
74        setme->sessionCount = (uint64_t) i;
75      if (tr_variantDictFindInt (&top, TR_KEY_uploaded_bytes, &i))
76        setme->uploadedBytes = (uint64_t) i;
77
78      tr_variantFree (&top);
79    }
80}
81
82static void
83saveCumulativeStats (const tr_session * session, const tr_session_stats * s)
84{
85  char * filename;
86  tr_variant top;
87
88  tr_variantInitDict (&top, 5);
89  tr_variantDictAddInt (&top, TR_KEY_downloaded_bytes, s->downloadedBytes);
90  tr_variantDictAddInt (&top, TR_KEY_files_added,      s->filesAdded);
91  tr_variantDictAddInt (&top, TR_KEY_seconds_active,   s->secondsActive);
92  tr_variantDictAddInt (&top, TR_KEY_session_count,    s->sessionCount);
93  tr_variantDictAddInt (&top, TR_KEY_uploaded_bytes,   s->uploadedBytes);
94
95  filename = getFilename (session);
96  tr_logAddDeep (__FILE__, __LINE__, NULL, "Saving stats to \"%s\"", filename);
97  tr_variantToFile (&top, TR_VARIANT_FMT_JSON, filename);
98
99  tr_free (filename);
100  tr_variantFree (&top);
101}
102
103/***
104****
105***/
106
107void
108tr_statsInit (tr_session * session)
109{
110  struct tr_stats_handle * stats = tr_new0 (struct tr_stats_handle, 1);
111
112  loadCumulativeStats (session, &stats->old);
113  stats->single.sessionCount = 1;
114  stats->startTime = tr_time ();
115  session->sessionStats = stats;
116}
117
118static struct tr_stats_handle *
119getStats (const tr_session * session)
120{
121  return session ? session->sessionStats : NULL;
122}
123
124void
125tr_statsSaveDirty (tr_session * session)
126{
127  struct tr_stats_handle * h = getStats (session);
128
129  if ((h != NULL) && h->isDirty)
130    {
131      tr_session_stats cumulative = STATS_INIT;
132      tr_sessionGetCumulativeStats (session, &cumulative);
133      saveCumulativeStats (session, &cumulative);
134      h->isDirty = false;
135    }
136}
137
138void
139tr_statsClose (tr_session * session)
140{
141  tr_statsSaveDirty (session);
142
143  tr_free (session->sessionStats);
144  session->sessionStats = NULL;
145}
146
147/***
148****
149***/
150
151static void
152updateRatio (tr_session_stats * setme)
153{
154  setme->ratio = tr_getRatio (setme->uploadedBytes, setme->downloadedBytes);
155}
156
157static void
158addStats (tr_session_stats       * setme,
159          const tr_session_stats * a,
160          const tr_session_stats * b)
161{
162  setme->uploadedBytes   = a->uploadedBytes   + b->uploadedBytes;
163  setme->downloadedBytes = a->downloadedBytes + b->downloadedBytes;
164  setme->filesAdded      = a->filesAdded      + b->filesAdded;
165  setme->sessionCount    = a->sessionCount    + b->sessionCount;
166  setme->secondsActive   = a->secondsActive   + b->secondsActive;
167  updateRatio (setme);
168}
169
170void
171tr_sessionGetStats (const tr_session * session, tr_session_stats * setme)
172{
173  const struct tr_stats_handle * stats = getStats (session);
174
175  if (stats)
176    {
177      *setme = stats->single;
178      setme->secondsActive = tr_time () - stats->startTime;
179      updateRatio (setme);
180    }
181}
182
183void
184tr_sessionGetCumulativeStats (const tr_session * session,
185                              tr_session_stats * setme)
186{
187  const struct tr_stats_handle * stats = getStats (session);
188  tr_session_stats current = STATS_INIT;
189
190  if (stats)
191    {
192      tr_sessionGetStats (session, &current);
193      addStats (setme, &stats->old, &current);
194    }
195}
196
197void
198tr_sessionClearStats (tr_session * session)
199{
200  tr_session_stats zero;
201
202  zero.uploadedBytes = 0;
203  zero.downloadedBytes = 0;
204  zero.ratio = TR_RATIO_NA;
205  zero.filesAdded = 0;
206  zero.sessionCount = 0;
207  zero.secondsActive = 0;
208
209  session->sessionStats->isDirty = true;
210  session->sessionStats->single = session->sessionStats->old = zero;
211  session->sessionStats->startTime = tr_time ();
212}
213
214/**
215***
216**/
217
218void
219tr_statsAddUploaded (tr_session * session, uint32_t bytes)
220{
221  struct tr_stats_handle * s;
222
223  if ((s = getStats (session)))
224    {
225      s->single.uploadedBytes += bytes;
226      s->isDirty = true;
227    }
228}
229
230void
231tr_statsAddDownloaded (tr_session * session, uint32_t bytes)
232{
233  struct tr_stats_handle * s;
234
235  if ((s = getStats (session)))
236    {
237      s->single.downloadedBytes += bytes;
238      s->isDirty = true;
239    }
240}
241
242void
243tr_statsFileCreated (tr_session * session)
244{
245  struct tr_stats_handle * s;
246
247  if ((s = getStats (session)))
248    s->single.filesAdded++;
249}
250
Note: See TracBrowser for help on using the repository browser.