Status: | Merged |
---|---|
Approved by: | Michael Frey |
Approved revision: | 100 |
Merged at revision: | 83 |
Proposed branch: | lp:~sforshee/powerd/stats |
Merge into: | lp:powerd |
Diff against target: |
994 lines (+778/-22) 9 files modified
CMakeLists.txt (+1/-0) cli/powerd-cli.c (+200/-1) data/com.canonical.powerd.xml (+8/-0) src/display-request.c (+37/-21) src/power-request.c (+2/-0) src/powerd-internal.h (+16/-0) src/powerd-object.c (+4/-0) src/powerd.cpp (+2/-0) src/stats.c (+508/-0) |
To merge this branch: | bzr merge lp:~sforshee/powerd/stats |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Frey (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email:
|
Commit message
Add support for collecting and reporting statistics about requests
Description of the change
Add support for collecting and reporting statistics about requests
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
- 99. By Seth Forshee
-
stats: Fix accounting and reporting of max_active_time
- 100. By Seth Forshee
-
powerd-cli: Reorder flag fields in display stats output
Printing out the "on time" and "on since" times for a given flag
side-by-side groups together fields which are likely to be used
together.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:99
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Seth Forshee (sforshee) wrote : | # |
Sample output: http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:100
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michael Frey (mfrey) wrote : | # |
tested. Works well.
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2013-07-23 14:42:07 +0000 | |||
3 | +++ CMakeLists.txt 2013-08-12 14:34:58 +0000 | |||
4 | @@ -46,6 +46,7 @@ | |||
5 | 46 | src/powerd-client.c | 46 | src/powerd-client.c |
6 | 47 | src/powerd-object.c | 47 | src/powerd-object.c |
7 | 48 | src/powerd-sensors.cpp | 48 | src/powerd-sensors.cpp |
8 | 49 | src/stats.c | ||
9 | 49 | src/util.c | 50 | src/util.c |
10 | 50 | src/${GDBUS_NAME}.c | 51 | src/${GDBUS_NAME}.c |
11 | 51 | ) | 52 | ) |
12 | 52 | 53 | ||
13 | === modified file 'cli/powerd-cli.c' | |||
14 | --- cli/powerd-cli.c 2013-08-02 12:48:24 +0000 | |||
15 | +++ cli/powerd-cli.c 2013-08-12 14:34:58 +0000 | |||
16 | @@ -22,6 +22,7 @@ | |||
17 | 22 | #include <stdio.h> | 22 | #include <stdio.h> |
18 | 23 | #include <string.h> | 23 | #include <string.h> |
19 | 24 | #include <unistd.h> | 24 | #include <unistd.h> |
20 | 25 | #include <inttypes.h> | ||
21 | 25 | #include <sys/types.h> | 26 | #include <sys/types.h> |
22 | 26 | #include <glib-object.h> | 27 | #include <glib-object.h> |
23 | 27 | #include <gio/gio.h> | 28 | #include <gio/gio.h> |
24 | @@ -57,6 +58,28 @@ | |||
25 | 57 | guint32 flags; | 58 | guint32 flags; |
26 | 58 | }; | 59 | }; |
27 | 59 | 60 | ||
28 | 61 | struct SysRequestStats { | ||
29 | 62 | const char *owner; | ||
30 | 63 | const char *name; | ||
31 | 64 | unsigned active_count; | ||
32 | 65 | guint64 active_time; | ||
33 | 66 | guint64 max_active_time; | ||
34 | 67 | guint64 active_since; | ||
35 | 68 | }; | ||
36 | 69 | |||
37 | 70 | struct DispRequestStats { | ||
38 | 71 | const char *owner; | ||
39 | 72 | const char *name; | ||
40 | 73 | unsigned active_count; | ||
41 | 74 | guint64 active_time; | ||
42 | 75 | guint64 max_active_time; | ||
43 | 76 | guint64 active_since; | ||
44 | 77 | guint64 disp_on_time; | ||
45 | 78 | guint64 disp_on_since; | ||
46 | 79 | guint64 flag_on_time[POWERD_NUM_DISPLAY_FLAGS]; | ||
47 | 80 | guint64 flag_on_since[POWERD_NUM_DISPLAY_FLAGS]; | ||
48 | 81 | }; | ||
49 | 82 | |||
50 | 60 | static GMainLoop *main_loop = NULL; | 83 | static GMainLoop *main_loop = NULL; |
51 | 61 | static powerd_cookie_t main_cookie; | 84 | static powerd_cookie_t main_cookie; |
52 | 62 | static gboolean checkForDbusName(const char *dbusname, int count, | 85 | static gboolean checkForDbusName(const char *dbusname, int count, |
53 | @@ -307,6 +330,171 @@ | |||
54 | 307 | } | 330 | } |
55 | 308 | } | 331 | } |
56 | 309 | 332 | ||
57 | 333 | static GArray * | ||
58 | 334 | getSysRequestStats(void) | ||
59 | 335 | { | ||
60 | 336 | GVariant *ret, *item; | ||
61 | 337 | GVariantIter *iter; | ||
62 | 338 | GArray *retarray; | ||
63 | 339 | GError *error; | ||
64 | 340 | |||
65 | 341 | retarray = g_array_new(FALSE, FALSE, sizeof(struct SysRequestStats)); | ||
66 | 342 | |||
67 | 343 | error = NULL; | ||
68 | 344 | ret = g_dbus_proxy_call_sync(powerd_proxy, | ||
69 | 345 | "getSysRequestStats", | ||
70 | 346 | NULL, | ||
71 | 347 | G_DBUS_CALL_FLAGS_NONE, | ||
72 | 348 | -1, | ||
73 | 349 | NULL, | ||
74 | 350 | &error); | ||
75 | 351 | if (ret == NULL) { | ||
76 | 352 | cli_warn("getSysRequestStats failed: %s", error->message); | ||
77 | 353 | g_error_free(error); | ||
78 | 354 | } else { | ||
79 | 355 | g_variant_get(ret, "(a(ssuttt))", &iter); | ||
80 | 356 | while ((item = g_variant_iter_next_value (iter))) { | ||
81 | 357 | struct SysRequestStats stats; | ||
82 | 358 | g_variant_get_child(item, 0, "s", &stats.owner); | ||
83 | 359 | g_variant_get_child(item, 1, "s", &stats.name); | ||
84 | 360 | g_variant_get_child(item, 2, "u", &stats.active_count); | ||
85 | 361 | g_variant_get_child(item, 3, "t", &stats.active_time); | ||
86 | 362 | g_variant_get_child(item, 4, "t", &stats.max_active_time); | ||
87 | 363 | g_variant_get_child(item, 5, "t", &stats.active_since); | ||
88 | 364 | g_array_append_val(retarray, stats); | ||
89 | 365 | g_variant_unref(item); | ||
90 | 366 | } | ||
91 | 367 | g_variant_unref(ret); | ||
92 | 368 | } | ||
93 | 369 | return retarray; | ||
94 | 370 | } | ||
95 | 371 | |||
96 | 372 | static void | ||
97 | 373 | printSysRequestStats(GArray *stats) | ||
98 | 374 | { | ||
99 | 375 | int i; | ||
100 | 376 | struct SysRequestStats *stat; | ||
101 | 377 | printf("System Request Statistics:\n"); | ||
102 | 378 | if (stats->len == 0) { | ||
103 | 379 | printf(" None\n"); | ||
104 | 380 | } else { | ||
105 | 381 | printf(" %-16.16s %-20.20s %-8.8s %-16.16s %-16.16s %-16.16s\n", | ||
106 | 382 | "", "", "Active", "", "Max Active", ""); | ||
107 | 383 | printf(" %-16.16s %-20.20s %-8.8s %-16.16s %-16.16s %-16.16s\n", | ||
108 | 384 | "Owner", "Name", "Count", "Active Time", "Time", "Active Since"); | ||
109 | 385 | for (i = 0; i < stats->len; i++) { | ||
110 | 386 | stat = &g_array_index(stats, struct SysRequestStats, i); | ||
111 | 387 | printf(" %-16.16s %-20.20s %-8u %-16.6f %-16.6f %-16.6f\n", | ||
112 | 388 | stat->owner, stat->name, stat->active_count, | ||
113 | 389 | (double)stat->active_time / 1000000.0f, | ||
114 | 390 | (double)stat->max_active_time / 1000000.0f, | ||
115 | 391 | (double)stat->active_since / 1000000.0f); | ||
116 | 392 | } | ||
117 | 393 | } | ||
118 | 394 | } | ||
119 | 395 | |||
120 | 396 | static GArray * | ||
121 | 397 | getDispRequestStats(void) | ||
122 | 398 | { | ||
123 | 399 | GVariant *ret, *item; | ||
124 | 400 | GVariantIter *iter; | ||
125 | 401 | GArray *retarray; | ||
126 | 402 | GError *error; | ||
127 | 403 | |||
128 | 404 | retarray = g_array_new(FALSE, FALSE, sizeof(struct DispRequestStats)); | ||
129 | 405 | |||
130 | 406 | error = NULL; | ||
131 | 407 | ret = g_dbus_proxy_call_sync(powerd_proxy, | ||
132 | 408 | "getDispRequestStats", | ||
133 | 409 | NULL, | ||
134 | 410 | G_DBUS_CALL_FLAGS_NONE, | ||
135 | 411 | -1, | ||
136 | 412 | NULL, | ||
137 | 413 | &error); | ||
138 | 414 | if (ret == NULL) { | ||
139 | 415 | cli_warn("getDispRequestStats failed: %s", error->message); | ||
140 | 416 | g_error_free(error); | ||
141 | 417 | } else { | ||
142 | 418 | g_variant_get(ret, "(a(ssutttttatat))", &iter); | ||
143 | 419 | while ((item = g_variant_iter_next_value (iter))) { | ||
144 | 420 | struct DispRequestStats stats; | ||
145 | 421 | GVariantIter *array_iter; | ||
146 | 422 | guint64 val; | ||
147 | 423 | int i; | ||
148 | 424 | |||
149 | 425 | g_variant_get_child(item, 0, "s", &stats.owner); | ||
150 | 426 | g_variant_get_child(item, 1, "s", &stats.name); | ||
151 | 427 | g_variant_get_child(item, 2, "u", &stats.active_count); | ||
152 | 428 | g_variant_get_child(item, 3, "t", &stats.active_time); | ||
153 | 429 | g_variant_get_child(item, 4, "t", &stats.max_active_time); | ||
154 | 430 | g_variant_get_child(item, 5, "t", &stats.active_since); | ||
155 | 431 | g_variant_get_child(item, 6, "t", &stats.disp_on_time); | ||
156 | 432 | g_variant_get_child(item, 7, "t", &stats.disp_on_since); | ||
157 | 433 | |||
158 | 434 | g_variant_get_child(item, 8, "at", &array_iter); | ||
159 | 435 | i = 0; | ||
160 | 436 | while (g_variant_iter_loop(array_iter, "t", &val)) { | ||
161 | 437 | if (i >= POWERD_NUM_DISPLAY_FLAGS) | ||
162 | 438 | break; | ||
163 | 439 | stats.flag_on_time[i++] = val; | ||
164 | 440 | } | ||
165 | 441 | g_variant_iter_free(array_iter); | ||
166 | 442 | |||
167 | 443 | g_variant_get_child(item, 9, "at", &array_iter); | ||
168 | 444 | i = 0; | ||
169 | 445 | while (g_variant_iter_loop(array_iter, "t", &val)) { | ||
170 | 446 | if (i >= POWERD_NUM_DISPLAY_FLAGS) | ||
171 | 447 | break; | ||
172 | 448 | stats.flag_on_since[i++] = val; | ||
173 | 449 | } | ||
174 | 450 | g_variant_iter_free(array_iter); | ||
175 | 451 | |||
176 | 452 | g_array_append_val(retarray, stats); | ||
177 | 453 | g_variant_unref(item); | ||
178 | 454 | } | ||
179 | 455 | g_variant_unref(ret); | ||
180 | 456 | } | ||
181 | 457 | return retarray; | ||
182 | 458 | } | ||
183 | 459 | |||
184 | 460 | static void | ||
185 | 461 | printDispRequestStats(GArray *stats) | ||
186 | 462 | { | ||
187 | 463 | int i, j; | ||
188 | 464 | struct DispRequestStats *stat; | ||
189 | 465 | printf("Display Request Statistics:\n"); | ||
190 | 466 | if (stats->len == 0) { | ||
191 | 467 | printf(" None\n"); | ||
192 | 468 | } else { | ||
193 | 469 | printf(" %-16.16s %-20.20s %-8.8s %-16.16s %-16.16s %-16.16s %-16.16s %-16.16s", | ||
194 | 470 | "", "", "Active", "", "Max Active", "", "Display On", | ||
195 | 471 | "Display On"); | ||
196 | 472 | for (i = 0; i < POWERD_NUM_DISPLAY_FLAGS; i++) | ||
197 | 473 | printf(" Flag %-2d Flag %-2d ", i, i); | ||
198 | 474 | printf("\n %-16.16s %-20.20s %-8.8s %-16.16s %-16.16s %-16.16s %-16.16s %-16.16s", | ||
199 | 475 | "Owner", "Name", "Count", "Active Time", "Time", "Active Since", | ||
200 | 476 | "Time", "Since"); | ||
201 | 477 | for (i = 0; i < POWERD_NUM_DISPLAY_FLAGS; i++) | ||
202 | 478 | printf(" On Time On Since "); | ||
203 | 479 | printf("\n"); | ||
204 | 480 | for (i = 0; i < stats->len; i++) { | ||
205 | 481 | stat = &g_array_index(stats, struct DispRequestStats, i); | ||
206 | 482 | printf(" %-16.16s %-20.20s %-8u %-16.6f %-16.6f %-16.6f %-16.6f %-16.6f", | ||
207 | 483 | stat->owner, stat->name, stat->active_count, | ||
208 | 484 | (double)stat->active_time / 1000000.0f, | ||
209 | 485 | (double)stat->max_active_time / 1000000.0f, | ||
210 | 486 | (double)stat->active_since / 1000000.0f, | ||
211 | 487 | (double)stat->disp_on_time / 1000000.0f, | ||
212 | 488 | (double)stat->disp_on_since / 1000000.0f); | ||
213 | 489 | for (j = 0; j < POWERD_NUM_DISPLAY_FLAGS; j++) { | ||
214 | 490 | printf(" %-16.6f", (double)stat->flag_on_time[j] / 1000000.0f); | ||
215 | 491 | printf(" %-16.6f", (double)stat->flag_on_since[j] / 1000000.0f); | ||
216 | 492 | } | ||
217 | 493 | printf("\n"); | ||
218 | 494 | } | ||
219 | 495 | } | ||
220 | 496 | } | ||
221 | 497 | |||
222 | 310 | gboolean | 498 | gboolean |
223 | 311 | clearSysState(powerd_cookie_t cookie) | 499 | clearSysState(powerd_cookie_t cookie) |
224 | 312 | { | 500 | { |
225 | @@ -601,7 +789,7 @@ | |||
226 | 601 | do_test(updateDisplayState(pdr, cookie) == TRUE); | 789 | do_test(updateDisplayState(pdr, cookie) == TRUE); |
227 | 602 | 790 | ||
228 | 603 | pdr.state = -1; | 791 | pdr.state = -1; |
230 | 604 | do_test(updateDisplayState(pdr, cookie) == TRUE); | 792 | do_test(updateDisplayState(pdr, cookie) == FALSE); |
231 | 605 | 793 | ||
232 | 606 | do_test(clearDisplayState(cookie) == TRUE); | 794 | do_test(clearDisplayState(cookie) == TRUE); |
233 | 607 | 795 | ||
234 | @@ -730,6 +918,7 @@ | |||
235 | 730 | printf("list - list outstanding requests\n"); | 918 | printf("list - list outstanding requests\n"); |
236 | 731 | printf("listen - listen for signals from powerd. This runs a\n"\ | 919 | printf("listen - listen for signals from powerd. This runs a\n"\ |
237 | 732 | "\tgmainloop and must be manually killed.\n"); | 920 | "\tgmainloop and must be manually killed.\n"); |
238 | 921 | printf("stats - print request statistics\n"); | ||
239 | 733 | printf("test - runs tests\n"); | 922 | printf("test - runs tests\n"); |
240 | 734 | } | 923 | } |
241 | 735 | 924 | ||
242 | @@ -756,6 +945,7 @@ | |||
243 | 756 | } | 945 | } |
244 | 757 | 946 | ||
245 | 758 | if ((strcmp(argv[1],"list")) && | 947 | if ((strcmp(argv[1],"list")) && |
246 | 948 | (strcmp(argv[1],"stats")) && | ||
247 | 759 | (strcmp(argv[1],"active")) && | 949 | (strcmp(argv[1],"active")) && |
248 | 760 | (strcmp(argv[1],"active-nc")) && | 950 | (strcmp(argv[1],"active-nc")) && |
249 | 761 | (strcmp(argv[1],"test")) && | 951 | (strcmp(argv[1],"test")) && |
250 | @@ -807,6 +997,15 @@ | |||
251 | 807 | printDisplayRequests(requests); | 997 | printDisplayRequests(requests); |
252 | 808 | g_array_free(requests, TRUE); | 998 | g_array_free(requests, TRUE); |
253 | 809 | } | 999 | } |
254 | 1000 | else if (!strcmp(argv[1], "stats")) { | ||
255 | 1001 | requests = getSysRequestStats(); | ||
256 | 1002 | printSysRequestStats(requests); | ||
257 | 1003 | g_array_free(requests, TRUE); | ||
258 | 1004 | |||
259 | 1005 | requests = getDispRequestStats(); | ||
260 | 1006 | printDispRequestStats(requests); | ||
261 | 1007 | g_array_free(requests, TRUE); | ||
262 | 1008 | } | ||
263 | 810 | else if (!strcmp(argv[1],"active-nc")) { | 1009 | else if (!strcmp(argv[1],"active-nc")) { |
264 | 811 | requestSysState("active-nc", POWERD_SYS_STATE_ACTIVE,&cookie); | 1010 | requestSysState("active-nc", POWERD_SYS_STATE_ACTIVE,&cookie); |
265 | 812 | printf("Power State requested, cookie is %s\n", cookie); | 1011 | printf("Power State requested, cookie is %s\n", cookie); |
266 | 813 | 1012 | ||
267 | === modified file 'data/com.canonical.powerd.xml' | |||
268 | --- data/com.canonical.powerd.xml 2013-07-29 16:05:34 +0000 | |||
269 | +++ data/com.canonical.powerd.xml 2013-08-12 14:34:58 +0000 | |||
270 | @@ -52,6 +52,14 @@ | |||
271 | 52 | <arg type="a(ssiu)" name="requestList" direction="out" /> | 52 | <arg type="a(ssiu)" name="requestList" direction="out" /> |
272 | 53 | </method> | 53 | </method> |
273 | 54 | 54 | ||
274 | 55 | <method name="getSysRequestStats"> | ||
275 | 56 | <arg type="a(ssuttt)" name="requestStats" direction="out" /> | ||
276 | 57 | </method> | ||
277 | 58 | |||
278 | 59 | <method name="getDispRequestStats"> | ||
279 | 60 | <arg type="a(ssutttttatat)" name="requestStats" direction="out" /> | ||
280 | 61 | </method> | ||
281 | 62 | |||
282 | 55 | <!-- Signals --> | 63 | <!-- Signals --> |
283 | 56 | <signal name="SysPowerStateChange"> | 64 | <signal name="SysPowerStateChange"> |
284 | 57 | <arg type="i" name="sysState" direction="out" /> | 65 | <arg type="i" name="sysState" direction="out" /> |
285 | 58 | 66 | ||
286 | === modified file 'src/display-request.c' | |||
287 | --- src/display-request.c 2013-07-29 16:05:34 +0000 | |||
288 | +++ src/display-request.c 2013-08-12 14:34:58 +0000 | |||
289 | @@ -116,6 +116,8 @@ | |||
290 | 116 | powerd_dbus_name_watch_add(request->owner); | 116 | powerd_dbus_name_watch_add(request->owner); |
291 | 117 | __add_request(&request->req); | 117 | __add_request(&request->req); |
292 | 118 | update_internal_state(); | 118 | update_internal_state(); |
293 | 119 | powerd_account_add_display_req(request->owner, request->name, | ||
294 | 120 | &request->req); | ||
295 | 119 | } | 121 | } |
296 | 120 | 122 | ||
297 | 121 | static gboolean update_request(struct powerd_display_request *new_req) | 123 | static gboolean update_request(struct powerd_display_request *new_req) |
298 | @@ -135,6 +137,7 @@ | |||
299 | 135 | ireq->req.flags = new_req->flags; | 137 | ireq->req.flags = new_req->flags; |
300 | 136 | 138 | ||
301 | 137 | update_internal_state(); | 139 | update_internal_state(); |
302 | 140 | powerd_account_update_display_req(ireq->owner, ireq->name, &ireq->req); | ||
303 | 138 | return TRUE; | 141 | return TRUE; |
304 | 139 | } | 142 | } |
305 | 140 | 143 | ||
306 | @@ -154,11 +157,12 @@ | |||
307 | 154 | ireq = g_hash_table_lookup(display_request_hash, cookie); | 157 | ireq = g_hash_table_lookup(display_request_hash, cookie); |
308 | 155 | if (ireq) { | 158 | if (ireq) { |
309 | 156 | req = ireq->req; | 159 | req = ireq->req; |
313 | 157 | /* We need to remove it from our watch hash before we remove it | 160 | /* We need to remove it from our watch hash and do accounting |
314 | 158 | * from the state hash or the ireq->owner memory will be freed | 161 | * before we remove it from the state hash or the ireq->owner |
315 | 159 | * before we try to use it. | 162 | * memory will be freed before we try to use it. |
316 | 160 | */ | 163 | */ |
317 | 161 | powerd_dbus_name_watch_remove(ireq->owner); | 164 | powerd_dbus_name_watch_remove(ireq->owner); |
318 | 165 | powerd_account_clear_display_req(ireq->owner, ireq->name); | ||
319 | 162 | found = g_hash_table_remove(display_request_hash, cookie); | 166 | found = g_hash_table_remove(display_request_hash, cookie); |
320 | 163 | if (!found) | 167 | if (!found) |
321 | 164 | powerd_warn("Display request found on lookup but not on remove"); | 168 | powerd_warn("Display request found on lookup but not on remove"); |
322 | @@ -172,25 +176,11 @@ | |||
323 | 172 | return found; | 176 | return found; |
324 | 173 | } | 177 | } |
325 | 174 | 178 | ||
342 | 175 | static int add_request_worker(gpointer data) | 179 | static gboolean request_valid(struct powerd_display_request *request) |
343 | 176 | { | 180 | { |
328 | 177 | struct display_request_internal *req = data; | ||
329 | 178 | add_request(req); | ||
330 | 179 | return 0; | ||
331 | 180 | } | ||
332 | 181 | |||
333 | 182 | /* | ||
334 | 183 | * @request need not refer to persistent memory, as the data from | ||
335 | 184 | * the struct will be copied into internally-managed storage. | ||
336 | 185 | */ | ||
337 | 186 | static int __powerd_add_display_request(struct powerd_display_request *request, | ||
338 | 187 | const char *name, const char *owner) | ||
339 | 188 | { | ||
340 | 189 | struct display_request_internal *hash_req; | ||
341 | 190 | |||
344 | 191 | if ((unsigned)request->state >= POWERD_NUM_DISPLAY_STATES) { | 181 | if ((unsigned)request->state >= POWERD_NUM_DISPLAY_STATES) { |
345 | 192 | powerd_warn("Invalid display state requested: %d", request->state); | 182 | powerd_warn("Invalid display state requested: %d", request->state); |
347 | 193 | return -EINVAL; | 183 | return FALSE; |
348 | 194 | } | 184 | } |
349 | 195 | 185 | ||
350 | 196 | /* | 186 | /* |
351 | @@ -199,8 +189,30 @@ | |||
352 | 199 | */ | 189 | */ |
353 | 200 | if (request->flags & (-1U << POWERD_NUM_DISPLAY_FLAGS)) { | 190 | if (request->flags & (-1U << POWERD_NUM_DISPLAY_FLAGS)) { |
354 | 201 | powerd_warn("Invalid display flags requested: 0x%08x", request->flags); | 191 | powerd_warn("Invalid display flags requested: 0x%08x", request->flags); |
355 | 192 | return FALSE; | ||
356 | 193 | } | ||
357 | 194 | |||
358 | 195 | return TRUE; | ||
359 | 196 | } | ||
360 | 197 | |||
361 | 198 | static int add_request_worker(gpointer data) | ||
362 | 199 | { | ||
363 | 200 | struct display_request_internal *req = data; | ||
364 | 201 | add_request(req); | ||
365 | 202 | return 0; | ||
366 | 203 | } | ||
367 | 204 | |||
368 | 205 | /* | ||
369 | 206 | * @request need not refer to persistent memory, as the data from | ||
370 | 207 | * the struct will be copied into internally-managed storage. | ||
371 | 208 | */ | ||
372 | 209 | static int __powerd_add_display_request(struct powerd_display_request *request, | ||
373 | 210 | const char *name, const char *owner) | ||
374 | 211 | { | ||
375 | 212 | struct display_request_internal *hash_req; | ||
376 | 213 | |||
377 | 214 | if (!request_valid(request)) | ||
378 | 202 | return -EINVAL; | 215 | return -EINVAL; |
379 | 203 | } | ||
380 | 204 | 216 | ||
381 | 205 | uuid_generate(request->cookie); | 217 | uuid_generate(request->cookie); |
382 | 206 | hash_req = g_new(struct display_request_internal, 1); | 218 | hash_req = g_new(struct display_request_internal, 1); |
383 | @@ -235,6 +247,9 @@ | |||
384 | 235 | { | 247 | { |
385 | 236 | gboolean found; | 248 | gboolean found; |
386 | 237 | 249 | ||
387 | 250 | if (!request_valid(request)) | ||
388 | 251 | return -EINVAL; | ||
389 | 252 | |||
390 | 238 | found = powerd_run_mainloop_sync(update_request_worker, request); | 253 | found = powerd_run_mainloop_sync(update_request_worker, request); |
391 | 239 | return found ? 0 : -EINVAL; | 254 | return found ? 0 : -EINVAL; |
392 | 240 | } | 255 | } |
393 | @@ -434,6 +449,7 @@ | |||
394 | 434 | while (g_hash_table_iter_next(&iter, &key, &value)) { | 449 | while (g_hash_table_iter_next(&iter, &key, &value)) { |
395 | 435 | struct display_request_internal *ireq = value; | 450 | struct display_request_internal *ireq = value; |
396 | 436 | if (!strcmp(owner, ireq->owner)) { | 451 | if (!strcmp(owner, ireq->owner)) { |
397 | 452 | powerd_account_clear_display_req(ireq->owner, ireq->name); | ||
398 | 437 | __remove_request(&ireq->req); | 453 | __remove_request(&ireq->req); |
399 | 438 | powerd_dbus_name_watch_remove(ireq->owner); | 454 | powerd_dbus_name_watch_remove(ireq->owner); |
400 | 439 | g_hash_table_iter_remove(&iter); | 455 | g_hash_table_iter_remove(&iter); |
401 | 440 | 456 | ||
402 | === modified file 'src/power-request.c' | |||
403 | --- src/power-request.c 2013-08-05 08:47:30 +0000 | |||
404 | +++ src/power-request.c 2013-08-12 14:34:58 +0000 | |||
405 | @@ -210,6 +210,7 @@ | |||
406 | 210 | g_hash_table_insert(state_request_hash, sr->cookie, sr); | 210 | g_hash_table_insert(state_request_hash, sr->cookie, sr); |
407 | 211 | state_request_count[sr->state - 1] += 1; | 211 | state_request_count[sr->state - 1] += 1; |
408 | 212 | powerd_dbus_name_watch_add(sr->owner); | 212 | powerd_dbus_name_watch_add(sr->owner); |
409 | 213 | powerd_account_request_sys_state(sr->owner, sr->name); | ||
410 | 213 | return 0; | 214 | return 0; |
411 | 214 | } | 215 | } |
412 | 215 | 216 | ||
413 | @@ -278,6 +279,7 @@ | |||
414 | 278 | { | 279 | { |
415 | 279 | powerd_dbus_name_watch_remove(req->owner); | 280 | powerd_dbus_name_watch_remove(req->owner); |
416 | 280 | state_request_count[req->state - 1] -= 1; | 281 | state_request_count[req->state - 1] -= 1; |
417 | 282 | powerd_account_clear_sys_state(req->owner, req->name); | ||
418 | 281 | } | 283 | } |
419 | 282 | 284 | ||
420 | 283 | /* Must only be called from main loop */ | 285 | /* Must only be called from main loop */ |
421 | 284 | 286 | ||
422 | === modified file 'src/powerd-internal.h' | |||
423 | --- src/powerd-internal.h 2013-07-29 16:05:34 +0000 | |||
424 | +++ src/powerd-internal.h 2013-08-12 14:34:58 +0000 | |||
425 | @@ -161,6 +161,22 @@ | |||
426 | 161 | int powerd_client_init(void); | 161 | int powerd_client_init(void); |
427 | 162 | void powerd_client_deinit(void); | 162 | void powerd_client_deinit(void); |
428 | 163 | 163 | ||
429 | 164 | /* Statistics functions */ | ||
430 | 165 | void powerd_account_request_sys_state(const char *dbus_name, const char *name); | ||
431 | 166 | void powerd_account_clear_sys_state(const char *dbus_name, const char *name); | ||
432 | 167 | void powerd_account_add_display_req(const char *dbus_name, const char *name, | ||
433 | 168 | const struct powerd_display_request *req); | ||
434 | 169 | void powerd_account_update_display_req(const char *dbus_name, | ||
435 | 170 | const char *name, | ||
436 | 171 | const struct powerd_display_request *req); | ||
437 | 172 | void powerd_account_clear_display_req(const char *dbus_name, const char *name); | ||
438 | 173 | int powerd_stats_init(void); | ||
439 | 174 | void powerd_stats_deinit(void); | ||
440 | 175 | gboolean handle_get_sys_request_stats(PowerdSource *obj, | ||
441 | 176 | GDBusMethodInvocation *invocation); | ||
442 | 177 | gboolean handle_get_disp_request_stats(PowerdSource *obj, | ||
443 | 178 | GDBusMethodInvocation *invocation); | ||
444 | 179 | |||
445 | 164 | /* Utility functions */ | 180 | /* Utility functions */ |
446 | 165 | int powerd_run_mainloop_sync(int (*func)(gpointer), gpointer data); | 181 | int powerd_run_mainloop_sync(int (*func)(gpointer), gpointer data); |
447 | 166 | guint powerd_uuid_hash(gconstpointer key); | 182 | guint powerd_uuid_hash(gconstpointer key); |
448 | 167 | 183 | ||
449 | === modified file 'src/powerd-object.c' | |||
450 | --- src/powerd-object.c 2013-07-24 14:39:08 +0000 | |||
451 | +++ src/powerd-object.c 2013-08-12 14:34:58 +0000 | |||
452 | @@ -177,6 +177,10 @@ | |||
453 | 177 | G_CALLBACK(handle_ack_state_change), powerd_source); | 177 | G_CALLBACK(handle_ack_state_change), powerd_source); |
454 | 178 | g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-list-display-requests", | 178 | g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-list-display-requests", |
455 | 179 | G_CALLBACK(handle_list_display_requests), powerd_source); | 179 | G_CALLBACK(handle_list_display_requests), powerd_source); |
456 | 180 | g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-get-sys-request-stats", | ||
457 | 181 | G_CALLBACK(handle_get_sys_request_stats), powerd_source); | ||
458 | 182 | g_signal_connect(G_OBJECT(powerd_source->priv->skel), "handle-get-disp-request-stats", | ||
459 | 183 | G_CALLBACK(handle_get_disp_request_stats), powerd_source); | ||
460 | 180 | 184 | ||
461 | 181 | powerd_dbus_init_complete(); | 185 | powerd_dbus_init_complete(); |
462 | 182 | } | 186 | } |
463 | 183 | 187 | ||
464 | === modified file 'src/powerd.cpp' | |||
465 | --- src/powerd.cpp 2013-07-29 16:05:34 +0000 | |||
466 | +++ src/powerd.cpp 2013-08-12 14:34:58 +0000 | |||
467 | @@ -472,6 +472,7 @@ | |||
468 | 472 | powerd_debug("Auto-dim Timeout is %d seconds\n", dim_timeout); | 472 | powerd_debug("Auto-dim Timeout is %d seconds\n", dim_timeout); |
469 | 473 | 473 | ||
470 | 474 | libsuspend_init(0); | 474 | libsuspend_init(0); |
471 | 475 | powerd_stats_init(); | ||
472 | 475 | powerd_client_init(); | 476 | powerd_client_init(); |
473 | 476 | power_request_init(); | 477 | power_request_init(); |
474 | 477 | display_request_init(); | 478 | display_request_init(); |
475 | @@ -512,5 +513,6 @@ | |||
476 | 512 | display_request_deinit(); | 513 | display_request_deinit(); |
477 | 513 | power_request_deinit(); | 514 | power_request_deinit(); |
478 | 514 | powerd_client_deinit(); | 515 | powerd_client_deinit(); |
479 | 516 | powerd_stats_deinit(); | ||
480 | 515 | return g_exit_code; | 517 | return g_exit_code; |
481 | 516 | } | 518 | } |
482 | 517 | 519 | ||
483 | === added file 'src/stats.c' | |||
484 | --- src/stats.c 1970-01-01 00:00:00 +0000 | |||
485 | +++ src/stats.c 2013-08-12 14:34:58 +0000 | |||
486 | @@ -0,0 +1,508 @@ | |||
487 | 1 | /* | ||
488 | 2 | * Copyright 2013 Canonical Ltd. | ||
489 | 3 | * | ||
490 | 4 | * This file is part of powerd. | ||
491 | 5 | * | ||
492 | 6 | * powerd is free software; you can redistribute it and/or modify | ||
493 | 7 | * it under the terms of the GNU General Public License as published by | ||
494 | 8 | * the Free Software Foundation; version 3. | ||
495 | 9 | * | ||
496 | 10 | * powerd is distributed in the hope that it will be useful, | ||
497 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
498 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
499 | 13 | * GNU General Public License for more details. | ||
500 | 14 | * | ||
501 | 15 | * You should have received a copy of the GNU General Public License | ||
502 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
503 | 17 | */ | ||
504 | 18 | |||
505 | 19 | #include <stdlib.h> | ||
506 | 20 | #include <errno.h> | ||
507 | 21 | #include <string.h> | ||
508 | 22 | #include <time.h> | ||
509 | 23 | |||
510 | 24 | #include <glib.h> | ||
511 | 25 | #include <gio/gio.h> | ||
512 | 26 | |||
513 | 27 | #include "powerd-internal.h" | ||
514 | 28 | #include "powerd-dbus.h" | ||
515 | 29 | #include "log.h" | ||
516 | 30 | |||
517 | 31 | #define USECS_PER_SEC 1000000 | ||
518 | 32 | #define NSECS_PER_USEC 1000 | ||
519 | 33 | |||
520 | 34 | struct client_stats { | ||
521 | 35 | const char *dbus_name; | ||
522 | 36 | GSList *sys_stats; | ||
523 | 37 | GSList *disp_stats; | ||
524 | 38 | }; | ||
525 | 39 | |||
526 | 40 | struct sys_request_stats { | ||
527 | 41 | const char *name; | ||
528 | 42 | unsigned active_count; | ||
529 | 43 | guint64 active_time; | ||
530 | 44 | guint64 max_active_time; | ||
531 | 45 | guint64 active_since; | ||
532 | 46 | }; | ||
533 | 47 | |||
534 | 48 | struct disp_request_stats { | ||
535 | 49 | const char *name; | ||
536 | 50 | unsigned active_count; | ||
537 | 51 | guint64 active_time; | ||
538 | 52 | guint64 max_active_time; | ||
539 | 53 | guint64 active_since; | ||
540 | 54 | guint64 disp_on_time; | ||
541 | 55 | guint64 disp_on_since; | ||
542 | 56 | guint64 flag_on_time[POWERD_NUM_DISPLAY_FLAGS]; | ||
543 | 57 | guint64 flag_on_since[POWERD_NUM_DISPLAY_FLAGS]; | ||
544 | 58 | struct powerd_display_request last_req; | ||
545 | 59 | }; | ||
546 | 60 | |||
547 | 61 | GHashTable *stats_hash; | ||
548 | 62 | |||
549 | 63 | static guint64 get_usecs(void) | ||
550 | 64 | { | ||
551 | 65 | struct timespec ts; | ||
552 | 66 | |||
553 | 67 | if (clock_gettime(CLOCK_MONOTONIC, &ts)) { | ||
554 | 68 | powerd_error("Could not get monotonic time: %s", strerror(errno)); | ||
555 | 69 | return 0; | ||
556 | 70 | } | ||
557 | 71 | return (guint64)ts.tv_sec * USECS_PER_SEC + | ||
558 | 72 | (ts.tv_nsec + NSECS_PER_USEC / 2) / NSECS_PER_USEC; | ||
559 | 73 | } | ||
560 | 74 | |||
561 | 75 | static struct client_stats *alloc_client(const char *dbus_name) | ||
562 | 76 | { | ||
563 | 77 | struct client_stats *client = calloc(1, sizeof(*client)); | ||
564 | 78 | if (!client) { | ||
565 | 79 | powerd_error("Error allocating client for statistics"); | ||
566 | 80 | return NULL; | ||
567 | 81 | } | ||
568 | 82 | |||
569 | 83 | client->dbus_name = strdup(dbus_name); | ||
570 | 84 | if (!client->dbus_name) { | ||
571 | 85 | powerd_error("Error duplicating client dbus name for statistics"); | ||
572 | 86 | free(client); | ||
573 | 87 | return NULL; | ||
574 | 88 | } | ||
575 | 89 | |||
576 | 90 | return client; | ||
577 | 91 | } | ||
578 | 92 | |||
579 | 93 | static struct sys_request_stats *alloc_sys_stats(const char *name) | ||
580 | 94 | { | ||
581 | 95 | struct sys_request_stats *stats = calloc(1, sizeof(*stats)); | ||
582 | 96 | if (!stats) { | ||
583 | 97 | powerd_error("Error allocating memory for system request statistics"); | ||
584 | 98 | return NULL; | ||
585 | 99 | } | ||
586 | 100 | |||
587 | 101 | stats->name = strdup(name); | ||
588 | 102 | if (!stats->name) { | ||
589 | 103 | powerd_error("Error duplicating request name for statistics"); | ||
590 | 104 | free(stats); | ||
591 | 105 | return NULL; | ||
592 | 106 | } | ||
593 | 107 | |||
594 | 108 | return stats; | ||
595 | 109 | } | ||
596 | 110 | |||
597 | 111 | static struct disp_request_stats *alloc_disp_stats(const char *name) | ||
598 | 112 | { | ||
599 | 113 | struct disp_request_stats *stats = calloc(1, sizeof(*stats)); | ||
600 | 114 | if (!stats) { | ||
601 | 115 | powerd_error("Error allocating memory for display request statistics"); | ||
602 | 116 | return NULL; | ||
603 | 117 | } | ||
604 | 118 | |||
605 | 119 | stats->name = strdup(name); | ||
606 | 120 | if (!stats->name) { | ||
607 | 121 | powerd_error("Error duplicating request name for statistics"); | ||
608 | 122 | free(stats); | ||
609 | 123 | return NULL; | ||
610 | 124 | } | ||
611 | 125 | |||
612 | 126 | return stats; | ||
613 | 127 | } | ||
614 | 128 | |||
615 | 129 | static gint sys_stats_comp(gconstpointer a, gconstpointer b) | ||
616 | 130 | { | ||
617 | 131 | const struct sys_request_stats *stats = a; | ||
618 | 132 | const char *name = b; | ||
619 | 133 | return strcmp(stats->name, name); | ||
620 | 134 | } | ||
621 | 135 | |||
622 | 136 | static gint disp_stats_comp(gconstpointer a, gconstpointer b) | ||
623 | 137 | { | ||
624 | 138 | const struct disp_request_stats *stats = a; | ||
625 | 139 | const char *name = b; | ||
626 | 140 | return strcmp(stats->name, name); | ||
627 | 141 | } | ||
628 | 142 | |||
629 | 143 | static struct client_stats *lookup_client(const char *dbus_name, | ||
630 | 144 | gboolean alloc) | ||
631 | 145 | { | ||
632 | 146 | struct client_stats *client; | ||
633 | 147 | |||
634 | 148 | if (!stats_hash) | ||
635 | 149 | return NULL; | ||
636 | 150 | |||
637 | 151 | client = g_hash_table_lookup(stats_hash, dbus_name); | ||
638 | 152 | if (!client && alloc) { | ||
639 | 153 | client = alloc_client(dbus_name); | ||
640 | 154 | if (client) | ||
641 | 155 | g_hash_table_insert(stats_hash, (gpointer)client->dbus_name, | ||
642 | 156 | client); | ||
643 | 157 | } | ||
644 | 158 | return client; | ||
645 | 159 | } | ||
646 | 160 | |||
647 | 161 | void powerd_account_request_sys_state(const char *dbus_name, const char *name) | ||
648 | 162 | { | ||
649 | 163 | struct client_stats *client; | ||
650 | 164 | struct sys_request_stats *stats; | ||
651 | 165 | GSList *item; | ||
652 | 166 | |||
653 | 167 | client = lookup_client(dbus_name, TRUE); | ||
654 | 168 | if (!client) | ||
655 | 169 | return; | ||
656 | 170 | |||
657 | 171 | item = g_slist_find_custom(client->sys_stats, name, sys_stats_comp); | ||
658 | 172 | if (item) { | ||
659 | 173 | stats = item->data; | ||
660 | 174 | } else { | ||
661 | 175 | stats = alloc_sys_stats(name); | ||
662 | 176 | if (!stats) | ||
663 | 177 | return; | ||
664 | 178 | client->sys_stats = g_slist_prepend(client->sys_stats, stats); | ||
665 | 179 | } | ||
666 | 180 | |||
667 | 181 | stats->active_count++; | ||
668 | 182 | stats->active_since = get_usecs(); | ||
669 | 183 | } | ||
670 | 184 | |||
671 | 185 | void powerd_account_clear_sys_state(const char *dbus_name, const char *name) | ||
672 | 186 | { | ||
673 | 187 | struct client_stats *client; | ||
674 | 188 | struct sys_request_stats *stats; | ||
675 | 189 | GSList *item; | ||
676 | 190 | guint64 duration; | ||
677 | 191 | |||
678 | 192 | if (!stats_hash) | ||
679 | 193 | return; | ||
680 | 194 | |||
681 | 195 | client = lookup_client(dbus_name, FALSE); | ||
682 | 196 | if (!client) | ||
683 | 197 | return; | ||
684 | 198 | item = g_slist_find_custom(client->sys_stats, name, sys_stats_comp); | ||
685 | 199 | if (!item) | ||
686 | 200 | return; | ||
687 | 201 | stats = item->data; | ||
688 | 202 | |||
689 | 203 | duration = get_usecs() - stats->active_since; | ||
690 | 204 | stats->active_since = 0; | ||
691 | 205 | stats->active_time += duration; | ||
692 | 206 | if (duration > stats->max_active_time) | ||
693 | 207 | stats->max_active_time = duration; | ||
694 | 208 | } | ||
695 | 209 | |||
696 | 210 | static void aggregate_disp_stats(struct disp_request_stats *stats, | ||
697 | 211 | const struct powerd_display_request *new) | ||
698 | 212 | { | ||
699 | 213 | guint64 us; | ||
700 | 214 | int i; | ||
701 | 215 | |||
702 | 216 | us = get_usecs(); | ||
703 | 217 | if (new->state != stats->last_req.state) { | ||
704 | 218 | if (new->state == POWERD_DISPLAY_STATE_ON) { | ||
705 | 219 | stats->disp_on_since = us; | ||
706 | 220 | } else { | ||
707 | 221 | stats->disp_on_time += us - stats->disp_on_since; | ||
708 | 222 | stats->disp_on_since = 0; | ||
709 | 223 | } | ||
710 | 224 | } | ||
711 | 225 | for (i = 0; i < POWERD_NUM_DISPLAY_FLAGS; i++) { | ||
712 | 226 | guint32 mask = 1 << i; | ||
713 | 227 | if ((new->flags & mask) != (stats->last_req.flags & mask)) { | ||
714 | 228 | if (new->flags & mask) { | ||
715 | 229 | stats->flag_on_since[i] = us; | ||
716 | 230 | } else { | ||
717 | 231 | stats->flag_on_time[i] += us - stats->flag_on_since[i]; | ||
718 | 232 | stats->flag_on_since[i] = 0; | ||
719 | 233 | } | ||
720 | 234 | } | ||
721 | 235 | } | ||
722 | 236 | } | ||
723 | 237 | |||
724 | 238 | void powerd_account_add_display_req(const char *dbus_name, const char *name, | ||
725 | 239 | const struct powerd_display_request *req) | ||
726 | 240 | { | ||
727 | 241 | struct client_stats *client; | ||
728 | 242 | struct disp_request_stats *stats; | ||
729 | 243 | GSList *item; | ||
730 | 244 | guint64 us; | ||
731 | 245 | int i; | ||
732 | 246 | |||
733 | 247 | if (!stats_hash) | ||
734 | 248 | return; | ||
735 | 249 | |||
736 | 250 | client = lookup_client(dbus_name, TRUE); | ||
737 | 251 | if (!client) | ||
738 | 252 | return; | ||
739 | 253 | |||
740 | 254 | item = g_slist_find_custom(client->disp_stats, name, disp_stats_comp); | ||
741 | 255 | if (item) { | ||
742 | 256 | stats = item->data; | ||
743 | 257 | } else { | ||
744 | 258 | stats = alloc_disp_stats(name); | ||
745 | 259 | if (!stats) | ||
746 | 260 | return; | ||
747 | 261 | client->disp_stats = g_slist_prepend(client->disp_stats, stats); | ||
748 | 262 | } | ||
749 | 263 | |||
750 | 264 | us = get_usecs(); | ||
751 | 265 | stats->active_count++; | ||
752 | 266 | stats->active_since = us; | ||
753 | 267 | if (req->state == POWERD_DISPLAY_STATE_ON) | ||
754 | 268 | stats->disp_on_since = us; | ||
755 | 269 | for (i = 0; i < POWERD_NUM_DISPLAY_FLAGS; i++) { | ||
756 | 270 | if (req->flags & (1 << i)) | ||
757 | 271 | stats->flag_on_since[i] = us; | ||
758 | 272 | } | ||
759 | 273 | stats->last_req = *req; | ||
760 | 274 | } | ||
761 | 275 | |||
762 | 276 | void powerd_account_update_display_req(const char *dbus_name, | ||
763 | 277 | const char *name, | ||
764 | 278 | const struct powerd_display_request *req) | ||
765 | 279 | { | ||
766 | 280 | struct client_stats *client; | ||
767 | 281 | struct disp_request_stats *stats; | ||
768 | 282 | GSList *item; | ||
769 | 283 | |||
770 | 284 | client = lookup_client(dbus_name, FALSE); | ||
771 | 285 | if (!client) | ||
772 | 286 | return; | ||
773 | 287 | |||
774 | 288 | item = g_slist_find_custom(client->disp_stats, name, disp_stats_comp); | ||
775 | 289 | if (!item) | ||
776 | 290 | return; | ||
777 | 291 | stats = item->data; | ||
778 | 292 | |||
779 | 293 | aggregate_disp_stats(stats, req); | ||
780 | 294 | stats->last_req = *req; | ||
781 | 295 | } | ||
782 | 296 | |||
783 | 297 | void powerd_account_clear_display_req(const char *dbus_name, const char *name) | ||
784 | 298 | { | ||
785 | 299 | struct client_stats *client; | ||
786 | 300 | struct disp_request_stats *stats; | ||
787 | 301 | GSList *item; | ||
788 | 302 | struct powerd_display_request req; | ||
789 | 303 | guint64 duration; | ||
790 | 304 | |||
791 | 305 | client = lookup_client(dbus_name, FALSE); | ||
792 | 306 | if (!client) | ||
793 | 307 | return; | ||
794 | 308 | |||
795 | 309 | item = g_slist_find_custom(client->disp_stats, name, disp_stats_comp); | ||
796 | 310 | if (!item) | ||
797 | 311 | return; | ||
798 | 312 | stats = item->data; | ||
799 | 313 | |||
800 | 314 | memset(&req, 0, sizeof(req)); | ||
801 | 315 | aggregate_disp_stats(stats, &req); | ||
802 | 316 | |||
803 | 317 | duration = get_usecs() - stats->active_since; | ||
804 | 318 | stats->active_time += duration; | ||
805 | 319 | stats->active_since = 0; | ||
806 | 320 | if (duration > stats->max_active_time) | ||
807 | 321 | stats->max_active_time = duration; | ||
808 | 322 | |||
809 | 323 | stats->last_req = req; | ||
810 | 324 | } | ||
811 | 325 | |||
812 | 326 | static void sys_stats_list_destroy(gpointer data) | ||
813 | 327 | { | ||
814 | 328 | struct sys_request_stats *stats = data; | ||
815 | 329 | free((void *)stats->name); | ||
816 | 330 | free(stats); | ||
817 | 331 | } | ||
818 | 332 | |||
819 | 333 | static void disp_stats_list_destroy(gpointer data) | ||
820 | 334 | { | ||
821 | 335 | struct disp_request_stats *stats = data; | ||
822 | 336 | free((void *)stats->name); | ||
823 | 337 | free(stats); | ||
824 | 338 | } | ||
825 | 339 | |||
826 | 340 | static void stats_hash_destroy(gpointer data) | ||
827 | 341 | { | ||
828 | 342 | struct client_stats *client = data; | ||
829 | 343 | g_slist_free_full(client->sys_stats, sys_stats_list_destroy); | ||
830 | 344 | g_slist_free_full(client->disp_stats, disp_stats_list_destroy); | ||
831 | 345 | free((void *)client->dbus_name); | ||
832 | 346 | free(client); | ||
833 | 347 | } | ||
834 | 348 | |||
835 | 349 | int powerd_stats_init(void) | ||
836 | 350 | { | ||
837 | 351 | stats_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, | ||
838 | 352 | stats_hash_destroy); | ||
839 | 353 | if (!stats_hash) { | ||
840 | 354 | powerd_warn("Unable to allocate stats hash table"); | ||
841 | 355 | return -ENOMEM; | ||
842 | 356 | } | ||
843 | 357 | return 0; | ||
844 | 358 | } | ||
845 | 359 | |||
846 | 360 | void powerd_stats_deinit(void) | ||
847 | 361 | { | ||
848 | 362 | if (stats_hash) | ||
849 | 363 | g_hash_table_destroy(stats_hash); | ||
850 | 364 | } | ||
851 | 365 | |||
852 | 366 | /* Dbus interface support */ | ||
853 | 367 | |||
854 | 368 | static int build_sys_request_list(GVariantBuilder *builder, | ||
855 | 369 | struct client_stats *client) | ||
856 | 370 | { | ||
857 | 371 | const char *dbus_name = client->dbus_name; | ||
858 | 372 | GSList *cur; | ||
859 | 373 | guint64 us; | ||
860 | 374 | int count = 0; | ||
861 | 375 | |||
862 | 376 | us = get_usecs(); | ||
863 | 377 | for (cur = client->sys_stats; cur; cur = g_slist_next(cur)) { | ||
864 | 378 | struct sys_request_stats *stats = cur->data; | ||
865 | 379 | guint64 active_time, max_active_time; | ||
866 | 380 | |||
867 | 381 | /* | ||
868 | 382 | * Aggregate currently held requests into active_time, and | ||
869 | 383 | * consider whether this is greater than the current | ||
870 | 384 | * max_active_time. | ||
871 | 385 | */ | ||
872 | 386 | active_time = stats->active_time; | ||
873 | 387 | max_active_time = stats->max_active_time; | ||
874 | 388 | if (stats->active_since != 0) { | ||
875 | 389 | guint64 duration = us - stats->active_since; | ||
876 | 390 | active_time += duration; | ||
877 | 391 | if (duration > max_active_time) | ||
878 | 392 | max_active_time = duration; | ||
879 | 393 | } | ||
880 | 394 | g_variant_builder_add(builder, "(ssuttt)", dbus_name, stats->name, | ||
881 | 395 | stats->active_count, active_time, | ||
882 | 396 | max_active_time, stats->active_since); | ||
883 | 397 | count++; | ||
884 | 398 | } | ||
885 | 399 | return count; | ||
886 | 400 | } | ||
887 | 401 | |||
888 | 402 | gboolean handle_get_sys_request_stats(PowerdSource *obj, | ||
889 | 403 | GDBusMethodInvocation *invocation) | ||
890 | 404 | { | ||
891 | 405 | GVariantBuilder *builder; | ||
892 | 406 | GVariant *list, *tuple; | ||
893 | 407 | GHashTableIter iter; | ||
894 | 408 | gpointer key, value; | ||
895 | 409 | int count = 0; | ||
896 | 410 | |||
897 | 411 | builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssuttt)")); | ||
898 | 412 | if (stats_hash) { | ||
899 | 413 | g_hash_table_iter_init(&iter, stats_hash); | ||
900 | 414 | while (g_hash_table_iter_next(&iter, &key, &value)) | ||
901 | 415 | count += build_sys_request_list(builder, value); | ||
902 | 416 | } | ||
903 | 417 | |||
904 | 418 | if (count == 0) { | ||
905 | 419 | g_variant_builder_clear(builder); | ||
906 | 420 | list = g_variant_new_array(G_VARIANT_TYPE("a(ssuttt)"), NULL, 0); | ||
907 | 421 | } else { | ||
908 | 422 | list = g_variant_builder_end(builder); | ||
909 | 423 | } | ||
910 | 424 | tuple = g_variant_new_tuple(&list, 1); | ||
911 | 425 | g_dbus_method_invocation_return_value(invocation, tuple); | ||
912 | 426 | g_variant_builder_unref(builder); | ||
913 | 427 | |||
914 | 428 | return TRUE; | ||
915 | 429 | } | ||
916 | 430 | |||
917 | 431 | static int build_disp_request_list(GVariantBuilder *builder, | ||
918 | 432 | struct client_stats *client) | ||
919 | 433 | { | ||
920 | 434 | const char *dbus_name = client->dbus_name; | ||
921 | 435 | GSList *cur; | ||
922 | 436 | guint64 us; | ||
923 | 437 | int count = 0; | ||
924 | 438 | |||
925 | 439 | us = get_usecs(); | ||
926 | 440 | for (cur = client->disp_stats; cur; cur = g_slist_next(cur)) { | ||
927 | 441 | struct disp_request_stats *stats = cur->data; | ||
928 | 442 | guint64 active_time, max_active_time; | ||
929 | 443 | guint64 disp_on_time; | ||
930 | 444 | GVariantBuilder *fot_builder, *fos_builder; | ||
931 | 445 | int i; | ||
932 | 446 | |||
933 | 447 | active_time = stats->active_time; | ||
934 | 448 | max_active_time = stats->max_active_time; | ||
935 | 449 | if (stats->active_since != 0) { | ||
936 | 450 | guint64 duration = us - stats->active_since; | ||
937 | 451 | active_time += duration; | ||
938 | 452 | if (duration > max_active_time) | ||
939 | 453 | max_active_time = duration; | ||
940 | 454 | } | ||
941 | 455 | |||
942 | 456 | disp_on_time = stats->disp_on_time; | ||
943 | 457 | if (stats->disp_on_since != 0) | ||
944 | 458 | disp_on_time += us - stats->disp_on_since; | ||
945 | 459 | |||
946 | 460 | fot_builder = g_variant_builder_new(G_VARIANT_TYPE("at")); | ||
947 | 461 | fos_builder = g_variant_builder_new(G_VARIANT_TYPE("at")); | ||
948 | 462 | for (i = 0; i < POWERD_NUM_DISPLAY_FLAGS; i++) { | ||
949 | 463 | guint64 flag_on_time = stats->flag_on_time[i]; | ||
950 | 464 | if (stats->flag_on_since[i] != 0) | ||
951 | 465 | flag_on_time += us - stats->flag_on_since[i]; | ||
952 | 466 | g_variant_builder_add(fot_builder, "t", flag_on_time); | ||
953 | 467 | g_variant_builder_add(fos_builder, "t", stats->flag_on_since[i]); | ||
954 | 468 | } | ||
955 | 469 | g_variant_builder_add(builder, "(ssutttttatat)", dbus_name, | ||
956 | 470 | stats->name, stats->active_count, active_time, | ||
957 | 471 | max_active_time, stats->active_since, | ||
958 | 472 | disp_on_time, stats->disp_on_since, | ||
959 | 473 | fot_builder, fos_builder); | ||
960 | 474 | g_variant_builder_unref(fot_builder); | ||
961 | 475 | g_variant_builder_unref(fos_builder); | ||
962 | 476 | count++; | ||
963 | 477 | } | ||
964 | 478 | return count; | ||
965 | 479 | } | ||
966 | 480 | |||
967 | 481 | gboolean handle_get_disp_request_stats(PowerdSource *obj, | ||
968 | 482 | GDBusMethodInvocation *invocation) | ||
969 | 483 | { | ||
970 | 484 | GVariantBuilder *builder; | ||
971 | 485 | GVariant *list, *tuple; | ||
972 | 486 | GHashTableIter iter; | ||
973 | 487 | gpointer key, value; | ||
974 | 488 | int count = 0; | ||
975 | 489 | |||
976 | 490 | builder = g_variant_builder_new(G_VARIANT_TYPE("a(ssutttttatat)")); | ||
977 | 491 | if (stats_hash) { | ||
978 | 492 | g_hash_table_iter_init(&iter, stats_hash); | ||
979 | 493 | while (g_hash_table_iter_next(&iter, &key, &value)) | ||
980 | 494 | count += build_disp_request_list(builder, value); | ||
981 | 495 | } | ||
982 | 496 | |||
983 | 497 | if (count == 0) { | ||
984 | 498 | g_variant_builder_clear(builder); | ||
985 | 499 | list = g_variant_new_array(G_VARIANT_TYPE("a(ssutttttatat)"), NULL, 0); | ||
986 | 500 | } else { | ||
987 | 501 | list = g_variant_builder_end(builder); | ||
988 | 502 | } | ||
989 | 503 | tuple = g_variant_new_tuple(&list, 1); | ||
990 | 504 | g_dbus_method_invocation_return_value(invocation, tuple); | ||
991 | 505 | g_variant_builder_unref(builder); | ||
992 | 506 | |||
993 | 507 | return TRUE; | ||
994 | 508 | } |
PASSED: Continuous integration, rev:98 jenkins. qa.ubuntu. com/job/ powerd- ci/104/ jenkins. qa.ubuntu. com/job/ powerd- saucy-armhf- ci/58 jenkins. qa.ubuntu. com/job/ powerd- saucy-armhf- ci/58/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ powerd- ci/104/ rebuild
http://