X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=src%2Fcommon.cpp;fp=src%2Fcommon.cpp;h=7ca08b48cd26c3b3d8e9c1420d2feb474cb33c55;hb=715cf83c121d2aeac7ae030d49ff5a31bd6b9ac5;hp=0000000000000000000000000000000000000000;hpb=62895477c7e60525e63e9e5117f92b34d467d0e6;p=lttngtop.git diff --git a/src/common.cpp b/src/common.cpp new file mode 100644 index 0000000..7ca08b4 --- /dev/null +++ b/src/common.cpp @@ -0,0 +1,1089 @@ +/* + * 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 +} +#include +#include +#include +#include "common.h" + +StateSystem *state_system; +std::set 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( + 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( + state_system->getCurrentStateValue(ql)); + value_ptr_h = std::tr1::dynamic_pointer_cast( + 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( + 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( + 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( + 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( + 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( + interval_l.value); + value_ptr_h = std::tr1::dynamic_pointer_cast( + 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( + 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( + 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( + 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 perfs; + std::string key; + int val; + int ret; + Quark proc; + Quark perf; + std::map::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 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; +}