summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/element.cpp13
-rw-r--r--lib/top_block_query.cpp44
-rw-r--r--query/__init__.py11
3 files changed, 59 insertions, 9 deletions
diff --git a/lib/element.cpp b/lib/element.cpp
index c2ae39e..008027c 100644
--- a/lib/element.cpp
+++ b/lib/element.cpp
@@ -5,7 +5,6 @@
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
-#include <boost/functional/hash.hpp>
#include <cstdlib>
using namespace gras;
@@ -19,12 +18,10 @@ Element::Element(const std::string &name)
{
this->reset(new ElementImpl());
(*this)->name = name;
- std::string extra;
- std::string uid = name;
- boost::hash<std::string> string_hash;
- std::size_t h = string_hash(uid);
+ size_t which = 0;
while (true)
{
+ const std::string uid = str(boost::format("%s %u") % name % which);
try
{
this->set_uid(uid);
@@ -32,12 +29,10 @@ Element::Element(const std::string &name)
}
catch(const std::invalid_argument &ex)
{
- extra = str(boost::format("%04x") % short(h++));
- uid = name+" "+extra;
+ which++;
}
}
- if (not extra.empty()) (*this)->repr = name;
- else (*this)->repr = str(boost::format("%s (%s)") % name % extra);
+ (*this)->repr = str(boost::format("%s (%u)") % name % which);
if (GENESIS) std::cerr
<< "===================================================\n"
diff --git a/lib/top_block_query.cpp b/lib/top_block_query.cpp
index e1ade67..1a5a408 100644
--- a/lib/top_block_query.cpp
+++ b/lib/top_block_query.cpp
@@ -3,6 +3,7 @@
#include "element_impl.hpp"
#include "gras_impl/query_common.hpp"
#include <boost/foreach.hpp>
+#include <boost/format.hpp>
#include <boost/property_tree/ptree.hpp>
#include <Theron/DefaultAllocator.h>
#include <algorithm>
@@ -199,6 +200,48 @@ static ptree query_props(ElementImpl *self, const ptree &query)
return root;
}
+static std::string query_flows(ElementImpl *self, const ptree &query)
+{
+ std::string buff;
+ buff += "digraph flat_flows {\n";
+ buff += "rankdir=LR;\n";
+ buff += "node [shape=record, fontsize=10];\n";
+
+ BOOST_FOREACH(Apology::Worker *w, self->executor->get_workers())
+ {
+ BlockActor *actor = dynamic_cast<BlockActor *>(w->get_actor());
+ std::string in_ports_str, out_ports_str;
+ for (size_t i = 0; i < w->get_num_inputs(); i++)
+ {
+ if (i) in_ports_str += " | ";
+ in_ports_str += str(boost::format("<in%u> %u") % i % i);
+ }
+ if (in_ports_str.size()) in_ports_str = "{" + in_ports_str + "} | ";
+ for (size_t i = 0; i < w->get_num_outputs(); i++)
+ {
+ if (i) out_ports_str += " | ";
+ out_ports_str += str(boost::format("<out%u> %u") % i % i);
+ }
+ if (out_ports_str.size()) out_ports_str = " | {" + out_ports_str + "}";
+ buff += str(boost::format("%s [shape=record, label=\"{ %s %s %s }\", style=filled];\n")
+ % actor->GetAddress().AsString() % in_ports_str % actor->data->block->to_string() % out_ports_str
+ );
+ }
+
+ BOOST_FOREACH(const Apology::Flow &flow, self->executor->get_flat_flows())
+ {
+ buff += str(boost::format("%s:out%u -> %s:in%u;\n")
+ % dynamic_cast<const Apology::Worker *>(flow.src.elem)->get_actor()->GetAddress().AsString()
+ % flow.src.index
+ % dynamic_cast<const Apology::Worker *>(flow.dst.elem)->get_actor()->GetAddress().AsString()
+ % flow.dst.index
+ );
+ }
+
+ buff += "}\n";
+ return buff;
+}
+
std::string TopBlock::query(const std::string &args)
{
//convert json args into property tree
@@ -207,6 +250,7 @@ std::string TopBlock::query(const std::string &args)
//dispatch based on path arg
std::string path = query.get<std::string>("path");
ptree result;
+ if (path == "/flows.dot") return query_flows(this->get(), query);
if (path == "/blocks.json") result = query_blocks(this->get(), query);
if (path == "/stats.json") result = query_stats(this->get(), query);
if (path == "/props.json") result = query_props(this->get(), query);
diff --git a/query/__init__.py b/query/__init__.py
index dc3339c..40c645b 100644
--- a/query/__init__.py
+++ b/query/__init__.py
@@ -26,6 +26,17 @@ class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
args = server_registry[s.server]
path = o.path
+ if path == "/flow.png":
+ s.send_response(200)
+ s.send_header("Content-type", "image/png")
+ s.end_headers()
+ dot = args['top_block'].query(json.dumps(dict(path='/flows.dot')))
+ import subprocess
+ p = subprocess.Popen(args=["dot", "-T", "png"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = p.communicate(input=dot)
+ s.wfile.write(stdout)
+ return
+
#handle json requests
if path.endswith('.json'):
s.send_response(200)