aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYordan Karadzhov (VMware) <y.karadz@gmail.com>2021-02-11 12:31:44 +0200
committerYordan Karadzhov (VMware) <y.karadz@gmail.com>2021-02-16 10:25:14 +0200
commit8e4577299d5c733ce0df575cdf87ef065011fb50 (patch)
tree10a60ac331c49c7f020d175a6971d0a74fd16b40
parent7b8e70b1b1f128c59b735688833a829291de4337 (diff)
downloadkernel-shark-8e4577299d5c733ce0df575cdf87ef065011fb50.tar.gz
kernel-shark: Update KsUtils
The compilation of KsUtils is re-enabled and all functionalities provided in it are made compatible with the new version of the C API of libkshark (KernelShark 2.0). Link: https://lore.kernel.org/linux-trace-devel/20210211103205.418588-7-y.karadz@gmail.com Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
-rw-r--r--CMakeLists.txt10
-rw-r--r--build/deff.h.cmake3
-rw-r--r--src/CMakeLists.txt73
-rw-r--r--src/KsUtils.cpp1154
-rw-r--r--src/KsUtils.hpp181
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/libkshark-tests.cpp1
7 files changed, 969 insertions, 455 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd620915..e013916d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,12 +49,18 @@ set(OpenGL_GL_PREFERENCE LEGACY)
find_package(OpenGL)
find_package(GLUT)
-# find_package(Qt5Widgets 5.7.1)
-# find_package(Qt5Network)
+find_package(Qt5Widgets 5.7.1)
+find_package(Qt5Network)
if (Qt5Widgets_FOUND)
message(STATUS "Found Qt5Widgets: (version ${Qt5Widgets_VERSION})")
+ if(Qt5Widgets_VERSION VERSION_LESS "5.11")
+
+ set(QT_VERSION_LESS_5_11 TRUE)
+
+ endif()
+
endif (Qt5Widgets_FOUND)
find_package (Boost COMPONENTS unit_test_framework)
diff --git a/build/deff.h.cmake b/build/deff.h.cmake
index 868ffeca..5584574f 100644
--- a/build/deff.h.cmake
+++ b/build/deff.h.cmake
@@ -26,6 +26,9 @@
/** GLUT has been found. */
#cmakedefine GLUT_FOUND
+/** Qt - old version detected. */
+#cmakedefine QT_VERSION_LESS_5_11
+
/** Semicolon-separated list of plugin names. */
#define KS_BUILTIN_PLUGINS "@PLUGINS@"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 980e802a..5c9fe176 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -66,34 +66,34 @@ endif (OPENGL_FOUND)
if (Qt5Widgets_FOUND AND Qt5Network_FOUND)
message(STATUS "libkshark-gui")
- set (ks-guiLib_hdr KsUtils.hpp
- KsModels.hpp
- KsGLWidget.hpp
- KsSearchFSM.hpp
- KsDualMarker.hpp
- KsWidgetsLib.hpp
- KsTraceGraph.hpp
- KsTraceViewer.hpp
- KsMainWindow.hpp
- KsCaptureDialog.hpp
- KsQuickContextMenu.hpp
- KsAdvFilteringDialog.hpp)
+ set (ks-guiLib_hdr KsUtils.hpp)
+# KsModels.hpp
+# KsGLWidget.hpp
+# KsSearchFSM.hpp
+# KsDualMarker.hpp
+# KsWidgetsLib.hpp
+# KsTraceGraph.hpp
+# KsTraceViewer.hpp
+# KsMainWindow.hpp
+# KsCaptureDialog.hpp
+# KsQuickContextMenu.hpp
+# KsAdvFilteringDialog.hpp)
QT5_WRAP_CPP(ks-guiLib_hdr_moc ${ks-guiLib_hdr})
- add_library(kshark-gui SHARED ${ks-guiLib_hdr_moc} KsUtils.cpp
- KsModels.cpp
- KsSession.cpp
- KsGLWidget.cpp
- KsSearchFSM.cpp
- KsDualMarker.cpp
- KsWidgetsLib.cpp
- KsTraceGraph.cpp
- KsTraceViewer.cpp
- KsMainWindow.cpp
- KsCaptureDialog.cpp
- KsQuickContextMenu.cpp
- KsAdvFilteringDialog.cpp)
+ add_library(kshark-gui SHARED ${ks-guiLib_hdr_moc} KsUtils.cpp)
+# KsModels.cpp
+# KsSession.cpp
+# KsGLWidget.cpp
+# KsSearchFSM.cpp
+# KsDualMarker.cpp
+# KsWidgetsLib.cpp
+# KsTraceGraph.cpp
+# KsTraceViewer.cpp
+# KsMainWindow.cpp
+# KsCaptureDialog.cpp
+# KsQuickContextMenu.cpp
+# KsAdvFilteringDialog.cpp)
target_link_libraries(kshark-gui kshark-plot
Qt5::Widgets
@@ -102,19 +102,20 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND)
set_target_properties(kshark-gui PROPERTIES SUFFIX ".so.${KS_VERSION_STRING}")
- message(STATUS ${KS_APP_NAME})
- add_executable(${KS_APP_NAME} kernelshark.cpp)
- target_link_libraries(${KS_APP_NAME} kshark-gui)
+# message(STATUS ${KS_APP_NAME})
+# add_executable(${KS_APP_NAME} kernelshark.cpp)
+# target_link_libraries(${KS_APP_NAME} kshark-gui)
- message(STATUS "kshark-record")
- add_executable(kshark-record kshark-record.cpp)
- target_link_libraries(kshark-record kshark-gui)
+# message(STATUS "kshark-record")
+# add_executable(kshark-record kshark-record.cpp)
+# target_link_libraries(kshark-record kshark-gui)
+
+# install(TARGETS ${KS_APP_NAME} kshark-record kshark-gui
+# RUNTIME DESTINATION ${_INSTALL_PREFIX}/bin/
+# COMPONENT kernelshark
+# LIBRARY DESTINATION ${_LIBDIR}
+# COMPONENT kernelshark)
- install(TARGETS ${KS_APP_NAME} kshark-record kshark-gui
- RUNTIME DESTINATION ${_INSTALL_PREFIX}/bin/
- COMPONENT kernelshark
- LIBRARY DESTINATION ${_LIBDIR}
- COMPONENT kernelshark)
install(FILES "${KS_DIR}/${KS_APP_NAME}.desktop"
DESTINATION ${_INSTALL_PREFIX}/share/applications/
diff --git a/src/KsUtils.cpp b/src/KsUtils.cpp
index 24f7178a..36f9b256 100644
--- a/src/KsUtils.cpp
+++ b/src/KsUtils.cpp
@@ -10,90 +10,244 @@
*/
// KernelShark
+#include "libkshark-plugin.h"
+#include "libkshark-tepdata.h"
#include "KsUtils.hpp"
-#include "KsWidgetsLib.hpp"
namespace KsUtils {
-/** @brief Get a sorted vector of CPU Ids. */
-QVector<int> getCPUList()
+/**
+ * @brief Get a sorted vector of CPU Ids associated with a given Data stream.
+ *
+ * @param sd: Data stream identifier.
+ *
+ * @returns Vector of CPU Ids on success or an empty vector on failure.
+ */
+QVector<int> getCPUList(int sd)
{
kshark_context *kshark_ctx(nullptr);
- int nCPUs;
+ kshark_data_stream *stream;
if (!kshark_instance(&kshark_ctx))
return {};
- nCPUs = tep_get_cpus(kshark_ctx->pevent);
- QVector<int> allCPUs = QVector<int>(nCPUs);
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
+
+ QVector<int> allCPUs = QVector<int>(stream->n_cpus);
std::iota(allCPUs.begin(), allCPUs.end(), 0);
return allCPUs;
}
-/** @brief Get a sorted vector of Task's Pids. */
-QVector<int> getPidList()
+/**
+ * @brief Get a sorteg vector of Task's PIDs associated with a given Data
+ * stream.
+ *
+ * @param sd: Data stream identifier.
+ *
+ * @returns Vector of PIDs on success or an empty vector on failure.
+ */
+QVector<int> getPidList(int sd)
{
kshark_context *kshark_ctx(nullptr);
- int nTasks, *tempPids;
- QVector<int> pids;
+ int nTasks, *ids;
if (!kshark_instance(&kshark_ctx))
- return pids;
+ return {};
- nTasks = kshark_get_task_pids(kshark_ctx, &tempPids);
- for (int r = 0; r < nTasks; ++r) {
- pids.append(tempPids[r]);
- }
+ nTasks = kshark_get_task_pids(kshark_ctx, sd, &ids);
- free(tempPids);
+ QVector<int> pids(nTasks);
+ for (int i = 0; i < nTasks; ++i)
+ pids[i] = ids[i];
- std::sort(pids.begin(), pids.end());
+ free(ids);
return pids;
}
/**
- * @brief Get a sorted vector of Event Ids.
+ * @brief Get a vector of all Event Ids associated with a given Data stream.
+ *
+ * @param sd: Data stream identifier.
+ *
+ * @returns Vector of Event Ids on success or an empty vector on failure.
*/
-QVector<int> getEventIdList(tep_event_sort_type sortType)
+QVector<int> getEventIdList(int sd)
{
kshark_context *kshark_ctx(nullptr);
- tep_event **events;
- int nEvts;
+ kshark_data_stream *stream;
+ int *ids;
if (!kshark_instance(&kshark_ctx))
return {};
- nEvts = tep_get_events_count(kshark_ctx->pevent);
- events = tep_list_events(kshark_ctx->pevent, sortType);
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
+
+ ids = kshark_get_all_event_ids(stream);
+ if (!ids)
+ return {};
- QVector<int> allEvts(nEvts);
- for (int i = 0; i < nEvts; ++i)
- allEvts[i] = events[i]->id;
+ QVector<int> evts(stream->n_events);
+ for (int i = 0; i < stream->n_events; ++i)
+ evts[i] = ids[i];
- return allEvts;
+ free(ids);
+
+ return evts;
}
-/** @brief Get a sorted vector of Id values of a filter. */
-QVector<int> getFilterIds(tracecmd_filter_id *filter)
+/**
+ * @brief Retrieve the unique Id of the event.
+ *
+ * @param sd: Data stream identifier.
+ * @param eventName: The name of the event.
+ *
+ * @returns Event Id on success or a negative errno code on failure.
+ */
+int getEventId(int sd, const QString &eventName)
{
+ const std::string buff = eventName.toStdString();
kshark_context *kshark_ctx(nullptr);
- int *cpuFilter, n;
- QVector<int> v;
+ kshark_data_stream *stream;
if (!kshark_instance(&kshark_ctx))
- return v;
+ return -EFAULT;
+
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return -ENODEV;
+
+ return kshark_find_event_id(stream, buff.c_str());
+}
+
+static kshark_entry probeEntry(int sd, int eventId)
+{
+ kshark_entry e;
- cpuFilter = tracecmd_filter_ids(filter);
- n = filter->count;
+ e.stream_id = sd;
+ e.event_id = eventId;
+ e.visible = 0xff;
+
+ return e;
+}
+
+/**
+ * @brief Retrieve the name of the event.
+ *
+ * @param sd: Data stream identifier.
+ * @param eventId: The unique Id of the event.
+ *
+ * @returns Event name on success or "Unknown" on failure.
+ */
+QString getEventName(int sd, int eventId)
+{
+ kshark_entry entry = probeEntry(sd, eventId);
+ QString ret("Unknown");
+ char *event;
+
+ event = kshark_get_event_name(&entry);
+ if (event) {
+ ret = QString(event);
+ free(event);
+ }
+
+ return QString(ret);
+}
+
+/**
+ * @brief Get the namse of all data fields associated with a given trace event.
+ *
+ * @param sd: Data stream identifier.
+ * @param eventId: The unique Id of the event.
+ *
+ * @returns List of fieldsnames on success or an empty list on failure.
+ */
+QStringList getEventFieldsList(int sd, int eventId)
+{
+ kshark_entry entry = probeEntry(sd, eventId);
+ QStringList fieldList;
+ char **eventFields;
+ int nFields;
+
+ nFields = kshark_get_all_event_field_names(&entry, &eventFields);
+ if (nFields <= 0)
+ return {};
+
+ for (int i = 0; i < nFields; ++i) {
+ fieldList << eventFields[i];
+ free(eventFields[i]);
+ }
+
+ free(eventFields);
+
+ return fieldList;
+}
+
+/**
+ * @brief Retrieve the type of a given data field associatedwith a given trace
+ * event.
+ *
+ * @param sd: Data stream identifier.
+ * @param eventId: The unique Id of the event.
+ * @param fieldName: The name of the data field.
+ *
+ * @returns Field format identifier.
+ */
+kshark_event_field_format getEventFieldType(int sd, int eventId,
+ const QString &fieldName)
+{
+ const std::string buff = fieldName.toStdString();
+ kshark_entry entry = probeEntry(sd, eventId);
+
+ return kshark_get_event_field_type(&entry, buff.c_str());
+}
+
+/**
+ * @brief Get all Data stream Ids.
+ *
+ * @param kshark_ctx: Input location for context pointer.
+ *
+ * @returns Vector of Data stream Ids.
+ */
+QVector<int> getStreamIdList(kshark_context *kshark_ctx)
+{
+ int *ids = kshark_all_streams(kshark_ctx);
+ QVector<int> streamIds(kshark_ctx->n_streams);
+
+ for (int i = 0; i < kshark_ctx->n_streams; ++i)
+ streamIds[i] = ids[i];
+
+ free(ids);
+
+ return streamIds;
+}
+
+/**
+ * @brief Get a sorted vector of Id values of a filter.
+ *
+ * @param filter: Input location for the filter object.
+ */
+QVector<int> getFilterIds(kshark_hash_id *filter)
+{
+ kshark_context *kshark_ctx(nullptr);
+ int *ids, n = filter->count;
+
+ if (!kshark_instance(&kshark_ctx))
+ return {};
+
+ ids = kshark_hash_ids(filter);
+ QVector<int> filterIds(n);
for (int i = 0; i < n; ++i)
- v.append(cpuFilter[i]);
+ filterIds[i] = ids[i];
- std::sort(v.begin(), v.end());
+ free(ids);
- free(cpuFilter);
- return v;
+ return filterIds;
}
/**
@@ -134,7 +288,6 @@ void graphFilterSync(bool state)
}
}
-
/**
* @brief Add a checkbox to a menu.
*
@@ -164,15 +317,46 @@ QCheckBox *addCheckBoxToMenu(QMenu *menu, QString name)
*
* @param kshark_ctx: Input location for the session context pointer.
* @param e: kshark_entry to be checked.
+ * @param sd: Data stream identifier.
* @param cpu: Matching condition value.
*
* @returns True if the CPU of the entry matches the value of "cpu" and
* the entry is visibility in Graph. Otherwise false.
*/
bool matchCPUVisible(struct kshark_context *kshark_ctx,
- struct kshark_entry *e, int cpu)
+ struct kshark_entry *e, int sd, int *cpu)
{
- return (e->cpu == cpu && (e->visible & KS_GRAPH_VIEW_FILTER_MASK));
+ return (e->cpu == *cpu &&
+ e->stream_id == sd &&
+ (e->visible & KS_GRAPH_VIEW_FILTER_MASK));
+}
+
+/**
+ * @brief Get an elided version of the string that will fit within a label.
+ *
+ * @param label: Pointer to the label object.
+ * @param text: The text to be elided.
+ * @param mode: Parameter specifies whether the text is elided on the left,
+ * in the middle, or on the right.
+ * @param labelWidth: The desired width of the label.
+ */
+void setElidedText(QLabel* label, QString text,
+ enum Qt::TextElideMode mode,
+ int labelWidth)
+{
+ QFontMetrics metrix(label->font());
+ QString elidedText;
+ int textWidth;
+
+ textWidth = labelWidth - FONT_WIDTH * 3;
+ elidedText = metrix.elidedText(text, Qt::ElideRight, textWidth);
+
+ while(labelWidth < STRING_WIDTH(elidedText) + FONT_WIDTH * 5) {
+ textWidth -= FONT_WIDTH * 3;
+ elidedText = metrix.elidedText(text, mode, textWidth);
+ }
+
+ label->setText(elidedText);
}
/**
@@ -268,36 +452,8 @@ QStringList getFiles(QWidget *parent,
}
/**
- * @brief Open a standard Qt getFileName dialog and return the name of the
- * selected file. Only one file can be selected.
- */
-QString getSaveFile(QWidget *parent,
- const QString &windowName,
- const QString &filter,
- const QString &extension,
- QString &lastFilePath)
-{
- QString fileName = getFileDialog(parent,
- windowName,
- filter,
- lastFilePath,
- true);
-
- if (!fileName.isEmpty() && !fileName.endsWith(extension)) {
- fileName += extension;
-
- if (QFileInfo(fileName).exists()) {
- if (!KsWidgetsLib::fileExistsDialog(fileName))
- fileName.clear();
- }
- }
-
- return fileName;
-}
-
-/**
- * Separate the command line arguments inside the string taking into account
- * possible shell quoting and new lines.
+ * @brief Separate the command line arguments inside the string taking into
+ * account possible shell quoting and new lines.
*/
QStringList splitArguments(QString cmd)
{
@@ -336,7 +492,10 @@ QStringList splitArguments(QString cmd)
return argv;
}
-/** Parse a string containing Ids. The string can be of the form "1 4-7 9". */
+/**
+ * @brief Parse a string containing Ids. The string can be of the form
+ * "1,4-7,9".
+ */
QVector<int> parseIdList(QString v_str)
{
QStringList list = v_str.split(",", QString::SkipEmptyParts);
@@ -360,6 +519,63 @@ QVector<int> parseIdList(QString v_str)
return v;
}
+/**
+ * @brief Split the ststem name from the actual name of the event itself.
+ *
+ * @param sd: Data stream identifier.
+ * @param eventId: Identifier of the Event.
+ */
+QStringList getTepEvtName(int sd, int eventId)
+{
+ QString name(kshark_event_from_id(sd, eventId));
+
+ return name.split('/');
+}
+
+/**
+ * @brief Get a string to be used as a standard name of a task graph.
+ *
+ * @param sd: Graph's Data stream identifier.
+ * @param pid: Graph's progress Id.
+ */
+QString taskPlotName(int sd, int pid)
+{
+ kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
+ QString name;
+
+ if (!kshark_instance(&kshark_ctx))
+ return {};
+
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
+
+ name = kshark_comm_from_pid(sd, pid);
+ name += "-";
+ name += QString("%1").arg(pid);
+
+ return name;
+}
+
+/**
+ * @brief Get a description of the stream showing its data file and buffer
+ * name.
+ *
+ * @param stream: Input location for a Trace data stream pointer.
+ */
+QString streamDescription(kshark_data_stream *stream)
+{
+ QString descr(stream->file);
+ QString buffName(stream->name);
+ if (!buffName.isEmpty() && !kshark_tep_is_top_stream(stream)) {
+ descr += ":";
+ descr += stream->name;
+ }
+
+ return descr;
+}
+
}; // KsUtils
/** A stream operator for converting QColor into KsPlot::Color. */
@@ -370,10 +586,17 @@ KsPlot::Color& operator <<(KsPlot::Color &thisColor, const QColor &c)
return thisColor;
}
+/** A stream operator for converting KsPlot::Color into QColor. */
+QColor& operator <<(QColor &thisColor, const KsPlot::Color &c)
+{
+ thisColor.setRgb(c.r(), c.g(), c.b());
+
+ return thisColor;
+}
+
/** Create a default (empty) KsDataStore. */
KsDataStore::KsDataStore(QWidget *parent)
: QObject(parent),
- _tep(nullptr),
_rows(nullptr),
_dataSize(0)
{}
@@ -382,29 +605,127 @@ KsDataStore::KsDataStore(QWidget *parent)
KsDataStore::~KsDataStore()
{}
+int KsDataStore::_openDataFile(kshark_context *kshark_ctx,
+ const QString &file)
+{
+ int sd = kshark_open(kshark_ctx, file.toStdString().c_str());
+ if (sd < 0) {
+ qCritical() << "ERROR:" << sd << "while opening file " << file;
+ return sd;
+ }
+
+ if (kshark_is_tep(kshark_ctx->stream[sd])) {
+ kshark_tep_init_all_buffers(kshark_ctx, sd);
+ for (int i = 0; i < kshark_ctx->n_streams; ++i)
+ kshark_tep_handle_plugins(kshark_ctx, i);
+ }
+
+ return sd;
+}
+
+void KsDataStore::_addPluginsToStream(kshark_context *kshark_ctx, int sd,
+ QVector<kshark_dpi *> plugins)
+{
+ kshark_data_stream *stream;
+
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return;
+
+ for (auto const &p: plugins) {
+ struct kshark_dpi_list *plugin;
+
+ plugin = kshark_register_plugin_to_stream(stream, p, true);
+ kshark_handle_dpi(stream, plugin, KSHARK_PLUGIN_INIT);
+ }
+}
+
/** Load trace data for file. */
-void KsDataStore::loadDataFile(const QString &file)
+int KsDataStore::loadDataFile(const QString &file,
+ QVector<kshark_dpi *> plugins)
{
kshark_context *kshark_ctx(nullptr);
+ int i, sd, n_streams;
if (!kshark_instance(&kshark_ctx))
- return;
+ return -EFAULT;
clear();
- if (!kshark_open(kshark_ctx, file.toStdString().c_str())) {
- qCritical() << "ERROR Loading file " << file;
- return;
+ sd = _openDataFile(kshark_ctx, file);
+ if (sd != 0)
+ return sd;
+
+ /*
+ * The file may contain multiple buffers so we can have multiple
+ * streams loaded.
+ */
+ n_streams = kshark_ctx->n_streams;
+ for (i = 0; i < n_streams; ++i)
+ _addPluginsToStream(kshark_ctx, i, plugins);
+
+ _dataSize = kshark_load_all_entries(kshark_ctx, &_rows);
+ if (_dataSize <= 0) {
+ kshark_close_all(kshark_ctx);
+ return _dataSize;
}
- _tep = kshark_ctx->pevent;
+ registerCPUCollections();
- if (kshark_ctx->event_handlers == nullptr)
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_INIT);
- else
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_UPDATE);
+ return sd;
+}
+
+/**
+ * @brief Append a trace data file to the data-set that is already loaded.
+ * The clock of the new data will be calibrated in order to be
+ * compatible with the clock of the prior data.
+ *
+ * @param file: Trace data file, to be append to the already loaded data.
+ * @param offset: The offset in time of the Data stream to be appended.
+ */
+int KsDataStore::appendDataFile(const QString &file, int64_t offset)
+{
+ kshark_context *kshark_ctx(nullptr);
+ struct kshark_entry **mergedRows;
+ ssize_t nLoaded = _dataSize;
+ int i, sd;
+
+ if (!kshark_instance(&kshark_ctx))
+ return -EFAULT;
+
+ unregisterCPUCollections();
+
+ sd = _openDataFile(kshark_ctx, file);
+ if (sd < 0)
+ return sd;
+
+ for (i = sd; i < kshark_ctx->n_streams; ++i) {
+ kshark_ctx->stream[sd]->calib = kshark_offset_calib;
+ kshark_ctx->stream[sd]->calib_array =
+ (int64_t *) calloc(1, sizeof(int64_t));
+ kshark_ctx->stream[sd]->calib_array[0] = offset;
+ kshark_ctx->stream[sd]->calib_array_size = 1;
+ }
+
+ _dataSize = kshark_append_all_entries(kshark_ctx, _rows, nLoaded, sd,
+ &mergedRows);
+
+ if (_dataSize <= 0 || _dataSize == nLoaded) {
+ QErrorMessage *em = new QErrorMessage();
+ em->showMessage(QString("File %1 contains no data.").arg(file));
+ em->exec();
+
+ for (i = sd; i < kshark_ctx->n_streams; ++i)
+ kshark_close(kshark_ctx, i);
+
+ return _dataSize;
+ }
+
+ _rows = mergedRows;
+
+ registerCPUCollections();
- _dataSize = kshark_load_data_entries(kshark_ctx, &_rows);
+ return sd;
}
void KsDataStore::_freeData()
@@ -430,8 +751,14 @@ void KsDataStore::reload()
_freeData();
- _dataSize = kshark_load_data_entries(kshark_ctx, &_rows);
- _tep = kshark_ctx->pevent;
+ if (kshark_ctx->n_streams == 0)
+ return;
+
+ unregisterCPUCollections();
+
+ _dataSize = kshark_load_all_entries(kshark_ctx, &_rows);
+
+ registerCPUCollections();
emit updateWidgets(this);
}
@@ -441,11 +768,12 @@ void KsDataStore::clear()
{
kshark_context *kshark_ctx(nullptr);
- _freeData();
- _tep = nullptr;
+ if (!kshark_instance(&kshark_ctx))
+ return;
- if (kshark_instance(&kshark_ctx) && kshark_ctx->handle)
- kshark_close(kshark_ctx);
+ _freeData();
+ unregisterCPUCollections();
+ kshark_close_all(kshark_ctx);
}
/** Update the visibility of the entries (filter). */
@@ -456,93 +784,113 @@ void KsDataStore::update()
if (!kshark_instance(&kshark_ctx))
return;
- _unregisterCPUCollections();
+ unregisterCPUCollections();
- if (kshark_filter_is_set(kshark_ctx)) {
- kshark_filter_entries(kshark_ctx, _rows, _dataSize);
- emit updateWidgets(this);
- }
+ kshark_filter_all_entries(kshark_ctx, _rows, _dataSize);
registerCPUCollections();
+
+ emit updateWidgets(this);
}
/** Register a collection of visible entries for each CPU. */
void KsDataStore::registerCPUCollections()
{
kshark_context *kshark_ctx(nullptr);
+ int *streamIds, nCPUs, sd;
- if (!kshark_instance(&kshark_ctx) ||
- !kshark_filter_is_set(kshark_ctx))
+ if (!kshark_instance(&kshark_ctx))
return;
- int nCPUs = tep_get_cpus(_tep);
- for (int cpu = 0; cpu < nCPUs; ++cpu) {
- kshark_register_data_collection(kshark_ctx,
- _rows, _dataSize,
- KsUtils::matchCPUVisible,
- cpu,
- 0);
+ streamIds = kshark_all_streams(kshark_ctx);
+ for (int i = 0; i < kshark_ctx->n_streams; ++i) {
+ sd = streamIds[i];
+
+ nCPUs = kshark_ctx->stream[sd]->n_cpus;
+ for (int cpu = 0; cpu < nCPUs; ++cpu) {
+ kshark_register_data_collection(kshark_ctx,
+ _rows, _dataSize,
+ KsUtils::matchCPUVisible,
+ sd, &cpu, 1,
+ 0);
+ }
}
+
+ free(streamIds);
}
-void KsDataStore::_unregisterCPUCollections()
+/** Unregister all CPU collections. */
+void KsDataStore::unregisterCPUCollections()
{
kshark_context *kshark_ctx(nullptr);
+ int *streamIds, nCPUs, sd;
if (!kshark_instance(&kshark_ctx))
return;
- int nCPUs = tep_get_cpus(_tep);
- for (int cpu = 0; cpu < nCPUs; ++cpu) {
- kshark_unregister_data_collection(&kshark_ctx->collections,
- KsUtils::matchCPUVisible,
- cpu);
+ streamIds = kshark_all_streams(kshark_ctx);
+ for (int i = 0; i < kshark_ctx->n_streams; ++i) {
+ sd = streamIds[i];
+
+ nCPUs = kshark_ctx->stream[sd]->n_cpus;
+ for (int cpu = 0; cpu < nCPUs; ++cpu) {
+ kshark_unregister_data_collection(&kshark_ctx->collections,
+ KsUtils::matchCPUVisible,
+ sd, &cpu, 1);
+ }
}
+
+ free(streamIds);
}
-void KsDataStore::_applyIdFilter(int filterId, QVector<int> vec)
+void KsDataStore::_applyIdFilter(int filterId, QVector<int> vec, int sd)
{
kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
if (!kshark_instance(&kshark_ctx))
return;
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return;
+
switch (filterId) {
case KS_SHOW_EVENT_FILTER:
case KS_HIDE_EVENT_FILTER:
- kshark_filter_clear(kshark_ctx, KS_SHOW_EVENT_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_EVENT_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_EVENT_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_EVENT_FILTER);
break;
case KS_SHOW_TASK_FILTER:
case KS_HIDE_TASK_FILTER:
- kshark_filter_clear(kshark_ctx, KS_SHOW_TASK_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_TASK_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_TASK_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_TASK_FILTER);
break;
case KS_SHOW_CPU_FILTER:
case KS_HIDE_CPU_FILTER:
- kshark_filter_clear(kshark_ctx, KS_SHOW_CPU_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_CPU_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_CPU_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_CPU_FILTER);
break;
default:
return;
}
for (auto &&val: vec)
- kshark_filter_add_id(kshark_ctx, filterId, val);
+ kshark_filter_add_id(kshark_ctx, sd, filterId, val);
- if (!_tep)
+ if (!kshark_ctx->n_streams)
return;
- _unregisterCPUCollections();
+ unregisterCPUCollections();
/*
- * If the advanced event filter is set, the data has to be reloaded,
+ * If the advanced event filter is set the data has to be reloaded,
* because the advanced filter uses tep_records.
*/
- if (kshark_ctx->advanced_event_filter->filters)
+ if (kshark_is_tep(stream) && kshark_tep_filter_is_set(stream))
reload();
else
- kshark_filter_entries(kshark_ctx, _rows, _dataSize);
+ kshark_filter_stream_entries(kshark_ctx, sd, _rows, _dataSize);
registerCPUCollections();
@@ -550,381 +898,475 @@ void KsDataStore::_applyIdFilter(int filterId, QVector<int> vec)
}
/** Apply Show Task filter. */
-void KsDataStore::applyPosTaskFilter(QVector<int> vec)
+void KsDataStore::applyPosTaskFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_SHOW_TASK_FILTER, vec);
+ _applyIdFilter(KS_SHOW_TASK_FILTER, vec, sd);
}
/** Apply Hide Task filter. */
-void KsDataStore::applyNegTaskFilter(QVector<int> vec)
+void KsDataStore::applyNegTaskFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_HIDE_TASK_FILTER, vec);
+ _applyIdFilter(KS_HIDE_TASK_FILTER, vec, sd);
}
/** Apply Show Event filter. */
-void KsDataStore::applyPosEventFilter(QVector<int> vec)
+void KsDataStore::applyPosEventFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_SHOW_EVENT_FILTER, vec);
+ _applyIdFilter(KS_SHOW_EVENT_FILTER, vec, sd);
}
/** Apply Hide Event filter. */
-void KsDataStore::applyNegEventFilter(QVector<int> vec)
+void KsDataStore::applyNegEventFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_HIDE_EVENT_FILTER, vec);
+ _applyIdFilter(KS_HIDE_EVENT_FILTER, vec, sd);
}
/** Apply Show CPU filter. */
-void KsDataStore::applyPosCPUFilter(QVector<int> vec)
+void KsDataStore::applyPosCPUFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_SHOW_CPU_FILTER, vec);
+ _applyIdFilter(KS_SHOW_CPU_FILTER, vec, sd);
}
/** Apply Hide CPU filter. */
-void KsDataStore::applyNegCPUFilter(QVector<int> vec)
+void KsDataStore::applyNegCPUFilter(int sd, QVector<int> vec)
{
- _applyIdFilter(KS_HIDE_CPU_FILTER, vec);
+ _applyIdFilter(KS_HIDE_CPU_FILTER, vec, sd);
}
/** Disable all filters. */
void KsDataStore::clearAllFilters()
{
kshark_context *kshark_ctx(nullptr);
+ int *streamIds, sd;
- if (!kshark_instance(&kshark_ctx) || !_tep)
+ if (!kshark_instance(&kshark_ctx) || !kshark_ctx->n_streams)
return;
- _unregisterCPUCollections();
+ unregisterCPUCollections();
+
+ streamIds = kshark_all_streams(kshark_ctx);
+ for (int i = 0; i < kshark_ctx->n_streams; ++i) {
+ sd = streamIds[i];
+
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_TASK_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_TASK_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_EVENT_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_EVENT_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_SHOW_CPU_FILTER);
+ kshark_filter_clear(kshark_ctx, sd, KS_HIDE_CPU_FILTER);
+
+ if (kshark_is_tep(kshark_ctx->stream[sd]))
+ kshark_tep_filter_reset(kshark_ctx->stream[sd]);
+ }
- kshark_filter_clear(kshark_ctx, KS_SHOW_TASK_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_TASK_FILTER);
- kshark_filter_clear(kshark_ctx, KS_SHOW_EVENT_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_EVENT_FILTER);
- kshark_filter_clear(kshark_ctx, KS_SHOW_CPU_FILTER);
- kshark_filter_clear(kshark_ctx, KS_HIDE_CPU_FILTER);
+ free(streamIds);
- tep_filter_reset(kshark_ctx->advanced_event_filter);
kshark_clear_all_filters(kshark_ctx, _rows, _dataSize);
+ registerCPUCollections();
emit updateWidgets(this);
}
/**
- * @brief Create Plugin Manager. Use list of plugins declared in the
- * CMake-generated header file.
+ * @brief Apply constant offset to the timestamps of all entries from a given
+ * Data stream.
+ *
+ * @param sd: Data stream identifier.
+ * @param offset: The constant offset to be added (in nanosecond).
*/
-KsPluginManager::KsPluginManager(QWidget *parent)
-: QObject(parent)
+void KsDataStore::setClockOffset(int sd, int64_t offset)
{
kshark_context *kshark_ctx(nullptr);
- _parsePluginList();
if (!kshark_instance(&kshark_ctx))
return;
- registerFromList(kshark_ctx);
+ if (!kshark_get_data_stream(kshark_ctx, sd))
+ return;
+
+ unregisterCPUCollections();
+ kshark_set_clock_offset(kshark_ctx, _rows, _dataSize, sd, offset);
+ registerCPUCollections();
}
-/** Parse the plugin list declared in the CMake-generated header file. */
-void KsPluginManager::_parsePluginList()
+/**
+ * @brief Create Plugin Manager. Use the list of plugins declared in the
+ * CMake-generated header file.
+ */
+KsPluginManager::KsPluginManager(QWidget *parent)
+: QObject(parent)
{
- _ksPluginList = KsUtils::getPluginList();
- int nPlugins = _ksPluginList.count();
+ _loadPluginList(KsUtils::getPluginList());
+}
- _registeredKsPlugins.resize(nPlugins);
+QVector<kshark_plugin_list *>
+KsPluginManager::_loadPluginList(const QStringList &plugins)
+{
+ kshark_context *kshark_ctx(nullptr);
+ QVector<kshark_plugin_list *> vec;
+ kshark_plugin_list *plugin;
+ std::string name, lib;
+ int nPlugins;
+
+ if (!kshark_instance(&kshark_ctx))
+ return vec;
+
+ nPlugins = plugins.count();
for (int i = 0; i < nPlugins; ++i) {
- if (_ksPluginList[i].contains(" default", Qt::CaseInsensitive)) {
- _ksPluginList[i].remove(" default", Qt::CaseInsensitive);
- _registeredKsPlugins[i] = true;
+ if (plugins[i].endsWith(".so")) {
+ lib = plugins[i].toStdString();
+ name = _pluginNameFromLib(plugins[i]);
} else {
- _registeredKsPlugins[i] = false;
+ lib = _pluginLibFromName(plugins[i]);
+ name = plugins[i].toStdString();
+ }
+
+ plugin = kshark_find_plugin(kshark_ctx->plugins,
+ lib.c_str());
+
+ if (!plugin) {
+ plugin = kshark_register_plugin(kshark_ctx,
+ name.c_str(),
+ lib.c_str());
+
+ if (plugin)
+ vec.append(plugin);
}
}
+
+ return vec;
}
/**
- * Register the plugins by using the information in "_ksPluginList" and
- * "_registeredKsPlugins".
+ * @brief Get a list of all plugins registered to a given Data stream.
+ *
+ * @param sd: Data stream identifier.
+ * @return List of plugin names.
*/
-void KsPluginManager::registerFromList(kshark_context *kshark_ctx)
+QStringList KsPluginManager::getStreamPluginList(int sd) const
{
- auto lamRegBuiltIn = [&kshark_ctx, this](const QString &plugin)
- {
- char *lib;
- int n;
-
- lib = _pluginLibFromName(plugin, n);
- if (n <= 0)
- return;
+ kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
+ kshark_dpi_list *plugin;
+ QStringList list;
- kshark_register_plugin(kshark_ctx, lib);
- free(lib);
- };
+ if (!kshark_instance(&kshark_ctx))
+ return {};
- auto lamRegUser = [&kshark_ctx](const QString &plugin)
- {
- std::string lib = plugin.toStdString();
- kshark_register_plugin(kshark_ctx, lib.c_str());
- };
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
- _forEachInList(_ksPluginList,
- _registeredKsPlugins,
- lamRegBuiltIn);
+ plugin = stream->plugins;
+ while (plugin) {
+ list.append(plugin->interface->name);
+ plugin = plugin->next;
+ }
- _forEachInList(_userPluginList,
- _registeredUserPlugins,
- lamRegUser);
+ return list;
}
/**
- * Unegister the plugins by using the information in "_ksPluginList" and
- * "_registeredKsPlugins".
+ * @brief Get a list of all plugins registered to a given Data stream.
+ *
+ * @param sd: Data stream identifier.
*/
-void KsPluginManager::unregisterFromList(kshark_context *kshark_ctx)
+QVector<int> KsPluginManager::getActivePlugins(int sd) const
{
- auto lamUregBuiltIn = [&kshark_ctx, this](const QString &plugin)
- {
- char *lib;
- int n;
+ kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
+ kshark_dpi_list *plugin;
+ QVector<int> vec;
+ int i(0);
- lib = _pluginLibFromName(plugin, n);
- if (n <= 0)
- return;
+ if (!kshark_instance(&kshark_ctx))
+ return {};
- kshark_unregister_plugin(kshark_ctx, lib);
- free(lib);
- };
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
- auto lamUregUser = [&kshark_ctx](const QString &plugin)
- {
- std::string lib = plugin.toStdString();
- kshark_unregister_plugin(kshark_ctx, lib.c_str());
- };
+ plugin = stream->plugins;
- _forEachInList(_ksPluginList,
- _registeredKsPlugins,
- lamUregBuiltIn);
+ while (plugin) {
+ vec.append(plugin->status & KSHARK_PLUGIN_ENABLED);
+ plugin = plugin->next;
+ i++;
+ }
- _forEachInList(_userPluginList,
- _registeredUserPlugins,
- lamUregUser);
+ return vec;
}
-char *KsPluginManager::_pluginLibFromName(const QString &plugin, int &n)
+/**
+ * @brief Get the indexes of all plugins registered to a given stream and
+ * having given status.
+ */
+QVector<int> KsPluginManager::getPluginsByStatus(int sd, int status) const
{
- QString appPath = QCoreApplication::applicationDirPath();
- QString libPath = appPath + "/../../kernel-shark/lib";
- std::string pluginStr = plugin.toStdString();
- char *lib;
+ kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
+ kshark_dpi_list *plugin;
+ QVector<int> vec;
+ int i(0);
- libPath = QDir::cleanPath(libPath);
- if (!KsUtils::isInstalled() && QDir(libPath).exists()) {
- std::string pathStr = libPath.toStdString();
- n = asprintf(&lib, "%s/plugin-%s.so",
- pathStr.c_str(), pluginStr.c_str());
- } else {
- n = asprintf(&lib, "%s/plugin-%s.so",
- KS_PLUGIN_INSTALL_PREFIX, pluginStr.c_str());
+ if (!kshark_instance(&kshark_ctx))
+ return {};
+
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return {};
+
+ plugin = stream->plugins;
+
+ while (plugin) {
+ if (plugin->status & status)
+ vec.append(i);
+
+ plugin = plugin->next;
+ i++;
}
- return lib;
+ return vec;
}
/**
- * @brief Register a Plugin.
- *
- * @param plugin: provide here the name of the plugin (as in the CMake-generated
- * header file) of a name of the plugin's library file (.so).
+ * @brief Loop over the registered plugins and register all plugin-defined
+ * menus (if any).
*/
-void KsPluginManager::registerPlugin(const QString &plugin)
+void KsPluginManager::registerPluginMenues()
{
kshark_context *kshark_ctx(nullptr);
- char *lib;
- int n;
+ kshark_plugin_list *plugin;
if (!kshark_instance(&kshark_ctx))
return;
- for (int i = 0; i < _ksPluginList.count(); ++i) {
- if (_ksPluginList[i] == plugin) {
- /*
- * The argument is the name of the plugin. From the
- * name get the library .so file.
- */
- lib = _pluginLibFromName(plugin, n);
- if (n > 0) {
- kshark_register_plugin(kshark_ctx, lib);
- _registeredKsPlugins[i] = true;
- free(lib);
+ for (plugin = kshark_ctx->plugins; plugin; plugin = plugin->next)
+ if (plugin->handle && plugin->ctrl_interface) {
+ void *dialogPtr = plugin->ctrl_interface(parent());
+ if (dialogPtr) {
+ QWidget *dialog =
+ static_cast<QWidget *>(dialogPtr);
+ _pluginDialogs.append(dialog);
}
+ }
+}
- return;
+std::string KsPluginManager::_pluginLibFromName(const QString &plugin)
+{
+ QString appPath = QCoreApplication::applicationDirPath();
+ QString libPath = appPath + "/../lib";
+ std::string lib;
- } else if (plugin.contains("/lib/plugin-" + _ksPluginList[i],
- Qt::CaseInsensitive)) {
- /*
- * The argument is the name of the library .so file.
- */
- n = asprintf(&lib, "%s", plugin.toStdString().c_str());
- if (n > 0) {
- kshark_register_plugin(kshark_ctx, lib);
- _registeredKsPlugins[i] = true;
- free(lib);
- }
+ auto lamFileName = [&] () {
+ return std::string("/plugin-" + plugin.toStdString() + ".so");
+ };
- return;
- }
- }
+ libPath = QDir::cleanPath(libPath);
+ if (!KsUtils::isInstalled() && QDir(libPath).exists())
+ lib = libPath.toStdString() + lamFileName();
+ else
+ lib = std::string(KS_PLUGIN_INSTALL_PREFIX) + lamFileName();
- /* No plugin with this name in the list. Try to add it anyway. */
- if (plugin.endsWith(".so") && QFileInfo::exists(plugin)) {
- kshark_register_plugin(kshark_ctx,
- plugin.toStdString().c_str());
+ return lib;
+}
- _userPluginList.append(plugin);
- _registeredUserPlugins.append(true);
- } else {
- qCritical() << "ERROR: " << plugin << "cannot be registered!";
- }
+std::string KsPluginManager::_pluginNameFromLib(const QString &plugin)
+{
+ QString name = plugin.section('/', -1);
+ name.remove("plugin-");
+ name.remove(".so");
+
+ return name.toStdString();
}
-/** @brief Unregister a Built in KernelShark plugin.
- *<br>
- * WARNING: Do not use this function to unregister User plugins.
- * Instead use directly kshark_unregister_plugin().
+/**
+ * @brief Register a list pf plugins
*
- * @param plugin: provide here the name of the plugin (as in the CMake-generated
- * header file) or a name of the plugin's library file (.so).
+ * @param pluginNames: Provide here the names of the plugin (as in the
+ * CMake-generated header file) or the names of the
+ * plugin's library files (.so including path).
+ * The names must be comma separated.
+ */
+void KsPluginManager::registerPlugins(const QString &pluginNames)
+{
+ _userPlugins.append(_loadPluginList(pluginNames.split(',')));
+}
+
+/**
+ * @brief Unregister a list pf plugins.
*
+ * @param pluginNames: Provide here a comma separated list of plugin names (as
+ * in the CMake-generated header file).
*/
-void KsPluginManager::unregisterPlugin(const QString &plugin)
+void KsPluginManager::unregisterPlugins(const QString &pluginNames)
{
kshark_context *kshark_ctx(nullptr);
- char *lib;
- int n;
+ kshark_plugin_list *plugin;
+ kshark_data_stream *stream;
+ int *streamArray;
if (!kshark_instance(&kshark_ctx))
return;
- for (int i = 0; i < _ksPluginList.count(); ++i) {
- if (_ksPluginList[i] == plugin) {
- /*
- * The argument is the name of the plugin. From the
- * name get the library .so file.
- */
- lib = _pluginLibFromName(plugin, n);
- if (n > 0) {
- kshark_unregister_plugin(kshark_ctx, lib);
- _registeredKsPlugins[i] = false;
- free(lib);
- }
-
- return;
- } else if (plugin.contains("/lib/plugin-" +
- _ksPluginList[i], Qt::CaseInsensitive)) {
- /*
- * The argument is the name of the library .so file.
- */
- n = asprintf(&lib, "%s", plugin.toStdString().c_str());
- if (n > 0) {
- kshark_unregister_plugin(kshark_ctx, lib);
- _registeredKsPlugins[i] = false;
- free(lib);
- }
+ for (auto const &name: pluginNames.split(',')) {
+ plugin = kshark_find_plugin_by_name(kshark_ctx->plugins,
+ name.toStdString().c_str());
- return;
+ streamArray = kshark_all_streams(kshark_ctx);
+ for (int i = 0; i < kshark_ctx->n_streams; ++i) {
+ stream = kshark_get_data_stream(kshark_ctx,
+ streamArray[i]);
+ kshark_unregister_plugin_from_stream(stream,
+ plugin->process_interface);
}
+
+ kshark_unregister_plugin(kshark_ctx,
+ name.toStdString().c_str(),
+ plugin->file);
}
}
-/** @brief Add to the list and initialize user-provided plugins. All other
- * previously loaded plugins will be reinitialized and the data will be
- * reloaded.
- *
- * @param fileNames: the library files (.so) of the plugins.
-*/
-void KsPluginManager::addPlugins(const QStringList &fileNames)
+void KsPluginManager::_pluginToStream(const QString &pluginName,
+ QVector<int> streamIds,
+ bool reg)
{
kshark_context *kshark_ctx(nullptr);
+ kshark_plugin_list *plugin;
+ kshark_data_stream *stream;
if (!kshark_instance(&kshark_ctx))
return;
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_CLOSE);
+ plugin = kshark_find_plugin_by_name(kshark_ctx->plugins,
+ pluginName.toStdString().c_str());
- for (auto const &p: fileNames)
- registerPlugin(p);
+ if (!plugin || !plugin->process_interface)
+ return;
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_INIT);
+ for (auto const &sd: streamIds) {
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ continue;
+
+ if (reg)
+ kshark_register_plugin_to_stream(stream,
+ plugin->process_interface,
+ true);
+ else
+ kshark_unregister_plugin_from_stream(stream,
+ plugin->process_interface);
+
+ kshark_handle_all_dpis(stream, KSHARK_PLUGIN_UPDATE);
+ }
emit dataReload();
}
-/** Unload all plugins. */
-void KsPluginManager::unloadAll()
+/**
+ * @brief Register a given plugin to given Data streams.
+ *
+ * @param pluginName: The name of the plugin to register.
+ * @param streamIds: Vector of Data stream identifiers.
+ */
+void KsPluginManager::registerPluginToStream(const QString &pluginName,
+ QVector<int> streamIds)
+{
+ _pluginToStream(pluginName, streamIds, true);
+}
+
+/**
+ * @brief Unregister a given plugin from given Data streams.
+ *
+ * @param pluginName: The name of the plugin to unregister.
+ * @param streamIds: Vector of Data stream identifiers.
+ */
+void KsPluginManager::unregisterPluginFromStream(const QString &pluginName,
+ QVector<int> streamIds)
+{
+ _pluginToStream(pluginName, streamIds, false);
+}
+
+/** @brief Add to the list and initialize user-provided plugins. All other
+ * previously loaded plugins will be reinitialized and the data will be
+ * reloaded.
+ *
+ * @param fileNames: The library files (.so) of the plugins.
+ * @param streamIds: Vector of Data stream identifiers. If the vector is empty
+ * the plugins will be registered to all Data streams.
+ * Otherwise the plugins will be registered to the listed
+ * streams.
+*/
+void KsPluginManager::addPlugins(const QStringList &fileNames,
+ QVector<int> streamIds)
{
+ QVector<kshark_plugin_list *> plugins;
kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
if (!kshark_instance(&kshark_ctx))
return;
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_CLOSE);
- kshark_free_plugin_list(kshark_ctx->plugins);
- kshark_ctx->plugins = nullptr;
- kshark_free_event_handler_list(kshark_ctx->event_handlers);
+ plugins = _loadPluginList(fileNames);
+ _userPlugins.append(plugins);
- unregisterFromList(kshark_ctx);
+ if (streamIds.isEmpty())
+ streamIds = KsUtils::getStreamIdList(kshark_ctx);
+
+ for (auto const &sd: streamIds) {
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+
+ for (auto const &p: plugins) {
+ if (p->process_interface)
+ kshark_register_plugin_to_stream(stream,
+ p->process_interface,
+ true);
+ }
+
+ kshark_handle_all_dpis(stream, KSHARK_PLUGIN_UPDATE);
+ }
}
-/** @brief Update (change) the Plugins.
+/** @brief Update (change) the plugins for a given Data stream.
*
- * @param pluginIds: The indexes of the plugins to be loaded.
+ * @param sd: Data stream identifier.
+ * @param pluginStates: A vector of plugin's states (0 or 1) telling which
+ * plugins to be loaded.
*/
-void KsPluginManager::updatePlugins(QVector<int> pluginIds)
+void KsPluginManager::updatePlugins(int sd, QVector<int> pluginStates)
{
kshark_context *kshark_ctx(nullptr);
+ kshark_data_stream *stream;
+ kshark_dpi_list *plugin;
+ QVector<int> vec;
+ int i(0);
if (!kshark_instance(&kshark_ctx))
return;
- auto register_plugins = [&] (QVector<int> ids)
- {
- int nKsPlugins = _registeredKsPlugins.count();
-
- /* First clear all registered plugins. */
- for (auto &p: _registeredKsPlugins)
- p = false;
- for (auto &p: _registeredUserPlugins)
- p = false;
-
- /* The vector contains the indexes of those to register. */
- for (auto const &p: ids) {
- if (p < nKsPlugins)
- _registeredKsPlugins[p] = true;
- else
- _registeredUserPlugins[p - nKsPlugins] = true;
- }
- registerFromList(kshark_ctx);
- };
+ stream = kshark_get_data_stream(kshark_ctx, sd);
+ if (!stream)
+ return;
- if (!kshark_ctx->pevent) {
- kshark_free_plugin_list(kshark_ctx->plugins);
- kshark_ctx->plugins = nullptr;
+ plugin = stream->plugins;
+ while (plugin) {
+ if (pluginStates[i++])
+ plugin->status |= KSHARK_PLUGIN_ENABLED;
+ else
+ plugin->status &= ~KSHARK_PLUGIN_ENABLED;
- /*
- * No data is loaded. For the moment, just register the
- * plugins. Handling of the plugins will be done after
- * we load a data file.
- */
- register_plugins(pluginIds);
- return;
+ plugin = plugin->next;
}
- /* Clean up all old plugins first. */
- unloadAll();
-
- /* Now load. */
- register_plugins(pluginIds);
- kshark_handle_plugins(kshark_ctx, KSHARK_PLUGIN_INIT);
+ kshark_handle_all_dpis(stream, KSHARK_PLUGIN_UPDATE);
+}
- emit dataReload();
+/**
+ * @brief Destroy all Plugin dialogs.
+ */
+void KsPluginManager::deletePluginDialogs()
+{
+ /** Delete all register plugin dialogs. */
+ for (auto &pd: _pluginDialogs)
+ delete pd;
}
diff --git a/src/KsUtils.hpp b/src/KsUtils.hpp
index 2772b84e..0d2c9c33 100644
--- a/src/KsUtils.hpp
+++ b/src/KsUtils.hpp
@@ -45,7 +45,15 @@ static auto stringWidth = [](QString s)
QFont font;
QFontMetrics fm(font);
+#ifdef QT_VERSION_LESS_5_11
+
+ return fm.width(s);
+
+#else
+
return fm.horizontalAdvance(s);
+
+#endif // QT_VERSION_LESS_5_11
};
//! @endcond
@@ -54,13 +62,13 @@ static auto stringWidth = [](QString s)
#define FONT_HEIGHT fontHeight()
/** Macro providing the width of the font in pixels. */
-#define FONT_WIDTH stringWidth("4")
+#define FONT_WIDTH (stringWidth("KernelShark") / 11)
/** Macro providing the width of a string in pixels. */
#define STRING_WIDTH(s) stringWidth(s)
/** Macro providing the height of the KernelShark graphs in pixels. */
-#define KS_GRAPH_HEIGHT (FONT_HEIGHT*2)
+#define KS_GRAPH_HEIGHT (FONT_HEIGHT * 2)
//! @cond Doxygen_Suppress
@@ -82,16 +90,27 @@ std::chrono::high_resolution_clock::now() - t0).count()
namespace KsUtils {
-QVector<int> getCPUList();
+QVector<int> getCPUList(int sd);
+
+QVector<int> getPidList(int sd);
+
+QVector<int> getEventIdList(int sd);
+
+int getEventId(int sd, const QString &eventName);
+
+QString getEventName(int sd, int eventId);
+
+QStringList getEventFieldsList(int sd, int eventId);
-QVector<int> getPidList();
+kshark_event_field_format getEventFieldType(int sd, int eventId,
+ const QString &fieldName);
-QVector<int> getEventIdList(tep_event_sort_type sortType=TEP_EVENT_SORT_ID);
+QVector<int> getStreamIdList(kshark_context *kshark_ctx);
-QVector<int> getFilterIds(tracecmd_filter_id *filter);
+QVector<int> getFilterIds(kshark_hash_id *filter);
-/** @brief Geat the list of plugins. */
-inline QStringList getPluginList() {return plugins.split(";");}
+/** @brief Geat the list of plugins provided by the package. */
+inline QStringList getPluginList() {return QString(KS_BUILTIN_PLUGINS).split(";");}
void listFilterSync(bool state);
@@ -113,8 +132,8 @@ inline QString Ts2String(int64_t ts, int prec)
return QString::number(ts * 1e-9, 'f', prec);
}
-bool matchCPUVisible(struct kshark_context *kshark_ctx,
- struct kshark_entry *e, int cpu);
+bool matchCPUVisible(kshark_context *kshark_ctx,
+ kshark_entry *e, int sd, int *cpu);
bool isInstalled();
@@ -134,10 +153,33 @@ QString getSaveFile(QWidget *parent,
const QString &extension,
QString &lastFilePath);
+void setElidedText(QLabel* label, QString text,
+ enum Qt::TextElideMode mode,
+ int labelWidth);
+
QStringList splitArguments(QString cmd);
QVector<int> parseIdList(QString v_str);
+QStringList getTepEvtName(int sd, int eventId);
+
+/** Get a string to be used as a standard name of a CPU graph. */
+inline QString cpuPlotName(int cpu) {return QString("CPU %1").arg(cpu);}
+
+QString taskPlotName(int sd, int pid);
+
+/** Get the total number of Data streams. */
+inline int getNStreams()
+{
+ kshark_context *kshark_ctx(nullptr);
+
+ if (!kshark_instance(&kshark_ctx))
+ return -1;
+ return kshark_ctx->n_streams;
+}
+
+QString streamDescription(kshark_data_stream *stream);
+
}; // KsUtils
/** Identifier of the Dual Marker active state. */
@@ -158,39 +200,49 @@ public:
~KsDataStore();
- void loadDataFile(const QString &file);
+ int loadDataFile(const QString &file,
+ QVector<kshark_dpi *> plugins);
+
+ int appendDataFile(const QString &file, int64_t shift);
void clear();
- /** Get the trace event parser. */
- tep_handle *tep() const {return _tep;}
+ /** Get the trace data array. */
+ kshark_entry **rows() const {return _rows;}
- /** Get the trace data array.. */
- struct kshark_entry **rows() const {return _rows;}
+ /** Get a reference of the trace data array. */
+ kshark_entry ***rows_r() {return &_rows;}
/** Get the size of the data array. */
ssize_t size() const {return _dataSize;}
+ /** Set the size of the data (number of entries). */
+ void setSize(ssize_t s) {_dataSize = s;}
+
void reload();
void update();
void registerCPUCollections();
- void applyPosTaskFilter(QVector<int>);
+ void unregisterCPUCollections();
+
+ void applyPosTaskFilter(int sd, QVector<int> vec);
- void applyNegTaskFilter(QVector<int>);
+ void applyNegTaskFilter(int sd, QVector<int> vec);
- void applyPosEventFilter(QVector<int>);
+ void applyPosEventFilter(int sd, QVector<int> vec);
- void applyNegEventFilter(QVector<int>);
+ void applyNegEventFilter(int sd, QVector<int> vec);
- void applyPosCPUFilter(QVector<int>);
+ void applyPosCPUFilter(int sd, QVector<int> vec);
- void applyNegCPUFilter(QVector<int>);
+ void applyNegCPUFilter(int sd, QVector<int> vec);
void clearAllFilters();
+ void setClockOffset(int sd, int64_t offset);
+
signals:
/**
* This signal is emitted when the data has changed and the View
@@ -199,75 +251,84 @@ signals:
void updateWidgets(KsDataStore *);
private:
- /** Page event used to parse the page. */
- tep_handle *_tep;
-
/** Trace data array. */
- struct kshark_entry **_rows;
+ kshark_entry **_rows;
/** The size of the data array. */
ssize_t _dataSize;
+ int _openDataFile(kshark_context *kshark_ctx, const QString &file);
+
void _freeData();
- void _unregisterCPUCollections();
- void _applyIdFilter(int filterId, QVector<int> vec);
+
+ void _applyIdFilter(int filterId, QVector<int> vec, int sd);
+
+ void _addPluginsToStream(kshark_context *kshark_ctx, int sd,
+ QVector<kshark_dpi *> plugins);
};
-/** A Plugin Manage class. */
+/** A Plugin Manager class. */
class KsPluginManager : public QObject
{
Q_OBJECT
public:
explicit KsPluginManager(QWidget *parent = nullptr);
- /** A list of available built-in plugins. */
- QStringList _ksPluginList;
+ QStringList getStreamPluginList(int sd) const;
+
+ QVector<int> getActivePlugins(int sd) const;
- /** A list of registered built-in plugins. */
- QVector<bool> _registeredKsPlugins;
+ QVector<int> getPluginsByStatus(int sd, int status) const;
- /** A list of available user plugins. */
- QStringList _userPluginList;
+ /** Get a list of all plugins added by the user. */
+ const QVector<kshark_plugin_list *>
+ getUserPlugins() const {return _userPlugins;}
- /** A list of registered user plugins. */
- QVector<bool> _registeredUserPlugins;
+ void registerPluginMenues();
- void registerFromList(kshark_context *kshark_ctx);
- void unregisterFromList(kshark_context *kshark_ctx);
+ void updatePlugins(int sd, QVector<int> pluginStates);
- void registerPlugin(const QString &plugin);
- void unregisterPlugin(const QString &plugin);
+ void addPlugins(const QStringList &fileNames, QVector<int> streams);
- void addPlugins(const QStringList &fileNames);
+ void registerPlugins(const QString &pluginNames);
- void unloadAll();
+ void unregisterPlugins(const QString &pluginNames);
- void updatePlugins(QVector<int> pluginId);
+ void registerPluginToStream(const QString &pluginName,
+ QVector<int> streamId);
+
+ void unregisterPluginFromStream(const QString &pluginName,
+ QVector<int> streamId);
+
+ void deletePluginDialogs();
+
+ /** Append to the list of User plugin. */
+ void addUserPluginToList(kshark_plugin_list *p) {_userPlugins.append(p);}
signals:
/** This signal is emitted when a plugin is loaded or unloaded. */
void dataReload();
private:
- void _parsePluginList();
-
- char *_pluginLibFromName(const QString &plugin, int &n);
-
- template <class T>
- void _forEachInList(const QStringList &pl,
- const QVector<bool> &reg,
- T action)
- {
- int nPlugins;
- nPlugins = pl.count();
- for (int i = 0; i < nPlugins; ++i) {
- if (reg[i]) {
- action(pl[i]);
- }
- }
- }
+ QVector<kshark_plugin_list *> _userPlugins;
+
+ /** Plugin dialogs. */
+ QVector<QWidget *> _pluginDialogs;
+
+ QVector<kshark_plugin_list *>
+ _loadPluginList(const QStringList &plugins);
+
+ std::string _pluginLibFromName(const QString &plugin);
+
+ std::string _pluginNameFromLib(const QString &plugin);
+
+ void _pluginToStream(const QString &pluginName,
+ QVector<int> streamId,
+ bool reg);
};
KsPlot::Color& operator <<(KsPlot::Color &thisColor, const QColor &c);
+QColor& operator <<(QColor &thisColor, const KsPlot::Color &c);
+
#endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a1e3085e..17b586e2 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -6,7 +6,7 @@ set(EXECUTABLE_OUTPUT_PATH ${KS_TEST_DIR})
add_executable(kshark-tests libkshark-tests.cpp)
target_include_directories(kshark-tests PRIVATE ${Boost_INCLUDE_DIRS})
target_compile_definitions(kshark-tests PRIVATE "BOOST_TEST_DYN_LINK=1")
-target_link_libraries(kshark-tests kshark
+target_link_libraries(kshark-tests kshark-gui
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test(NAME "libkshark_tests"
diff --git a/tests/libkshark-tests.cpp b/tests/libkshark-tests.cpp
index 780a3fae..eb5cb1fb 100644
--- a/tests/libkshark-tests.cpp
+++ b/tests/libkshark-tests.cpp
@@ -46,6 +46,7 @@ BOOST_AUTO_TEST_CASE(add_remove_streams)
BOOST_CHECK_EQUAL(sd, -ENODEV);
kshark_close_all(kshark_ctx);
+ kshark_free(kshark_ctx);
}
#define ARRAY_DEFAULT_SIZE 1000