Convert LTTngTop to C++ and state system
[lttngtop.git] / src / common.cpp
1 /*
2 * Copyright (C) 2011-2012 Julien Desfossez
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 extern "C" {
19 #include <babeltrace/ctf/events.h>
20 }
21 #include <stdlib.h>
22 #include <linux/unistd.h>
23 #include <string.h>
24 #include "common.h"
25
26 StateSystem *state_system;
27 std::set<Quark> modified_quarks;
28 unsigned long last_display_update = 0;
29 unsigned long first_display_update = 0;
30 sem_t goodtodisplay, goodtoupdate, timer, pause_sem, end_trace_sem, bootstrap;
31
32 int get_cpu_id(const struct bt_ctf_event *event)
33 {
34 const struct definition *scope;
35 int cpu_id;
36
37 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_PACKET_CONTEXT);
38 cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(event, scope, "cpu_id"));
39 if (bt_ctf_field_get_error()) {
40 fprintf(stderr, "[error] get cpu_id\n");
41 return -1;
42 }
43
44 return cpu_id;
45 }
46
47 int get_context_tid(const struct bt_ctf_event *event)
48 {
49 const struct definition *scope;
50 int tid;
51
52 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
53 tid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_tid"));
54 if (bt_ctf_field_get_error()) {
55 fprintf(stderr, "Missing tid context info\n");
56 return -1;
57 }
58
59 return tid;
60 }
61
62 int get_context_pid(const struct bt_ctf_event *event)
63 {
64 const struct definition *scope;
65 int pid;
66
67 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
68 pid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_pid"));
69 if (bt_ctf_field_get_error()) {
70 fprintf(stderr, "Missing pid context info\n");
71 return -1;
72 }
73
74 return pid;
75 }
76
77 int get_context_ppid(const struct bt_ctf_event *event)
78 {
79 const struct definition *scope;
80 int ppid;
81
82 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
83 ppid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_ppid"));
84 if (bt_ctf_field_get_error()) {
85 fprintf(stderr, "Missing ppid context info\n");
86 return -1;
87 }
88
89 return ppid;
90 }
91
92 char *get_context_comm(const struct bt_ctf_event *event)
93 {
94 const struct definition *scope;
95 char *comm;
96
97 scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
98 comm = bt_ctf_get_char_array(bt_ctf_get_field(event,
99 scope, "_procname"));
100 if (bt_ctf_field_get_error()) {
101 fprintf(stderr, "Missing comm context info\n");
102 return NULL;
103 }
104
105 return comm;
106 }
107
108 /*
109 * To get the parent process, put the pid in the tid field
110 * because the parent process gets pid = tid
111 */
112 bool find_process_tid(int tid, Quark &ret_proc_quark)
113 {
114 std::string path_name = path_name_from_tid(tid);
115
116 if (state_system->attributeExists(path_name)) {
117 ret_proc_quark = state_system->getQuark(path_name);
118 return true;
119 } else {
120 return false;
121 }
122 }
123
124 Quark add_proc(int tid, std::string comm, unsigned long timestamp)
125 {
126 Quark proc_quark = state_system->getQuark(path_name_from_tid(tid));
127
128 modify_attribute(timestamp, &proc_quark, "comm", comm);
129 modify_attribute(timestamp, &proc_quark, "tid", tid);
130 modify_attribute(timestamp, &proc_quark, "birth", timestamp);
131 modify_attribute(timestamp, &proc_quark, "totalfileread", 0);
132 modify_attribute(timestamp, &proc_quark, "totalfilewrite", 0);
133 modify_attribute(timestamp, &proc_quark, "fileread", 0);
134 modify_attribute(timestamp, &proc_quark, "filewrite", 0);
135 modify_attribute(timestamp, &proc_quark, "totalcpunsec", 0UL);
136 modify_attribute(timestamp, &proc_quark, "threadstotalcpunsec", 0UL);
137 modify_attribute(timestamp, &proc_quark, "selected", 0);
138
139 increment_attribute(timestamp, NULL, "nbnewthreads");
140 increment_attribute(timestamp, NULL, "nbthreads");
141
142 add_in_sequence(timestamp, proc_quark, state_system->getQuark("proc"));
143
144 return proc_quark;
145 }
146
147 void update_proc(unsigned long timestamp, Quark proc, int pid, int tid,
148 int ppid, char *comm)
149 {
150 modify_attribute(timestamp, &proc, "pid", pid);
151 modify_attribute(timestamp, &proc, "tid", tid);
152 modify_attribute(timestamp, &proc, "ppid", ppid);
153 modify_attribute(timestamp, &proc, "comm", comm);
154 }
155
156 /*
157 * This function just sets the time of death of a process.
158 * When we rotate the cputime we remove it from the process list.
159 */
160 void death_proc(int tid, char *comm, unsigned long timestamp)
161 {
162 Quark proc_quark;
163 std::string procname;
164 bool proc_found;
165 bool procname_found;
166
167 proc_found = find_process_tid(tid, proc_quark);
168 if (proc_found) {
169 procname_found = get_current_attribute_value_string(
170 &proc_quark, "comm", procname);
171 if (procname_found && procname == comm) {
172 modify_attribute(timestamp, &proc_quark, "death",
173 timestamp);
174 increment_attribute(timestamp, NULL, "nbdeadthreads");
175 decrement_attribute(timestamp, NULL, "nbthreads");
176 }
177 }
178 }
179
180 Quark get_proc(int tid, char *comm, unsigned long timestamp)
181 {
182 Quark proc_quark;
183 std::string proc_comm;
184 bool exists = find_process_tid(tid, proc_quark);
185 std::string comm_str(comm);
186
187 if (!exists)
188 proc_quark = add_proc(tid, comm_str, timestamp);
189
190 /* If PID already exists under different name,
191 we just rename the process */
192 /* FIXME : need to integrate with clone/fork/exit to be accurate */
193 else {
194 get_current_attribute_value_string(&proc_quark, "comm",
195 proc_comm);
196 if (comm_str != proc_comm)
197 modify_attribute(timestamp, &proc_quark, "comm", comm);
198 }
199
200 return proc_quark;
201 }
202
203 Quark get_proc_pid(int pid, int tid, unsigned long timestamp)
204 {
205 Quark proc;
206 bool proc_found;
207 int proc_pid;
208 bool pid_found;
209
210 proc_found = find_process_tid(tid, proc);
211 if (proc_found) {
212 pid_found = get_current_attribute_value_int(&proc, "pid",
213 proc_pid);
214 if (pid_found && proc_pid == pid)
215 return proc;
216 }
217 return add_proc(tid, "Unknown", timestamp);
218 }
219
220 void add_thread(unsigned long timestamp, Quark parent, Quark thread)
221 {
222 std::string path;
223 int tid;
224 Quark thread_in_parent;
225
226 get_current_attribute_value_int(&thread, "tid", tid);
227 path = thread_path_name_from_tid(tid);
228
229 if (!state_system->attributeExists(parent, path)) {
230 thread_in_parent = state_system->getQuark(parent, path);
231 modify_attribute(timestamp, &thread_in_parent, "", thread);
232 add_in_sequence(timestamp, thread_in_parent,
233 state_system->getQuark(parent, "threads"));
234 }
235 }
236
237 Quark add_cpu(int cpu, unsigned long timestamp)
238 {
239 Quark cpu_quark = state_system->getQuark(path_name_from_cpuid(cpu));
240 Quark cpu_root = state_system->getQuark("cpu");
241 modify_attribute(timestamp, &cpu_quark, "id", cpu);
242
243 add_in_sequence(timestamp, cpu_quark, cpu_root);
244
245 return cpu_quark;
246 }
247
248 Quark get_cpu(int cpu, unsigned long timestamp)
249 {
250 std::string path = path_name_from_cpuid(cpu);
251 if (state_system->attributeExists(path))
252 return state_system->getQuark(path);
253 else
254 return add_cpu(cpu, timestamp);
255 }
256
257 /*
258 * At the end of a sampling period, we need to display the cpu time for each
259 * process
260 */
261 void rotate_cputime(unsigned long end)
262 {
263 Quark cpu;
264 Quark current_task;
265 unsigned long elapsed;
266 unsigned long start;
267 int tid;
268 int pid;
269
270 if (!get_current_attribute_value_quark(NULL, "cpu", cpu)) {
271 // No CPU to process
272 return;
273 }
274
275 do {
276 get_current_attribute_value_ulong(&cpu, "task_start", start);
277 elapsed = end - start;
278 if (get_current_attribute_value_quark(&cpu, "current_task",
279 current_task)) {
280 increase_attribute(
281 end, &current_task, "totalcpunsec", elapsed);
282 increase_attribute(
283 end, &current_task, "threadstotalcpunsec",
284 elapsed);
285 get_current_attribute_value_int(
286 &current_task, "pid", pid);
287 get_current_attribute_value_int(
288 &current_task, "tid", tid);
289 if (pid != tid &&
290 state_system->attributeExists(
291 current_task, "threadparent")) {
292 increase_attribute(
293 end, &current_task,
294 "threadparent/threadstotalcpunsec",
295 elapsed);
296 }
297 }
298 modify_attribute(end + 1, &cpu, "task_start", end);
299 } while (get_current_attribute_value_quark(&cpu, "next", cpu));
300 }
301
302 void update_state_on_refresh(unsigned long start, unsigned long end)
303 {
304 Quark proc;
305
306 rotate_cputime(end);
307
308 if (get_current_attribute_value_quark(NULL, "proc", proc)) {
309 do {
310 update_proc_on_refresh(proc, start, end);
311 } while (get_current_attribute_value_quark(
312 &proc, "next", proc));
313 }
314 }
315
316 enum bt_cb_ret handle_statedump_process_state(
317 struct bt_ctf_event *call_data, void *private_data)
318 {
319 const struct definition *scope;
320 unsigned long timestamp;
321 int pid, tid;
322 /* FIXME */
323 /* char *procname; */
324 Quark proc_quark;
325
326 timestamp = bt_ctf_get_timestamp(call_data);
327 if (timestamp == -1ULL)
328 goto error;
329
330 scope = bt_ctf_get_top_level_scope(call_data,
331 BT_EVENT_FIELDS);
332 pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
333 scope, "_pid"));
334 if (bt_ctf_field_get_error()) {
335 fprintf(stderr, "Missing pid context info\n");
336 goto error;
337 }
338
339 scope = bt_ctf_get_top_level_scope(call_data,
340 BT_EVENT_FIELDS);
341 tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
342 scope, "_tid"));
343 if (bt_ctf_field_get_error()) {
344 fprintf(stderr, "Missing tid context info\n");
345 goto error;
346 }
347
348 /*
349 * FIXME
350 * I first tried with bt_ctf_get_string but doesn`t work at all
351 * It couldn`t find the field _name because it is an integer in
352 * the metadata and not a string like _filename for the
353 * statedump_file_descriptor
354 */
355 /*
356 * FIXME
357 * We use "Dumped" instead of procname because procname sometimes
358 * causes memory corruption. All FIXME's in this function are
359 * related to this.
360 */
361 /* procname = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
362 scope, "_name")); */
363 if (bt_ctf_field_get_error()) {
364 fprintf(stderr, "Missing process name context info\n");
365 goto error;
366 }
367
368 proc_quark = get_proc(tid, (char *)"Dumped", timestamp);
369 modify_attribute(timestamp, &proc_quark, "pid", pid);
370
371 /* FIXME */
372 /* free(procname); */
373
374 return BT_CB_OK;
375
376 error:
377 return BT_CB_ERROR_STOP;
378 }
379
380 std::string path_name_from_cpuid(int cpuid)
381 {
382 std::stringstream ss;
383 ss << "cpus/" << cpuid;
384 return ss.str();
385 }
386
387 std::string thread_path_name_from_tid(int tid)
388 {
389 std::stringstream ss;
390 ss << "threads/" << tid;
391 return ss.str();
392 }
393
394 std::string path_name_from_tid(int tid)
395 {
396 std::stringstream ss;
397 ss << "processes/" << tid;
398 return ss.str();
399 }
400
401 std::string path_name_from_fd(int fd)
402 {
403 std::stringstream ss;
404 ss << "files/" << fd;
405 return ss.str();
406 }
407
408 void update_file_on_refresh(Quark proc, Quark file, unsigned long end)
409 {
410 int flag;
411 int fd;
412 std::string path;
413 Quark file_pointer;
414
415 /* File closed */
416 get_current_attribute_value_int(&file, "file/flag", flag);
417 if (flag == __NR_close) {
418 get_current_attribute_value_int(&file, "file/fd", fd);
419 if (fd != -1) {
420 path = path_name_from_fd(fd);
421 file_pointer = state_system->getQuark(proc, path);
422 state_system->removeAttribute(end + 1, file_pointer);
423 state_system->modifyAttribute(end + 1,
424 state_system->getQuark(
425 file, "file/fd"),
426 -1);
427 }
428 }
429 }
430
431 void update_proc_on_refresh(Quark proc, unsigned long start, unsigned long end)
432 {
433
434 int fileread = 0;
435 int filewrite = 0;
436 unsigned long time;
437 unsigned long death;
438 Quark parent;
439 Quark file;
440 int tid;
441 std::string path;
442
443 /* Process died */
444 if (get_current_attribute_value_ulong(&proc, "death", death) &&
445 death > 0 && death <= end) {
446 /* Remove thread from threadparent's threads */
447 if (get_current_attribute_value_quark(
448 &proc, "threadparent", parent)) {
449 get_current_attribute_value_int(&proc, "tid", tid);
450 path = thread_path_name_from_tid(tid);
451 remove_from_sequence(
452 end + 1,
453 state_system->getQuark(parent, path),
454 state_system->getQuark(parent, "threads"));
455 }
456
457 remove_from_sequence(end + 1, proc,
458 state_system->getQuark("proc"));
459 return;
460 }
461
462 /* Files */
463 if (get_current_attribute_value_quark(
464 &proc, "files_history/current", file)) {
465 do {
466 update_file_on_refresh(proc, file, end);
467 } while (get_current_attribute_value_quark(
468 &file, "next", file));
469 }
470
471 /* compute the stream speed */
472 if (end - start != 0) {
473 time = end - start;
474 get_current_attribute_value_int(&proc, "fileread", fileread);
475 get_current_attribute_value_int(&proc, "filewrite", filewrite);
476 modify_attribute(end, &proc, "fileread", (int)(fileread / time));
477 modify_attribute(end, &proc, "filewrite", (int)(filewrite / time));
478 }
479 }
480
481 void modify_attribute(unsigned long timestamp, const Quark *starting_node,
482 std::string attribute, int value)
483 {
484 Quark q;
485 if (starting_node)
486 q = state_system->getQuark(*starting_node, attribute);
487 else
488 q = state_system->getQuark(attribute);
489 state_system->updateCurrentState(q, value);
490
491 modified_quarks.insert(q);
492 }
493
494 void modify_attribute(unsigned long timestamp, const Quark *starting_node,
495 std::string attribute, Quark value)
496 {
497 Quark q;
498 if (starting_node)
499 q = state_system->getQuark(*starting_node, attribute);
500 else
501 q = state_system->getQuark(attribute);
502 state_system->updateCurrentState(q, StateValue::SharedPtr(
503 new QuarkStateValue(value)));
504
505 modified_quarks.insert(q);
506 }
507
508 void modify_attribute(unsigned long timestamp, const Quark *starting_node,
509 std::string attribute, char *value)
510 {
511 Quark q;
512 if (starting_node)
513 q = state_system->getQuark(*starting_node, attribute);
514 else
515 q = state_system->getQuark(attribute);
516 state_system->updateCurrentState(q, std::string(value));
517
518 modified_quarks.insert(q);
519 }
520
521 void modify_attribute(unsigned long timestamp, const Quark *starting_node,
522 std::string attribute, std::string value)
523 {
524 Quark q;
525 if (starting_node)
526 q = state_system->getQuark(*starting_node, attribute);
527 else
528 q = state_system->getQuark(attribute);
529 state_system->updateCurrentState(q, value);
530
531 modified_quarks.insert(q);
532 }
533
534 void modify_attribute(unsigned long timestamp, const Quark *starting_node,
535 std::string attribute, unsigned long value)
536 {
537 // Libstate works with 32-bit ints, we split the 64-bit ulong
538 // into 2 32-bit ints
539 unsigned int h = value >> 32;
540 unsigned int l = value & 0xffffffff;
541 Quark ql, qh;
542
543 if (starting_node) {
544 ql = state_system->getQuark(*starting_node, attribute + "/l");
545 qh = state_system->getQuark(*starting_node, attribute + "/h");
546 }
547 else {
548 ql = state_system->getQuark(attribute + "/l");
549 qh = state_system->getQuark(attribute + "/h");
550 }
551 state_system->updateCurrentState(ql, l);
552 state_system->updateCurrentState(qh, h);
553
554 modified_quarks.insert(ql);
555 modified_quarks.insert(qh);
556 }
557
558 void nullify_attribute(unsigned long timestamp, const Quark *starting_node,
559 std::string attribute)
560 {
561 Quark q;
562 q = state_system->getQuark(*starting_node, attribute);
563 state_system->updateCurrentState(q, StateValue::getNullValue());
564
565 modified_quarks.insert(q);
566 }
567
568 void increment_attribute(unsigned long timestamp, const Quark *starting_node,
569 std::string attribute)
570 {
571 increase_attribute(timestamp, starting_node, attribute, 1);
572 }
573
574 void increase_attribute(unsigned long timestamp, const Quark *starting_node,
575 std::string attribute, int amount)
576 {
577 int starting_value = 0;
578 get_current_attribute_value_int(starting_node, attribute,
579 starting_value);
580 modify_attribute(timestamp, starting_node, attribute,
581 starting_value + amount);
582 }
583
584 void increase_attribute(unsigned long timestamp, const Quark *starting_node,
585 std::string attribute, unsigned long amount)
586 {
587 unsigned long starting_value = 0;
588 get_current_attribute_value_ulong(starting_node, attribute,
589 starting_value);
590 modify_attribute(timestamp, starting_node, attribute,
591 starting_value + amount);
592 }
593
594 void decrement_attribute(unsigned long timestamp, const Quark *starting_node,
595 std::string attribute)
596 {
597 decrease_attribute(timestamp, starting_node, attribute, 1);
598 }
599
600 void decrease_attribute(unsigned long timestamp, const Quark *starting_node,
601 std::string attribute, int amount)
602 {
603 int starting_value = 0;
604 get_current_attribute_value_int(starting_node, attribute,
605 starting_value);
606 modify_attribute(timestamp, starting_node, attribute,
607 starting_value - amount);
608 }
609
610 void decrease_attribute(unsigned long timestamp, const Quark *starting_node,
611 std::string attribute, unsigned long amount)
612 {
613 unsigned long starting_value = 0;
614 get_current_attribute_value_ulong(starting_node, attribute,
615 starting_value);
616 modify_attribute(timestamp, starting_node, attribute,
617 starting_value - amount);
618 }
619
620 bool get_current_attribute_value_int(const Quark *starting_node,
621 std::string attribute, int &value)
622 {
623 IntegerStateValue::SharedPtr value_ptr;
624 Quark q;
625
626 if (starting_node == NULL)
627 q = state_system->getQuark(attribute);
628 else
629 q = state_system->getQuark(*starting_node, attribute);
630 value_ptr = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
631 state_system->getCurrentStateValue(q));
632
633 if (value_ptr) {
634 value = value_ptr->getValue();
635 return true;
636 }
637 return false;
638 }
639
640 bool get_current_attribute_value_ulong(const Quark *starting_node,
641 std::string attribute,
642 unsigned long &value)
643 {
644 // Libstate works with 32-bit ints, we split the 64-bit ulong
645 // into 2 32-bit ints
646 IntegerStateValue::SharedPtr value_ptr_l, value_ptr_h;
647 Quark ql, qh;
648 unsigned int l, h;
649
650 if (starting_node == NULL) {
651 ql = state_system->getQuark(attribute + "/l");
652 qh = state_system->getQuark(attribute + "/h");
653 }
654 else {
655 ql = state_system->getQuark(*starting_node, attribute + "/l");
656 qh = state_system->getQuark(*starting_node, attribute + "/h");
657 }
658 value_ptr_l = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
659 state_system->getCurrentStateValue(ql));
660 value_ptr_h = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
661 state_system->getCurrentStateValue(qh));
662
663 if (value_ptr_l && value_ptr_h) {
664 l = value_ptr_l->getValue();
665 h = value_ptr_h->getValue();
666 value = (unsigned long)h << 32 | l;
667 return true;
668 }
669 return false;
670 }
671
672 bool get_current_attribute_value_quark(const Quark *starting_node,
673 std::string attribute, Quark &value)
674 {
675 QuarkStateValue::SharedPtr value_ptr;
676 IntegerStateValue::SharedPtr value_ptr_int;
677 Quark q;
678
679 if (starting_node == NULL)
680 q = state_system->getQuark(attribute);
681 else
682 q = state_system->getQuark(*starting_node, attribute);
683 value_ptr = std::tr1::dynamic_pointer_cast<QuarkStateValue>(
684 state_system->getCurrentStateValue(q));
685
686 if (value_ptr) {
687 value = value_ptr->getValue();
688 return true;
689 } else {
690 /* Quark attribute support is not fully integrated in libstate
691 and librbrntrvll so quarks may get demoted to ints */
692 value_ptr_int = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
693 state_system->getCurrentStateValue(q));
694 if (value_ptr_int) {
695 value = (Quark)value_ptr_int->getValue();
696 return true;
697 }
698 }
699 return false;
700 }
701
702 bool get_current_attribute_value_string(const Quark *starting_node,
703 std::string attribute, std::string &value)
704 {
705 StringStateValue::SharedPtr value_ptr;
706 Quark q;
707
708 if (starting_node == NULL)
709 q = state_system->getQuark(attribute);
710 else
711 q = state_system->getQuark(*starting_node, attribute);
712 value_ptr = std::tr1::dynamic_pointer_cast<StringStateValue>(
713 state_system->getCurrentStateValue(q));
714
715 if (value_ptr) {
716 value = value_ptr->getValue();
717 return true;
718 }
719 return false;
720 }
721
722 bool get_attribute_value_at_int(unsigned long timestamp,
723 const Quark *starting_node,
724 std::string attribute,
725 int &value)
726 {
727 StateInterval interval;
728 Quark q;
729 IntegerStateValue::SharedPtr value_ptr;
730
731 if (starting_node == NULL)
732 q = state_system->getQuark(attribute);
733 else
734 q = state_system->getQuark(*starting_node, attribute);
735 interval = state_system->getStateOfAt(timestamp, q);
736 value_ptr = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
737 interval.value);
738
739 if (value_ptr) {
740 value = value_ptr->getValue();
741 return true;
742 }
743 return false;
744 }
745
746 bool get_attribute_value_at_ulong(unsigned long timestamp,
747 const Quark *starting_node,
748 std::string attribute,
749 unsigned long &value)
750 {
751 // Libstate works with 32-bit ints, we split the 64-bit ulong
752 // into 2 32-bit ints
753 StateInterval interval_l, interval_h;
754 Quark ql, qh;
755 IntegerStateValue::SharedPtr value_ptr_l, value_ptr_h;
756 unsigned int l, h;
757
758 if (starting_node == NULL) {
759 ql = state_system->getQuark(attribute + "/l");
760 qh = state_system->getQuark(attribute + "/h");
761 }
762 else {
763 ql = state_system->getQuark(*starting_node, attribute + "/l");
764 qh = state_system->getQuark(*starting_node, attribute + "/h");
765 }
766 interval_l = state_system->getStateOfAt(timestamp, ql);
767 interval_h = state_system->getStateOfAt(timestamp, qh);
768 value_ptr_l = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
769 interval_l.value);
770 value_ptr_h = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
771 interval_h.value);
772
773 if (value_ptr_l && value_ptr_h) {
774 l = value_ptr_l->getValue();
775 h = value_ptr_h->getValue();
776 value = (unsigned long)h << 32 | l;
777 return true;
778 }
779 return false;
780 }
781
782 bool get_attribute_value_at_quark(unsigned long timestamp,
783 const Quark *starting_node,
784 std::string attribute,
785 Quark &value)
786 {
787 StateInterval interval;
788 Quark q;
789 QuarkStateValue::SharedPtr value_ptr;
790 IntegerStateValue::SharedPtr value_ptr_int;
791
792 if (starting_node == NULL)
793 q = state_system->getQuark(attribute);
794 else
795 q = state_system->getQuark(*starting_node, attribute);
796 interval = state_system->getStateOfAt(timestamp, q);
797 value_ptr = std::tr1::dynamic_pointer_cast<QuarkStateValue>(
798 interval.value);
799
800 if (value_ptr) {
801 value = value_ptr->getValue();
802 return true;
803 } else {
804 /* Quark attribute support is not fully integrated in libstate
805 and librbrntrvll so quarks may get demoted to ints */
806 value_ptr_int = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
807 interval.value);
808 if (value_ptr_int) {
809 value = (Quark)value_ptr_int->getValue();
810 return true;
811 }
812 }
813 return false;
814 }
815
816 bool get_attribute_value_at_string(unsigned long timestamp,
817 const Quark *starting_node,
818 std::string attribute,
819 std::string &value)
820 {
821 StateInterval interval;
822 Quark q;
823 StringStateValue::SharedPtr value_ptr;
824
825 if (starting_node == NULL)
826 q = state_system->getQuark(attribute);
827 else
828 q = state_system->getQuark(*starting_node, attribute);
829 interval = state_system->getStateOfAt(timestamp, q);
830 value_ptr = std::tr1::dynamic_pointer_cast<StringStateValue>(
831 interval.value);
832
833 if (value_ptr) {
834 value = value_ptr->getValue();
835 return true;
836 }
837 return false;
838 }
839
840 void add_in_sequence(unsigned long timestamp, Quark item, Quark beg)
841 {
842 Quark old_newest;
843 if (get_current_attribute_value_quark(&beg, "", old_newest)) {
844 modify_attribute(timestamp, &item, "next", old_newest);
845 modify_attribute(timestamp, &old_newest, "prev", item);
846 }
847 modify_attribute(timestamp, &beg, "", item);
848
849 }
850
851 void remove_from_sequence(unsigned long timestamp, Quark item, Quark beg)
852 {
853 Quark prev;
854 Quark next;
855 bool hasPrev;
856 bool hasNext;
857
858 hasPrev = get_current_attribute_value_quark(&item,
859 "prev", prev);
860 hasNext = get_current_attribute_value_quark(&item,
861 "next", next);
862 if (hasPrev && hasNext) {
863 state_system->modifyAttribute(timestamp,
864 state_system->getQuark(next, "prev"),
865 StateValue::SharedPtr(
866 new QuarkStateValue(prev)));
867 state_system->modifyAttribute(timestamp,
868 state_system->getQuark(prev, "next"),
869 StateValue::SharedPtr(
870 new QuarkStateValue(next)));
871 } else if (hasPrev) {
872 state_system->modifyAttribute(timestamp,
873 state_system->getQuark(prev, "next"),
874 StateValue::getNullValue());
875 } else if (hasNext) {
876 state_system->modifyAttribute(timestamp,
877 state_system->getQuark(next, "prev"),
878 StateValue::getNullValue());
879 state_system->modifyAttribute(timestamp, beg,
880 StateValue::SharedPtr(
881 new QuarkStateValue(next)));
882 } else {
883 state_system->modifyAttribute(timestamp, beg,
884 StateValue::getNullValue());
885 }
886
887 state_system->removeAttribute(timestamp, item);
888 }
889
890 int get_sequence_length(unsigned long timestamp, Quark beg)
891 {
892 int length = 0;
893 Quark it;
894
895 if (get_attribute_value_at_quark(timestamp, &beg, "", it)) {
896 do {
897 length++;
898 } while (get_attribute_value_at_quark(
899 timestamp, &it, "next", it));
900 }
901
902 return length;
903 }
904
905 bool get_interval_value_int(unsigned long start,
906 unsigned long end,
907 const Quark *starting_node,
908 std::string attribute,
909 int &value)
910 {
911 int start_value, end_value;
912
913 if (get_attribute_value_at_int(
914 start, starting_node, attribute, start_value) &&
915 get_attribute_value_at_int(
916 end, starting_node, attribute, end_value)) {
917 value = end_value - start_value;
918 return true;
919 }
920 return false;
921 }
922
923 bool get_interval_value_ulong(unsigned long start,
924 unsigned long end,
925 const Quark *starting_node,
926 std::string attribute,
927 unsigned long &value)
928 {
929 unsigned long start_value, end_value;
930
931 if (get_attribute_value_at_ulong(
932 start, starting_node, attribute, start_value) &&
933 get_attribute_value_at_ulong(
934 end, starting_node, attribute, end_value)) {
935 value = end_value - start_value;
936 return true;
937 }
938 return false;
939 }
940
941 int sequence_to_array(unsigned long timestamp, Quark beg, Quark *arr,
942 int len)
943 {
944 int ret = 0;
945 Quark it;
946
947 if (arr == NULL || len < 1)
948 return 0;
949
950 if (get_attribute_value_at_quark(timestamp, &beg, "", it)) {
951 do {
952 arr[ret] = it;
953 ret++;
954 } while (get_attribute_value_at_quark(
955 timestamp, &it, "next", it) && ret < len);
956 }
957
958 return ret;
959 }
960
961 int get_global_perf_list(unsigned long timestamp, Quark *arr, int len)
962 {
963 std::map<std::string, int> perfs;
964 std::string key;
965 int val;
966 int ret;
967 Quark proc;
968 Quark perf;
969 std::map<std::string, int>::const_iterator iter;
970
971 if (arr == NULL || len < 1)
972 return 0;
973
974 if (get_attribute_value_at_quark(timestamp, NULL, "proc", proc)) {
975 do {
976 if (get_attribute_value_at_quark(timestamp, &proc,
977 "perf", perf)) {
978 do {
979 get_attribute_value_at_string(timestamp,
980 &perf,
981 "key",
982 key);
983 get_attribute_value_at_int(timestamp,
984 &perf,
985 "count",
986 val);
987 if (perfs.find(key) != perfs.end())
988 perfs[key] += val;
989 else
990 perfs[key] = val;
991 } while (get_attribute_value_at_quark(timestamp,
992 &perf,
993 "next",
994 perf));
995 }
996 } while (get_attribute_value_at_quark(timestamp, &proc, "next",
997 proc));
998 }
999
1000 for (iter = perfs.begin(), ret = 0; iter != perfs.end() && ret < len;
1001 iter++, ret++) {
1002 perf = state_system->getQuark("perf/" + iter->first);
1003 modify_attribute(timestamp, &perf, "count", iter->second);
1004 arr[ret] = perf;
1005 }
1006
1007 return ret;
1008 }
1009
1010 int get_global_perf_list_size(unsigned long timestamp)
1011 {
1012 std::set<std::string> perfs;
1013 std::string key;
1014 int len = 0;
1015 Quark proc;
1016 Quark perf;
1017
1018 if (get_attribute_value_at_quark(timestamp, NULL, "proc", proc)) {
1019 do {
1020 if (get_attribute_value_at_quark(timestamp, &proc,
1021 "perf", perf)) {
1022 do {
1023 get_attribute_value_at_string(timestamp,
1024 &perf,
1025 "key",
1026 key);
1027 if (perfs.find(key) == perfs.end()) {
1028 perfs.insert(key);
1029 len++;
1030 }
1031 } while (get_attribute_value_at_quark(timestamp,
1032 &perf,
1033 "next",
1034 perf));
1035 }
1036 } while (get_attribute_value_at_quark(timestamp, &proc, "next",
1037 proc));
1038 }
1039
1040 return len;
1041 }
1042
1043 int get_number_of_opened_files(unsigned long timestamp, Quark proc)
1044 {
1045 int len = 0;
1046 Quark fh;
1047 int fd;
1048
1049 if (get_attribute_value_at_quark(timestamp, &proc,
1050 "files_history/current", fh)) {
1051 do {
1052 get_attribute_value_at_int(timestamp, &fh, "file/fd",
1053 fd);
1054 if (fd != -1)
1055 len++;
1056 } while (get_attribute_value_at_quark(timestamp, &fh, "next",
1057 fh));
1058 }
1059
1060 return len;
1061 }
1062
1063 int get_opened_files(unsigned long timestamp, Quark proc, Quark *arr, int len)
1064 {
1065 int ret = 0;
1066 Quark file, fh;
1067 int fd;
1068
1069 if (arr == NULL || len < 1)
1070 return 0;
1071
1072 if (get_attribute_value_at_quark(timestamp, &proc,
1073 "files_history/current", fh)) {
1074 do {
1075 file = state_system->getQuark(fh, "file");
1076 get_attribute_value_at_int(timestamp, &file, "fd",
1077 fd);
1078 if (fd != -1) {
1079 arr[ret] = file;
1080 ret++;
1081 }
1082 if (ret == len)
1083 break;
1084 } while (get_attribute_value_at_quark(timestamp, &fh, "next",
1085 fh));
1086 }
1087
1088 return ret;
1089 }
This page took 0.051216 seconds and 4 git commands to generate.