summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Moore <timoore@redhat.com>2009-12-04 13:08:01 +0100
committerTim Moore <timoore@redhat.com>2009-12-04 13:08:01 +0100
commit5ddc5963ce06ecea574e90ca503a3ee598522d8f (patch)
treecd6dd73b8104da1c2527180b24b38b48828b307e
parent388924acea820c7a1328eb2ac8a4128437853c3a (diff)
downloadsystemtap-steved-5ddc5963ce06ecea574e90ca503a3ee598522d8f.tar.gz
systemtap-steved-5ddc5963ce06ecea574e90ca503a3ee598522d8f.tar.xz
systemtap-steved-5ddc5963ce06ecea574e90ca503a3ee598522d8f.zip
support multiline data output from scripts run under the grapher
This is accompanied by support for multiline output in hover text. * grapher/StapParser.cxx (ioCallback): Read data 'til the end of line character, not just '\n'. Be careful to use I/O functions that don't treat '\n' specially. * grapher/StapParser.hxx: ditto * grapher/CairoWidget.cxx (CairoTextBox::draw): Perform line breaks for hover text. * testsuite/systemtap.examples/general/grapher.stp: Do multiline output of keyboard events. Also, fix longstanding breaking in the pty probe.
-rw-r--r--grapher/CairoWidget.cxx36
-rw-r--r--grapher/GraphWidget.cxx2
-rw-r--r--grapher/StapParser.cxx27
-rw-r--r--grapher/StapParser.hxx3
-rwxr-xr-xtestsuite/systemtap.examples/general/grapher.stp18
5 files changed, 66 insertions, 20 deletions
diff --git a/grapher/CairoWidget.cxx b/grapher/CairoWidget.cxx
index f627dfaa..db0e464e 100644
--- a/grapher/CairoWidget.cxx
+++ b/grapher/CairoWidget.cxx
@@ -1,9 +1,15 @@
#include "CairoWidget.hxx"
#include <math.h>
+#include <vector>
+
+#include <boost/algorithm/string.hpp>
namespace systemtap
{
+ using namespace std;
+ using namespace boost;
+
void CairoPlayButton::draw(Cairo::RefPtr<Cairo::Context> cr)
{
if (!_visible)
@@ -44,10 +50,22 @@ namespace systemtap
{
if (!_visible)
return;
+ vector<string> lines;
+ split(lines, contents, is_any_of("\n"));
+ vector<Cairo::TextExtents> extents;
+ double width = 0.0, height = 0.0;
+ for (vector<string>::iterator itr = lines.begin(), end = lines.end();
+ itr != end;
+ ++itr)
+ {
+ Cairo::TextExtents extent;
+ cr->get_text_extents(*itr, extent);
+ extents.push_back(extent);
+ width = max(width, extent.width);
+ height += extent.height;
+ }
+
cr->save();
- Cairo::TextExtents extents;
- cr->get_text_extents(contents, extents);
- double width = extents.width, height = extents.height;
cr->move_to(_x0 - 2, _y0 - 2);
cr->line_to(_x0 + width + 2, _y0 - 2);
cr->line_to(_x0 + width + 2, _y0 + height + 2);
@@ -56,8 +74,16 @@ namespace systemtap
cr->set_source_rgba(1.0, 1.0, 1.0, .8);
cr->fill();
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
- cr->move_to(_x0, _y0 + height);
- cr->show_text(contents);
+ vector<Cairo::TextExtents>::iterator titr = extents.begin();
+ double texty = _y0;
+ for (vector<string>::iterator itr = lines.begin(), end = lines.end();
+ itr != end;
+ ++itr,++titr)
+ {
+ cr->move_to(_x0, texty + titr->height);
+ cr->show_text(*itr);
+ texty += titr->height;
+ }
cr->restore();
}
}
diff --git a/grapher/GraphWidget.cxx b/grapher/GraphWidget.cxx
index 9067988a..e37485b8 100644
--- a/grapher/GraphWidget.cxx
+++ b/grapher/GraphWidget.cxx
@@ -275,7 +275,7 @@ namespace systemtap
{
if (!_hoverText)
_hoverText = shared_ptr<CairoTextBox>(new CairoTextBox());
- _hoverText->setOrigin(_mouseX + 5, _mouseY - 5);
+ _hoverText->setOrigin(_mouseX + 10, _mouseY - 5);
Graph::DatasetList& dataSets = g->getDatasets();
for (Graph::DatasetList::reverse_iterator ritr = dataSets.rbegin(),
end = dataSets.rend();
diff --git a/grapher/StapParser.cxx b/grapher/StapParser.cxx
index 6218e229..2a246475 100644
--- a/grapher/StapParser.cxx
+++ b/grapher/StapParser.cxx
@@ -4,6 +4,7 @@
#include <gtkmm/window.h>
#include <algorithm>
+#include <iomanip>
#include <iostream>
#include <sstream>
#include <cstring>
@@ -76,14 +77,14 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
_win->hide();
return true;
}
- buf[bytes_read] = '\0';
- _buffer += buf;
+ _buffer.append(buf, bytes_read);
string::size_type ret = string::npos;
- while ((ret = _buffer.find('\n')) != string::npos)
+ while ((ret = _buffer.find(_lineEndChar)) != string::npos)
{
Glib::ustring dataString(_buffer, 0, ret);
- // %DataSet and %CSV declare a data set; all other statements begin with
- // the name of a data set.
+ // %DataSet and %CSV declare a data set; all other
+ // statements begin with the name of a data set.
+ // Except %LineEnd :)
sub_range<Glib::ustring> found;
if (dataString[0] == '%')
{
@@ -142,6 +143,15 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
setIter->second));
}
}
+ else if ((found = find_first(dataString, "%LineEnd:")))
+ {
+ istringstream stream(Glib::ustring(found.end(),
+ dataString.end()));
+ int charAsInt = 0;
+ // parse hex and octal numbers too
+ stream >> std::setbase(0) >> charAsInt;
+ _lineEndChar = static_cast<char>(charAsInt);
+ }
else
{
cerr << "Unknown declaration " << dataString << endl;
@@ -199,9 +209,10 @@ vector<string> commaSplit(const boost::sub_range<Glib::ustring>& range)
else
{
int64_t time;
- string data;
- stream >> time >> data;
- parseData(itr->second, time, data);
+ stringbuf data;
+ stream >> time;
+ stream.get(data, _lineEndChar);
+ parseData(itr->second, time, data.str());
}
}
}
diff --git a/grapher/StapParser.hxx b/grapher/StapParser.hxx
index a77ad1bc..4f1cbd5a 100644
--- a/grapher/StapParser.hxx
+++ b/grapher/StapParser.hxx
@@ -14,10 +14,11 @@ class StapParser
GraphWidget* _widget;
int _errFd;
int _inFd;
+ unsigned char _lineEndChar;
public:
StapParser(Gtk::Window* win,
GraphWidget* widget) : _win(win), _widget(widget), _errFd(-1),
- _inFd(-1)
+ _inFd(-1), _lineEndChar('\n')
{
}
void parseData(std::tr1::shared_ptr<GraphDataBase> gdata,
diff --git a/testsuite/systemtap.examples/general/grapher.stp b/testsuite/systemtap.examples/general/grapher.stp
index e8655b37..c1c60437 100755
--- a/testsuite/systemtap.examples/general/grapher.stp
+++ b/testsuite/systemtap.examples/general/grapher.stp
@@ -8,7 +8,7 @@ printf ("%%DataSet:pty 50 0000ff discreet\n");
printf ("cpu %%Title:CPU utilization\n");
printf ("cpu %%XAxisTitle:Time\n");
printf ("cpu %%YAxisTitle:Percent\n");
-
+printf ("%%LineEnd:0\n");
}
# CPU utilization
@@ -26,17 +26,25 @@ function qsq_util_reset(q) {
probe timer.ms(100) { # collect utilization percentages frequently
foreach (q in qnames)
- printf("cpu %d %d\n", gettimeofday_ms(), qsq_util_reset(q))
+ printf("cpu %d %d%c", gettimeofday_ms(), qsq_util_reset(q), 0)
}
probe kernel.function("kbd_event") {
if ($event_type == 1 && $value)
- printf("kbd %d %d\n", gettimeofday_ms(), $event_code)
+ printf("kbd %d %d\n0x%x%c", gettimeofday_ms(), $event_code, $event_code, 0)
}
probe kernel.function("pty_write") {
- if (count > 0)
- printf("pty %d %.5s\n", gettimeofday_ms(), buf)
+ if ($count > 0) {
+ printf("pty %d ", gettimeofday_ms())
+ str = kernel_string($buf)
+ for (i = 0; i < $count; ++i) {
+ # yes it's gross
+ c = substr(str, i, 1)
+ printf("%s\n", text_str(c))
+ }
+ printf("%c", 0)
+ }
}