summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-05-27 10:32:51 +0200
committerTim Moore <timoore@redhat.com>2009-07-28 10:17:29 +0200
commit5f4f8b1129659adb2015ce42821faccf8fe6d8d5 (patch)
tree9fdb07036f2461a01f8efa1f5d07f496191e71bc
parent95ddfc079a1d9affdb285f7690f8d5623cd7124a (diff)
downloadsystemtap-steved-5f4f8b1129659adb2015ce42821faccf8fe6d8d5.tar.gz
systemtap-steved-5f4f8b1129659adb2015ce42821faccf8fe6d8d5.tar.xz
systemtap-steved-5f4f8b1129659adb2015ce42821faccf8fe6d8d5.zip
Templatize GraphData
* grapher/GraphData.hxx (GraphDataBase): new superclass for GraphData. Split time data out as a separate vector. (GraphData): Rewrite as template. * grapher/GraphWidget.cxx (on_expose_event): Reflect GraphData templatization. Handle events with string values. * grapher/GraphWidget.hxx (GraphWidget): Keep pointers to GraphDataBase objects instead of GraphData. * grapher/StapParser.cxx (parseData): new member function (ioCallback): Handle new discreet event * grapher/StapParser.hxx (StapParser): keep pointers to GraphDataBase objects instead of GraphData * testsuite/systemtap.examples/general/grapher.stp: Display actual key pressed for keyboard event
-rw-r--r--grapher/GraphData.hxx40
-rw-r--r--grapher/GraphWidget.cxx85
-rw-r--r--grapher/GraphWidget.hxx4
-rw-r--r--grapher/StapParser.cxx77
-rw-r--r--grapher/StapParser.hxx5
-rw-r--r--testsuite/systemtap.examples/general/grapher.stp5
6 files changed, 146 insertions, 70 deletions
diff --git a/grapher/GraphData.hxx b/grapher/GraphData.hxx
index 2c0783c6..9bf3b624 100644
--- a/grapher/GraphData.hxx
+++ b/grapher/GraphData.hxx
@@ -7,44 +7,38 @@
namespace systemtap
{
- struct GraphData
+ struct GraphDataBase
{
- public:
+ virtual ~GraphDataBase() {}
enum Style
{ BAR,
- DOT
+ DOT,
+ EVENT
};
- GraphData() : scale(1.0), style(BAR)
+ GraphDataBase() : scale(1.0), style(BAR)
{
color[0] = 0.0; color[1] = 1.0; color[2] = 0.0;
}
- typedef std::pair<double, double> Datum;
- typedef std::vector<Datum> List;
+ typedef std::vector<double> TimeList;
// size of grid square at "normal" viewing
double scale;
double color[3];
Style style;
- List data;
- struct Compare
- {
- bool operator() (const Datum& lhs, const Datum& rhs) const
- {
- return lhs.first < rhs.first;
- }
- bool operator() (double lhs, const Datum& rhs) const
- {
- return lhs < rhs.first;
- }
- bool operator() (const Datum& lhs, double rhs) const
- {
- return lhs.first < rhs;
- }
- };
+ TimeList times;
};
+ template<typename T>
+ class GraphData : public GraphDataBase
+ {
+ public:
+ typedef T data_type;
+ typedef std::vector<data_type> DataList;
+ DataList data;
+ };
struct CSVData
{
- typedef std::pair<std::string, std::tr1::shared_ptr<GraphData> > Element;
+ typedef std::pair<std::string, std::tr1::shared_ptr<GraphDataBase> >
+ Element;
std::vector<Element> elements;
};
}
diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx
index 34b4daf4..d62ec4f3 100644
--- a/grapher/GraphWidget.cxx
+++ b/grapher/GraphWidget.cxx
@@ -2,6 +2,7 @@
#include <ctime>
#include <math.h>
#include <sstream>
+#include <iostream>
#include <iomanip>
#include <cairomm/context.h>
#include "GraphWidget.hxx"
@@ -9,6 +10,8 @@
namespace systemtap
{
+ using std::string;
+
GraphWidget::GraphWidget()
: _left(0.0), _right(1.0), _top(1.0), _bottom(0.0), _lineWidth(10),
_autoScaling(true), _autoScrolling(true), _zoomFactor(1.0),
@@ -55,7 +58,7 @@ namespace systemtap
{
}
- void GraphWidget::addGraphData(std::tr1::shared_ptr<GraphData> data)
+ void GraphWidget::addGraphData(std::tr1::shared_ptr<GraphDataBase> data)
{
_datasets.push_back(data);
}
@@ -94,9 +97,9 @@ namespace systemtap
ditr != de;
++ditr)
{
- if (!(*ditr)->data.empty())
+ if (!(*ditr)->times.empty())
{
- double lastDataTime = (*ditr)->data.back().first;
+ double lastDataTime = (*ditr)->times.back();
if (lastDataTime > latestTime)
latestTime = lastDataTime;
}
@@ -108,16 +111,16 @@ namespace systemtap
ditr != de;
++ditr)
{
- GraphData::List& gdata = (*ditr)->data;
- if (gdata.size() <= 1)
+ GraphDataBase::TimeList& gtimes = (*ditr)->times;
+ if (gtimes.size() <= 1)
continue;
double totalDiff = 0.0;
- for (GraphData::List::reverse_iterator ritr = gdata.rbegin(),
- re = gdata.rend();
- ritr + 1 != gdata.rend();
+ for (GraphDataBase::TimeList::reverse_iterator ritr = gtimes.rbegin(),
+ re = gtimes.rend();
+ ritr + 1 != gtimes.rend();
ritr++)
{
- double timeDiff = ritr->first - (ritr + 1)->first;
+ double timeDiff = *ritr - *(ritr + 1);
if (timeDiff < minDiff || (timeDiff != 0 && minDiff == 0))
minDiff = timeDiff;
if (minDiff != 0
@@ -148,35 +151,71 @@ namespace systemtap
itr != e;
++itr)
{
+ std::tr1::shared_ptr<GraphData<double> > realData
+ = std::tr1::dynamic_pointer_cast<GraphData<double> >(*itr);
+ std::tr1::shared_ptr<GraphData<string> > stringData
+ = std::tr1::dynamic_pointer_cast<GraphData<string> >(*itr);
cr->save();
cr->translate(0.0, height);
cr->scale(1.0, -1.0);
- GraphData::List::iterator lower
- = std::lower_bound((*itr)->data.begin(), (*itr)->data.end(), _left,
- GraphData::Compare());
- GraphData::List::iterator upper
- = std::upper_bound((*itr)->data.begin(), (*itr)->data.end(), _right,
- GraphData::Compare());
- for (GraphData::List::iterator ditr = lower, de = upper;
+ GraphDataBase::TimeList::iterator lower
+ = std::lower_bound((*itr)->times.begin(), (*itr)->times.end(), _left);
+ GraphDataBase::TimeList::iterator upper
+ = std::upper_bound((*itr)->times.begin(), (*itr)->times.end(),
+ _right);
+ // event bar
+ if ((*itr)->style == GraphDataBase::EVENT)
+ {
+ double eventHeight = height * ((*itr)->scale / 100.0);
+ cr->save();
+ cr->set_line_width(3 * _lineWidth);
+ cr->set_source_rgba((*itr)->color[0], (*itr)->color[1],
+ (*itr)->color[2], .33);
+ cr->move_to(0, eventHeight);
+ cr->line_to(width, eventHeight);
+ cr->stroke();
+ cr->restore();
+ }
+ for (GraphDataBase::TimeList::iterator ditr = lower, de = upper;
ditr != de;
++ditr)
{
+ size_t dataIndex = ditr - (*itr)->times.begin();
cr->set_source_rgba((*itr)->color[0], (*itr)->color[1],
(*itr)->color[2], 1.0);
- if ((*itr)->style == GraphData::BAR)
+ if ((*itr)->style == GraphDataBase::BAR && realData)
{
- cr->move_to((ditr->first - _left) * horizScale, 0);
- cr->line_to((ditr->first - _left) * horizScale,
- ditr->second * height / (*itr)->scale);
+ cr->move_to((*ditr - _left) * horizScale, 0);
+ cr->line_to((*ditr - _left) * horizScale,
+ realData->data[dataIndex] * height / (*itr)->scale);
cr->stroke();
}
- else
+ else if ((*itr)->style == GraphDataBase::DOT && realData)
{
- cr->arc((ditr->first - _left) * horizScale,
- ditr->second * height / (*itr)->scale,
+ cr->arc((*ditr - _left) * horizScale,
+ realData->data[dataIndex] * height / (*itr)->scale,
_lineWidth / 2.0, 0.0, M_PI * 2.0);
cr->fill();
}
+ else if ((*itr)->style == GraphDataBase::EVENT && stringData)
+ {
+ double eventHeight = height * ((*itr)->scale / 100.0);
+ cr->save();
+ cr->select_font_face("Sans", Cairo::FONT_SLANT_NORMAL,
+ Cairo::FONT_WEIGHT_NORMAL);
+ cr->set_font_size(12.0);
+ cr->save();
+ cr->scale(1.0, -1.0);
+ cr->move_to((*ditr - _left) * horizScale,
+ -eventHeight -3.0 * _lineWidth - 2.0);
+ cr->show_text(stringData->data[dataIndex]);
+ cr->restore();
+ cr->rectangle((*ditr - _left) * horizScale - 1.5 * _lineWidth,
+ eventHeight - 1.5 * _lineWidth,
+ 3.0 * _lineWidth, 3.0 * _lineWidth);
+ cr->fill();
+ cr->restore();
+ }
}
cr->restore();
}
diff --git a/grapher/GraphWidget.hxx b/grapher/GraphWidget.hxx
index 46075b78..86ba771d 100644
--- a/grapher/GraphWidget.hxx
+++ b/grapher/GraphWidget.hxx
@@ -17,7 +17,7 @@ namespace systemtap
public:
GraphWidget();
virtual ~GraphWidget();
- void addGraphData(std::tr1::shared_ptr<GraphData> data);
+ void addGraphData(std::tr1::shared_ptr<GraphDataBase> data);
void getExtents(double& left, double& right, double& top, double& bottom) const;
void setExtents(double left, double right, double top, double bottom);
double getLineWidth() { return _lineWidth; }
@@ -38,7 +38,7 @@ namespace systemtap
virtual bool on_button_release_event(GdkEventButton* event);
virtual bool on_scroll_event(GdkEventScroll* event);
bool on_timeout();
- typedef std::vector<std::tr1::shared_ptr<GraphData> > DatasetList;
+ typedef std::vector<std::tr1::shared_ptr<GraphDataBase> > DatasetList;
DatasetList _datasets;
double _left;
double _right;
diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx
index c973b0aa..8b72f93b 100644
--- a/grapher/StapParser.cxx
+++ b/grapher/StapParser.cxx
@@ -1,6 +1,7 @@
#include "StapParser.hxx"
#include <gtkmm/window.h>
+#include <iostream>
namespace systemtap
{
@@ -27,6 +28,29 @@ vector<string> commaSplit(const string& inStr, size_t pos = 0)
return result;
}
+ void StapParser::parseData(std::tr1::shared_ptr<GraphDataBase> gdata,
+ double time, const string& dataString)
+ {
+ std::istringstream stream(dataString);
+ std::tr1::shared_ptr<GraphData<double> > dblptr;
+ std::tr1::shared_ptr<GraphData<string> > strptr;
+ dblptr = std::tr1::dynamic_pointer_cast<GraphData<double> >(gdata);
+ if (dblptr)
+ {
+ double data;
+ stream >> data;
+ dblptr->times.push_back(time);
+ dblptr->data.push_back(data);
+ }
+ else if ((strptr = std::tr1
+ ::dynamic_pointer_cast<GraphData<string> >(gdata))
+ != 0)
+ {
+ strptr->times.push_back(time);
+ strptr->data.push_back(dataString);
+ }
+ }
+
bool StapParser::ioCallback(Glib::IOCondition ioCondition)
{
using namespace std;
@@ -71,20 +95,38 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition)
}
else if ((found = dataString.find("%DataSet:") == 0))
{
- std::tr1::shared_ptr<GraphData> dataSet(new GraphData);
std::string setName;
int hexColor;
+ double scale;
std::string style;
std::istringstream stream(dataString.substr(9));
- stream >> setName >> dataSet->scale >> std::hex >> hexColor
+ stream >> setName >> scale >> std::hex >> hexColor
>> style;
- dataSet->color[0] = (hexColor >> 16) / 255.0;
- dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
- dataSet->color[2] = (hexColor & 0xff) / 255.0;
- if (style == "dot")
- dataSet->style = GraphData::DOT;
- _dataSets.insert(std::make_pair(setName, dataSet));
- _widget.addGraphData(dataSet);
+ if (style == "bar" || style == "dot")
+ {
+ std::tr1::shared_ptr<GraphData<double> >
+ dataSet(new GraphData<double>);
+ if (style == "dot")
+ dataSet->style = GraphDataBase::DOT;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ _widget.addGraphData(dataSet);
+ }
+ else if (style == "discreet")
+ {
+ std::tr1::shared_ptr<GraphData<string> >
+ dataSet(new GraphData<string>);
+ dataSet->style = GraphDataBase::EVENT;
+ dataSet->color[0] = (hexColor >> 16) / 255.0;
+ dataSet->color[1] = ((hexColor >> 8) & 0xff) / 255.0;
+ dataSet->color[2] = (hexColor & 0xff) / 255.0;
+ dataSet->scale = scale;
+ _dataSets.insert(std::make_pair(setName, dataSet));
+ _widget.addGraphData(dataSet);
+ }
}
else if ((found = dataString.find("%CSV:") == 0))
{
@@ -96,8 +138,9 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition)
{
DataMap::iterator setIter = _dataSets.find(*tokIter);
if (setIter != _dataSets.end())
- _csv.elements.push_back(CSVData::Element(*tokIter,
- setIter->second));
+ _csv.elements
+ .push_back(CSVData::Element(*tokIter,
+ setIter->second));
}
}
}
@@ -115,23 +158,21 @@ bool StapParser::ioCallback(Glib::IOCondition ioCondition)
tokIter != e;
++tokIter, ++i)
{
- std::istringstream stream(*tokIter);
- double data;
- stream >> data;
- _csv.elements[i].second
- ->data.push_back(std::make_pair(time, data));
+ parseData(_csv.elements[i].second, time, *tokIter);
}
}
else
{
std::string dataSet;
double time;
- double data;
+ string data;
std::istringstream stream(dataString);
stream >> dataSet >> time >> data;
DataMap::iterator itr = _dataSets.find(dataSet);
if (itr != _dataSets.end())
- itr->second->data.push_back(std::make_pair(time, data));
+ {
+ parseData(itr->second, time, data);
+ }
}
}
_buffer.erase(0, ret + 1);
diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx
index 624accc7..e11e7302 100644
--- a/grapher/StapParser.hxx
+++ b/grapher/StapParser.hxx
@@ -7,7 +7,7 @@ namespace systemtap
class StapParser
{
std::string _buffer;
- typedef std::map<std::string, std::tr1::shared_ptr<GraphData> > DataMap;
+ typedef std::map<std::string, std::tr1::shared_ptr<GraphDataBase> > DataMap;
DataMap _dataSets;
CSVData _csv;
Gtk::Window& _win;
@@ -15,7 +15,8 @@ class StapParser
public:
StapParser(Gtk::Window& win,
GraphWidget& widget) : _win(win), _widget(widget) {}
-
+ void parseData(std::tr1::shared_ptr<GraphDataBase> gdata,
+ double time, const std::string& dataString);
bool ioCallback(Glib::IOCondition ioCondition);
};
diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp
index 5d9b4bb5..26d35aca 100644
--- a/testsuite/systemtap.examples/general/grapher.stp
+++ b/testsuite/systemtap.examples/general/grapher.stp
@@ -6,7 +6,7 @@ printf ("%%Title:CPU utilization\n");
printf ("%%XAxisTitle:Time\n");
printf ("%%YAxisTitle:Percent\n");
printf ("%%DataSet:cpu 100 00ff00 bar\n");
-printf ("%%DataSet:kbd 100 ff0000 dot\n");
+printf ("%%DataSet:kbd 75 ff0000 discreet\n");
}
# CPU utilization
@@ -28,5 +28,6 @@ probe timer.ms(100) { # collect utilization percentages frequently
}
probe kernel.function("kbd_event") {
- printf("kbd %d %d\n", gettimeofday_ms(), 75)
+ if ($event_type == 1 && $value)
+ printf("kbd %d %d\n", gettimeofday_ms(), $event_code)
}