--- /dev/null
+/*
+ * Copyright (C) 2011-2012 Julien Desfossez
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern "C" {
+#include <babeltrace/ctf/events.h>
+}
+#include <stdlib.h>
+#include <linux/unistd.h>
+#include <string.h>
+#include "common.h"
+
+StateSystem *state_system;
+std::set<Quark> modified_quarks;
+unsigned long last_display_update = 0;
+unsigned long first_display_update = 0;
+sem_t goodtodisplay, goodtoupdate, timer, pause_sem, end_trace_sem, bootstrap;
+
+int get_cpu_id(const struct bt_ctf_event *event)
+{
+ const struct definition *scope;
+ int cpu_id;
+
+ scope = bt_ctf_get_top_level_scope(event, BT_STREAM_PACKET_CONTEXT);
+ cpu_id = bt_ctf_get_uint64(bt_ctf_get_field(event, scope, "cpu_id"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "[error] get cpu_id\n");
+ return -1;
+ }
+
+ return cpu_id;
+}
+
+int get_context_tid(const struct bt_ctf_event *event)
+{
+ const struct definition *scope;
+ int tid;
+
+ scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
+ tid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_tid"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing tid context info\n");
+ return -1;
+ }
+
+ return tid;
+}
+
+int get_context_pid(const struct bt_ctf_event *event)
+{
+ const struct definition *scope;
+ int pid;
+
+ scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
+ pid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_pid"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing pid context info\n");
+ return -1;
+ }
+
+ return pid;
+}
+
+int get_context_ppid(const struct bt_ctf_event *event)
+{
+ const struct definition *scope;
+ int ppid;
+
+ scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
+ ppid = bt_ctf_get_int64(bt_ctf_get_field(event, scope, "_ppid"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing ppid context info\n");
+ return -1;
+ }
+
+ return ppid;
+}
+
+char *get_context_comm(const struct bt_ctf_event *event)
+{
+ const struct definition *scope;
+ char *comm;
+
+ scope = bt_ctf_get_top_level_scope(event, BT_STREAM_EVENT_CONTEXT);
+ comm = bt_ctf_get_char_array(bt_ctf_get_field(event,
+ scope, "_procname"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing comm context info\n");
+ return NULL;
+ }
+
+ return comm;
+}
+
+/*
+ * To get the parent process, put the pid in the tid field
+ * because the parent process gets pid = tid
+ */
+bool find_process_tid(int tid, Quark &ret_proc_quark)
+{
+ std::string path_name = path_name_from_tid(tid);
+
+ if (state_system->attributeExists(path_name)) {
+ ret_proc_quark = state_system->getQuark(path_name);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Quark add_proc(int tid, std::string comm, unsigned long timestamp)
+{
+ Quark proc_quark = state_system->getQuark(path_name_from_tid(tid));
+
+ modify_attribute(timestamp, &proc_quark, "comm", comm);
+ modify_attribute(timestamp, &proc_quark, "tid", tid);
+ modify_attribute(timestamp, &proc_quark, "birth", timestamp);
+ modify_attribute(timestamp, &proc_quark, "totalfileread", 0);
+ modify_attribute(timestamp, &proc_quark, "totalfilewrite", 0);
+ modify_attribute(timestamp, &proc_quark, "fileread", 0);
+ modify_attribute(timestamp, &proc_quark, "filewrite", 0);
+ modify_attribute(timestamp, &proc_quark, "totalcpunsec", 0UL);
+ modify_attribute(timestamp, &proc_quark, "threadstotalcpunsec", 0UL);
+ modify_attribute(timestamp, &proc_quark, "selected", 0);
+
+ increment_attribute(timestamp, NULL, "nbnewthreads");
+ increment_attribute(timestamp, NULL, "nbthreads");
+
+ add_in_sequence(timestamp, proc_quark, state_system->getQuark("proc"));
+
+ return proc_quark;
+}
+
+void update_proc(unsigned long timestamp, Quark proc, int pid, int tid,
+ int ppid, char *comm)
+{
+ modify_attribute(timestamp, &proc, "pid", pid);
+ modify_attribute(timestamp, &proc, "tid", tid);
+ modify_attribute(timestamp, &proc, "ppid", ppid);
+ modify_attribute(timestamp, &proc, "comm", comm);
+}
+
+/*
+ * This function just sets the time of death of a process.
+ * When we rotate the cputime we remove it from the process list.
+ */
+void death_proc(int tid, char *comm, unsigned long timestamp)
+{
+ Quark proc_quark;
+ std::string procname;
+ bool proc_found;
+ bool procname_found;
+
+ proc_found = find_process_tid(tid, proc_quark);
+ if (proc_found) {
+ procname_found = get_current_attribute_value_string(
+ &proc_quark, "comm", procname);
+ if (procname_found && procname == comm) {
+ modify_attribute(timestamp, &proc_quark, "death",
+ timestamp);
+ increment_attribute(timestamp, NULL, "nbdeadthreads");
+ decrement_attribute(timestamp, NULL, "nbthreads");
+ }
+ }
+}
+
+Quark get_proc(int tid, char *comm, unsigned long timestamp)
+{
+ Quark proc_quark;
+ std::string proc_comm;
+ bool exists = find_process_tid(tid, proc_quark);
+ std::string comm_str(comm);
+
+ if (!exists)
+ proc_quark = add_proc(tid, comm_str, timestamp);
+
+ /* If PID already exists under different name,
+ we just rename the process */
+ /* FIXME : need to integrate with clone/fork/exit to be accurate */
+ else {
+ get_current_attribute_value_string(&proc_quark, "comm",
+ proc_comm);
+ if (comm_str != proc_comm)
+ modify_attribute(timestamp, &proc_quark, "comm", comm);
+ }
+
+ return proc_quark;
+}
+
+Quark get_proc_pid(int pid, int tid, unsigned long timestamp)
+{
+ Quark proc;
+ bool proc_found;
+ int proc_pid;
+ bool pid_found;
+
+ proc_found = find_process_tid(tid, proc);
+ if (proc_found) {
+ pid_found = get_current_attribute_value_int(&proc, "pid",
+ proc_pid);
+ if (pid_found && proc_pid == pid)
+ return proc;
+ }
+ return add_proc(tid, "Unknown", timestamp);
+}
+
+void add_thread(unsigned long timestamp, Quark parent, Quark thread)
+{
+ std::string path;
+ int tid;
+ Quark thread_in_parent;
+
+ get_current_attribute_value_int(&thread, "tid", tid);
+ path = thread_path_name_from_tid(tid);
+
+ if (!state_system->attributeExists(parent, path)) {
+ thread_in_parent = state_system->getQuark(parent, path);
+ modify_attribute(timestamp, &thread_in_parent, "", thread);
+ add_in_sequence(timestamp, thread_in_parent,
+ state_system->getQuark(parent, "threads"));
+ }
+}
+
+Quark add_cpu(int cpu, unsigned long timestamp)
+{
+ Quark cpu_quark = state_system->getQuark(path_name_from_cpuid(cpu));
+ Quark cpu_root = state_system->getQuark("cpu");
+ modify_attribute(timestamp, &cpu_quark, "id", cpu);
+
+ add_in_sequence(timestamp, cpu_quark, cpu_root);
+
+ return cpu_quark;
+}
+
+Quark get_cpu(int cpu, unsigned long timestamp)
+{
+ std::string path = path_name_from_cpuid(cpu);
+ if (state_system->attributeExists(path))
+ return state_system->getQuark(path);
+ else
+ return add_cpu(cpu, timestamp);
+}
+
+/*
+ * At the end of a sampling period, we need to display the cpu time for each
+ * process
+ */
+void rotate_cputime(unsigned long end)
+{
+ Quark cpu;
+ Quark current_task;
+ unsigned long elapsed;
+ unsigned long start;
+ int tid;
+ int pid;
+
+ if (!get_current_attribute_value_quark(NULL, "cpu", cpu)) {
+ // No CPU to process
+ return;
+ }
+
+ do {
+ get_current_attribute_value_ulong(&cpu, "task_start", start);
+ elapsed = end - start;
+ if (get_current_attribute_value_quark(&cpu, "current_task",
+ current_task)) {
+ increase_attribute(
+ end, ¤t_task, "totalcpunsec", elapsed);
+ increase_attribute(
+ end, ¤t_task, "threadstotalcpunsec",
+ elapsed);
+ get_current_attribute_value_int(
+ ¤t_task, "pid", pid);
+ get_current_attribute_value_int(
+ ¤t_task, "tid", tid);
+ if (pid != tid &&
+ state_system->attributeExists(
+ current_task, "threadparent")) {
+ increase_attribute(
+ end, ¤t_task,
+ "threadparent/threadstotalcpunsec",
+ elapsed);
+ }
+ }
+ modify_attribute(end + 1, &cpu, "task_start", end);
+ } while (get_current_attribute_value_quark(&cpu, "next", cpu));
+}
+
+void update_state_on_refresh(unsigned long start, unsigned long end)
+{
+ Quark proc;
+
+ rotate_cputime(end);
+
+ if (get_current_attribute_value_quark(NULL, "proc", proc)) {
+ do {
+ update_proc_on_refresh(proc, start, end);
+ } while (get_current_attribute_value_quark(
+ &proc, "next", proc));
+ }
+}
+
+enum bt_cb_ret handle_statedump_process_state(
+ struct bt_ctf_event *call_data, void *private_data)
+{
+ const struct definition *scope;
+ unsigned long timestamp;
+ int pid, tid;
+ /* FIXME */
+ /* char *procname; */
+ Quark proc_quark;
+
+ timestamp = bt_ctf_get_timestamp(call_data);
+ if (timestamp == -1ULL)
+ goto error;
+
+ scope = bt_ctf_get_top_level_scope(call_data,
+ BT_EVENT_FIELDS);
+ pid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
+ scope, "_pid"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing pid context info\n");
+ goto error;
+ }
+
+ scope = bt_ctf_get_top_level_scope(call_data,
+ BT_EVENT_FIELDS);
+ tid = bt_ctf_get_int64(bt_ctf_get_field(call_data,
+ scope, "_tid"));
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing tid context info\n");
+ goto error;
+ }
+
+ /*
+ * FIXME
+ * I first tried with bt_ctf_get_string but doesn`t work at all
+ * It couldn`t find the field _name because it is an integer in
+ * the metadata and not a string like _filename for the
+ * statedump_file_descriptor
+ */
+ /*
+ * FIXME
+ * We use "Dumped" instead of procname because procname sometimes
+ * causes memory corruption. All FIXME's in this function are
+ * related to this.
+ */
+ /* procname = bt_ctf_get_char_array(bt_ctf_get_field(call_data,
+ scope, "_name")); */
+ if (bt_ctf_field_get_error()) {
+ fprintf(stderr, "Missing process name context info\n");
+ goto error;
+ }
+
+ proc_quark = get_proc(tid, (char *)"Dumped", timestamp);
+ modify_attribute(timestamp, &proc_quark, "pid", pid);
+
+ /* FIXME */
+ /* free(procname); */
+
+ return BT_CB_OK;
+
+error:
+ return BT_CB_ERROR_STOP;
+}
+
+std::string path_name_from_cpuid(int cpuid)
+{
+ std::stringstream ss;
+ ss << "cpus/" << cpuid;
+ return ss.str();
+}
+
+std::string thread_path_name_from_tid(int tid)
+{
+ std::stringstream ss;
+ ss << "threads/" << tid;
+ return ss.str();
+}
+
+std::string path_name_from_tid(int tid)
+{
+ std::stringstream ss;
+ ss << "processes/" << tid;
+ return ss.str();
+}
+
+std::string path_name_from_fd(int fd)
+{
+ std::stringstream ss;
+ ss << "files/" << fd;
+ return ss.str();
+}
+
+void update_file_on_refresh(Quark proc, Quark file, unsigned long end)
+{
+ int flag;
+ int fd;
+ std::string path;
+ Quark file_pointer;
+
+ /* File closed */
+ get_current_attribute_value_int(&file, "file/flag", flag);
+ if (flag == __NR_close) {
+ get_current_attribute_value_int(&file, "file/fd", fd);
+ if (fd != -1) {
+ path = path_name_from_fd(fd);
+ file_pointer = state_system->getQuark(proc, path);
+ state_system->removeAttribute(end + 1, file_pointer);
+ state_system->modifyAttribute(end + 1,
+ state_system->getQuark(
+ file, "file/fd"),
+ -1);
+ }
+ }
+}
+
+void update_proc_on_refresh(Quark proc, unsigned long start, unsigned long end)
+{
+
+ int fileread = 0;
+ int filewrite = 0;
+ unsigned long time;
+ unsigned long death;
+ Quark parent;
+ Quark file;
+ int tid;
+ std::string path;
+
+ /* Process died */
+ if (get_current_attribute_value_ulong(&proc, "death", death) &&
+ death > 0 && death <= end) {
+ /* Remove thread from threadparent's threads */
+ if (get_current_attribute_value_quark(
+ &proc, "threadparent", parent)) {
+ get_current_attribute_value_int(&proc, "tid", tid);
+ path = thread_path_name_from_tid(tid);
+ remove_from_sequence(
+ end + 1,
+ state_system->getQuark(parent, path),
+ state_system->getQuark(parent, "threads"));
+ }
+
+ remove_from_sequence(end + 1, proc,
+ state_system->getQuark("proc"));
+ return;
+ }
+
+ /* Files */
+ if (get_current_attribute_value_quark(
+ &proc, "files_history/current", file)) {
+ do {
+ update_file_on_refresh(proc, file, end);
+ } while (get_current_attribute_value_quark(
+ &file, "next", file));
+ }
+
+ /* compute the stream speed */
+ if (end - start != 0) {
+ time = end - start;
+ get_current_attribute_value_int(&proc, "fileread", fileread);
+ get_current_attribute_value_int(&proc, "filewrite", filewrite);
+ modify_attribute(end, &proc, "fileread", (int)(fileread / time));
+ modify_attribute(end, &proc, "filewrite", (int)(filewrite / time));
+ }
+}
+
+void modify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, int value)
+{
+ Quark q;
+ if (starting_node)
+ q = state_system->getQuark(*starting_node, attribute);
+ else
+ q = state_system->getQuark(attribute);
+ state_system->updateCurrentState(q, value);
+
+ modified_quarks.insert(q);
+}
+
+void modify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, Quark value)
+{
+ Quark q;
+ if (starting_node)
+ q = state_system->getQuark(*starting_node, attribute);
+ else
+ q = state_system->getQuark(attribute);
+ state_system->updateCurrentState(q, StateValue::SharedPtr(
+ new QuarkStateValue(value)));
+
+ modified_quarks.insert(q);
+}
+
+void modify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, char *value)
+{
+ Quark q;
+ if (starting_node)
+ q = state_system->getQuark(*starting_node, attribute);
+ else
+ q = state_system->getQuark(attribute);
+ state_system->updateCurrentState(q, std::string(value));
+
+ modified_quarks.insert(q);
+}
+
+void modify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, std::string value)
+{
+ Quark q;
+ if (starting_node)
+ q = state_system->getQuark(*starting_node, attribute);
+ else
+ q = state_system->getQuark(attribute);
+ state_system->updateCurrentState(q, value);
+
+ modified_quarks.insert(q);
+}
+
+void modify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, unsigned long value)
+{
+ // Libstate works with 32-bit ints, we split the 64-bit ulong
+ // into 2 32-bit ints
+ unsigned int h = value >> 32;
+ unsigned int l = value & 0xffffffff;
+ Quark ql, qh;
+
+ if (starting_node) {
+ ql = state_system->getQuark(*starting_node, attribute + "/l");
+ qh = state_system->getQuark(*starting_node, attribute + "/h");
+ }
+ else {
+ ql = state_system->getQuark(attribute + "/l");
+ qh = state_system->getQuark(attribute + "/h");
+ }
+ state_system->updateCurrentState(ql, l);
+ state_system->updateCurrentState(qh, h);
+
+ modified_quarks.insert(ql);
+ modified_quarks.insert(qh);
+}
+
+void nullify_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute)
+{
+ Quark q;
+ q = state_system->getQuark(*starting_node, attribute);
+ state_system->updateCurrentState(q, StateValue::getNullValue());
+
+ modified_quarks.insert(q);
+}
+
+void increment_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute)
+{
+ increase_attribute(timestamp, starting_node, attribute, 1);
+}
+
+void increase_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, int amount)
+{
+ int starting_value = 0;
+ get_current_attribute_value_int(starting_node, attribute,
+ starting_value);
+ modify_attribute(timestamp, starting_node, attribute,
+ starting_value + amount);
+}
+
+void increase_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, unsigned long amount)
+{
+ unsigned long starting_value = 0;
+ get_current_attribute_value_ulong(starting_node, attribute,
+ starting_value);
+ modify_attribute(timestamp, starting_node, attribute,
+ starting_value + amount);
+}
+
+void decrement_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute)
+{
+ decrease_attribute(timestamp, starting_node, attribute, 1);
+}
+
+void decrease_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, int amount)
+{
+ int starting_value = 0;
+ get_current_attribute_value_int(starting_node, attribute,
+ starting_value);
+ modify_attribute(timestamp, starting_node, attribute,
+ starting_value - amount);
+}
+
+void decrease_attribute(unsigned long timestamp, const Quark *starting_node,
+ std::string attribute, unsigned long amount)
+{
+ unsigned long starting_value = 0;
+ get_current_attribute_value_ulong(starting_node, attribute,
+ starting_value);
+ modify_attribute(timestamp, starting_node, attribute,
+ starting_value - amount);
+}
+
+bool get_current_attribute_value_int(const Quark *starting_node,
+ std::string attribute, int &value)
+{
+ IntegerStateValue::SharedPtr value_ptr;
+ Quark q;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ value_ptr = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ state_system->getCurrentStateValue(q));
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ }
+ return false;
+}
+
+bool get_current_attribute_value_ulong(const Quark *starting_node,
+ std::string attribute,
+ unsigned long &value)
+{
+ // Libstate works with 32-bit ints, we split the 64-bit ulong
+ // into 2 32-bit ints
+ IntegerStateValue::SharedPtr value_ptr_l, value_ptr_h;
+ Quark ql, qh;
+ unsigned int l, h;
+
+ if (starting_node == NULL) {
+ ql = state_system->getQuark(attribute + "/l");
+ qh = state_system->getQuark(attribute + "/h");
+ }
+ else {
+ ql = state_system->getQuark(*starting_node, attribute + "/l");
+ qh = state_system->getQuark(*starting_node, attribute + "/h");
+ }
+ value_ptr_l = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ state_system->getCurrentStateValue(ql));
+ value_ptr_h = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ state_system->getCurrentStateValue(qh));
+
+ if (value_ptr_l && value_ptr_h) {
+ l = value_ptr_l->getValue();
+ h = value_ptr_h->getValue();
+ value = (unsigned long)h << 32 | l;
+ return true;
+ }
+ return false;
+}
+
+bool get_current_attribute_value_quark(const Quark *starting_node,
+ std::string attribute, Quark &value)
+{
+ QuarkStateValue::SharedPtr value_ptr;
+ IntegerStateValue::SharedPtr value_ptr_int;
+ Quark q;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ value_ptr = std::tr1::dynamic_pointer_cast<QuarkStateValue>(
+ state_system->getCurrentStateValue(q));
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ } else {
+ /* Quark attribute support is not fully integrated in libstate
+ and librbrntrvll so quarks may get demoted to ints */
+ value_ptr_int = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ state_system->getCurrentStateValue(q));
+ if (value_ptr_int) {
+ value = (Quark)value_ptr_int->getValue();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool get_current_attribute_value_string(const Quark *starting_node,
+ std::string attribute, std::string &value)
+{
+ StringStateValue::SharedPtr value_ptr;
+ Quark q;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ value_ptr = std::tr1::dynamic_pointer_cast<StringStateValue>(
+ state_system->getCurrentStateValue(q));
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ }
+ return false;
+}
+
+bool get_attribute_value_at_int(unsigned long timestamp,
+ const Quark *starting_node,
+ std::string attribute,
+ int &value)
+{
+ StateInterval interval;
+ Quark q;
+ IntegerStateValue::SharedPtr value_ptr;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ interval = state_system->getStateOfAt(timestamp, q);
+ value_ptr = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ interval.value);
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ }
+ return false;
+}
+
+bool get_attribute_value_at_ulong(unsigned long timestamp,
+ const Quark *starting_node,
+ std::string attribute,
+ unsigned long &value)
+{
+ // Libstate works with 32-bit ints, we split the 64-bit ulong
+ // into 2 32-bit ints
+ StateInterval interval_l, interval_h;
+ Quark ql, qh;
+ IntegerStateValue::SharedPtr value_ptr_l, value_ptr_h;
+ unsigned int l, h;
+
+ if (starting_node == NULL) {
+ ql = state_system->getQuark(attribute + "/l");
+ qh = state_system->getQuark(attribute + "/h");
+ }
+ else {
+ ql = state_system->getQuark(*starting_node, attribute + "/l");
+ qh = state_system->getQuark(*starting_node, attribute + "/h");
+ }
+ interval_l = state_system->getStateOfAt(timestamp, ql);
+ interval_h = state_system->getStateOfAt(timestamp, qh);
+ value_ptr_l = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ interval_l.value);
+ value_ptr_h = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ interval_h.value);
+
+ if (value_ptr_l && value_ptr_h) {
+ l = value_ptr_l->getValue();
+ h = value_ptr_h->getValue();
+ value = (unsigned long)h << 32 | l;
+ return true;
+ }
+ return false;
+}
+
+bool get_attribute_value_at_quark(unsigned long timestamp,
+ const Quark *starting_node,
+ std::string attribute,
+ Quark &value)
+{
+ StateInterval interval;
+ Quark q;
+ QuarkStateValue::SharedPtr value_ptr;
+ IntegerStateValue::SharedPtr value_ptr_int;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ interval = state_system->getStateOfAt(timestamp, q);
+ value_ptr = std::tr1::dynamic_pointer_cast<QuarkStateValue>(
+ interval.value);
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ } else {
+ /* Quark attribute support is not fully integrated in libstate
+ and librbrntrvll so quarks may get demoted to ints */
+ value_ptr_int = std::tr1::dynamic_pointer_cast<IntegerStateValue>(
+ interval.value);
+ if (value_ptr_int) {
+ value = (Quark)value_ptr_int->getValue();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool get_attribute_value_at_string(unsigned long timestamp,
+ const Quark *starting_node,
+ std::string attribute,
+ std::string &value)
+{
+ StateInterval interval;
+ Quark q;
+ StringStateValue::SharedPtr value_ptr;
+
+ if (starting_node == NULL)
+ q = state_system->getQuark(attribute);
+ else
+ q = state_system->getQuark(*starting_node, attribute);
+ interval = state_system->getStateOfAt(timestamp, q);
+ value_ptr = std::tr1::dynamic_pointer_cast<StringStateValue>(
+ interval.value);
+
+ if (value_ptr) {
+ value = value_ptr->getValue();
+ return true;
+ }
+ return false;
+}
+
+void add_in_sequence(unsigned long timestamp, Quark item, Quark beg)
+{
+ Quark old_newest;
+ if (get_current_attribute_value_quark(&beg, "", old_newest)) {
+ modify_attribute(timestamp, &item, "next", old_newest);
+ modify_attribute(timestamp, &old_newest, "prev", item);
+ }
+ modify_attribute(timestamp, &beg, "", item);
+
+}
+
+void remove_from_sequence(unsigned long timestamp, Quark item, Quark beg)
+{
+ Quark prev;
+ Quark next;
+ bool hasPrev;
+ bool hasNext;
+
+ hasPrev = get_current_attribute_value_quark(&item,
+ "prev", prev);
+ hasNext = get_current_attribute_value_quark(&item,
+ "next", next);
+ if (hasPrev && hasNext) {
+ state_system->modifyAttribute(timestamp,
+ state_system->getQuark(next, "prev"),
+ StateValue::SharedPtr(
+ new QuarkStateValue(prev)));
+ state_system->modifyAttribute(timestamp,
+ state_system->getQuark(prev, "next"),
+ StateValue::SharedPtr(
+ new QuarkStateValue(next)));
+ } else if (hasPrev) {
+ state_system->modifyAttribute(timestamp,
+ state_system->getQuark(prev, "next"),
+ StateValue::getNullValue());
+ } else if (hasNext) {
+ state_system->modifyAttribute(timestamp,
+ state_system->getQuark(next, "prev"),
+ StateValue::getNullValue());
+ state_system->modifyAttribute(timestamp, beg,
+ StateValue::SharedPtr(
+ new QuarkStateValue(next)));
+ } else {
+ state_system->modifyAttribute(timestamp, beg,
+ StateValue::getNullValue());
+ }
+
+ state_system->removeAttribute(timestamp, item);
+}
+
+int get_sequence_length(unsigned long timestamp, Quark beg)
+{
+ int length = 0;
+ Quark it;
+
+ if (get_attribute_value_at_quark(timestamp, &beg, "", it)) {
+ do {
+ length++;
+ } while (get_attribute_value_at_quark(
+ timestamp, &it, "next", it));
+ }
+
+ return length;
+}
+
+bool get_interval_value_int(unsigned long start,
+ unsigned long end,
+ const Quark *starting_node,
+ std::string attribute,
+ int &value)
+{
+ int start_value, end_value;
+
+ if (get_attribute_value_at_int(
+ start, starting_node, attribute, start_value) &&
+ get_attribute_value_at_int(
+ end, starting_node, attribute, end_value)) {
+ value = end_value - start_value;
+ return true;
+ }
+ return false;
+}
+
+bool get_interval_value_ulong(unsigned long start,
+ unsigned long end,
+ const Quark *starting_node,
+ std::string attribute,
+ unsigned long &value)
+{
+ unsigned long start_value, end_value;
+
+ if (get_attribute_value_at_ulong(
+ start, starting_node, attribute, start_value) &&
+ get_attribute_value_at_ulong(
+ end, starting_node, attribute, end_value)) {
+ value = end_value - start_value;
+ return true;
+ }
+ return false;
+}
+
+int sequence_to_array(unsigned long timestamp, Quark beg, Quark *arr,
+ int len)
+{
+ int ret = 0;
+ Quark it;
+
+ if (arr == NULL || len < 1)
+ return 0;
+
+ if (get_attribute_value_at_quark(timestamp, &beg, "", it)) {
+ do {
+ arr[ret] = it;
+ ret++;
+ } while (get_attribute_value_at_quark(
+ timestamp, &it, "next", it) && ret < len);
+ }
+
+ return ret;
+}
+
+int get_global_perf_list(unsigned long timestamp, Quark *arr, int len)
+{
+ std::map<std::string, int> perfs;
+ std::string key;
+ int val;
+ int ret;
+ Quark proc;
+ Quark perf;
+ std::map<std::string, int>::const_iterator iter;
+
+ if (arr == NULL || len < 1)
+ return 0;
+
+ if (get_attribute_value_at_quark(timestamp, NULL, "proc", proc)) {
+ do {
+ if (get_attribute_value_at_quark(timestamp, &proc,
+ "perf", perf)) {
+ do {
+ get_attribute_value_at_string(timestamp,
+ &perf,
+ "key",
+ key);
+ get_attribute_value_at_int(timestamp,
+ &perf,
+ "count",
+ val);
+ if (perfs.find(key) != perfs.end())
+ perfs[key] += val;
+ else
+ perfs[key] = val;
+ } while (get_attribute_value_at_quark(timestamp,
+ &perf,
+ "next",
+ perf));
+ }
+ } while (get_attribute_value_at_quark(timestamp, &proc, "next",
+ proc));
+ }
+
+ for (iter = perfs.begin(), ret = 0; iter != perfs.end() && ret < len;
+ iter++, ret++) {
+ perf = state_system->getQuark("perf/" + iter->first);
+ modify_attribute(timestamp, &perf, "count", iter->second);
+ arr[ret] = perf;
+ }
+
+ return ret;
+}
+
+int get_global_perf_list_size(unsigned long timestamp)
+{
+ std::set<std::string> perfs;
+ std::string key;
+ int len = 0;
+ Quark proc;
+ Quark perf;
+
+ if (get_attribute_value_at_quark(timestamp, NULL, "proc", proc)) {
+ do {
+ if (get_attribute_value_at_quark(timestamp, &proc,
+ "perf", perf)) {
+ do {
+ get_attribute_value_at_string(timestamp,
+ &perf,
+ "key",
+ key);
+ if (perfs.find(key) == perfs.end()) {
+ perfs.insert(key);
+ len++;
+ }
+ } while (get_attribute_value_at_quark(timestamp,
+ &perf,
+ "next",
+ perf));
+ }
+ } while (get_attribute_value_at_quark(timestamp, &proc, "next",
+ proc));
+ }
+
+ return len;
+}
+
+int get_number_of_opened_files(unsigned long timestamp, Quark proc)
+{
+ int len = 0;
+ Quark fh;
+ int fd;
+
+ if (get_attribute_value_at_quark(timestamp, &proc,
+ "files_history/current", fh)) {
+ do {
+ get_attribute_value_at_int(timestamp, &fh, "file/fd",
+ fd);
+ if (fd != -1)
+ len++;
+ } while (get_attribute_value_at_quark(timestamp, &fh, "next",
+ fh));
+ }
+
+ return len;
+}
+
+int get_opened_files(unsigned long timestamp, Quark proc, Quark *arr, int len)
+{
+ int ret = 0;
+ Quark file, fh;
+ int fd;
+
+ if (arr == NULL || len < 1)
+ return 0;
+
+ if (get_attribute_value_at_quark(timestamp, &proc,
+ "files_history/current", fh)) {
+ do {
+ file = state_system->getQuark(fh, "file");
+ get_attribute_value_at_int(timestamp, &file, "fd",
+ fd);
+ if (fd != -1) {
+ arr[ret] = file;
+ ret++;
+ }
+ if (ret == len)
+ break;
+ } while (get_attribute_value_at_quark(timestamp, &fh, "next",
+ fh));
+ }
+
+ return ret;
+}