Skip to content

Commit 309e124

Browse files
authored
calql: Add leaf() preprocessor kernel (#525)
* Add preprocessor leaf() kernel * leaf kernel can use path attributes * Always apply preprocessor before filter * Add documentation for leaf kernel
1 parent ff53426 commit 309e124

File tree

7 files changed

+127
-11
lines changed

7 files changed

+127
-11
lines changed

doc/sphinx/calql.rst

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ This table contains a quick reference of all CalQL statements:
2929
<a>=truncate(<b>,<S>) # computes <a> = <b> - mod(<b>, S)
3030
<a>=first(<a0>,<a1>, ...) # <a> is the first of <a0>, <a1>, ... found in the input record
3131
<a>=sum(<a0>,<a1>,...) # computes sum of <a0>, <a1>, ... in the input record
32+
<a>=leaf(<b>) # Takes the leaf of the region hierarchy <b>
3233
... IF <condition> # apply only if input record meets condition
3334

3435
SELECT <list> # Select attributes and define aggregations (i.e., select columns)

include/caliper/common/CaliperMetadataAccessInterface.h

+2
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,6 @@ class CaliperMetadataAccessInterface
6565
get_globals() = 0;
6666
};
6767

68+
Entry get_path_entry(const CaliperMetadataAccessInterface& db, const Entry& e);
69+
6870
}

src/common/CaliperMetadataAccessInterface.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,26 @@ CaliperMetadataAccessInterface::find_attributes_with_prop(int prop) const
3232
ret.push_back(attr);
3333

3434
return ret;
35-
}
35+
}
36+
37+
namespace cali
38+
{
39+
40+
Entry
41+
get_path_entry(const CaliperMetadataAccessInterface& db, const Entry& e)
42+
{
43+
Entry ret;
44+
45+
if (e.is_reference()) {
46+
for (Node* node = e.node(); node; node = node->parent())
47+
if (db.get_attribute(node->attribute()).is_nested()) {
48+
ret = Entry(node);
49+
break;
50+
}
51+
}
52+
53+
return ret;
54+
}
55+
56+
}
57+

src/reader/Preprocessor.cpp

+66-5
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ Variant get_value(const CaliperMetadataAccessInterface& db, const std::string& a
4040
return Variant();
4141
}
4242

43-
4443
class Kernel {
4544
public:
4645

@@ -273,7 +272,7 @@ class SumKernel : public Kernel
273272

274273
if (v_tgt.empty())
275274
continue;
276-
275+
277276
v_sum += v_tgt;
278277
}
279278

@@ -293,12 +292,72 @@ class SumKernel : public Kernel
293292

294293
};
295294

295+
class LeafKernel : public Kernel
296+
{
297+
bool m_use_path;
298+
std::string m_res_attr_name;
299+
Attribute m_res_attr;
300+
std::string m_tgt_attr_name;
301+
Attribute m_tgt_attr;
302+
303+
public:
304+
305+
LeafKernel(const std::string& def)
306+
: m_use_path(true),
307+
m_res_attr_name(def),
308+
m_res_attr(Attribute::invalid),
309+
m_tgt_attr(Attribute::invalid)
310+
{ }
311+
312+
LeafKernel(const std::string& def, const std::string& tgt)
313+
: m_use_path(false),
314+
m_res_attr_name(def),
315+
m_res_attr(Attribute::invalid),
316+
m_tgt_attr_name(tgt),
317+
m_tgt_attr(Attribute::invalid)
318+
{ }
319+
320+
void process(CaliperMetadataAccessInterface& db, EntryList& rec) {
321+
if (m_res_attr == Attribute::invalid) {
322+
cali_attr_type type = CALI_TYPE_STRING;
323+
int prop = CALI_ATTR_SKIP_EVENTS | CALI_ATTR_ASVALUE;
324+
325+
if (!m_use_path) {
326+
m_tgt_attr = db.get_attribute(m_tgt_attr_name);
327+
if (m_tgt_attr == Attribute::invalid)
328+
return;
329+
type = m_tgt_attr.type();
330+
prop |= m_tgt_attr.properties();
331+
prop &= ~CALI_ATTR_NESTED;
332+
}
333+
334+
m_res_attr = db.create_attribute(m_res_attr_name, type, prop);
335+
}
336+
337+
for (const Entry& e : rec) {
338+
Entry e_target = m_use_path ? get_path_entry(db, e) : e.get(m_tgt_attr);
339+
if (!e_target.empty() && m_res_attr.type() == e_target.value().type()) {
340+
rec.push_back(Entry(m_res_attr, e_target.value()));
341+
return;
342+
}
343+
}
344+
}
345+
346+
static Kernel* create(const std::string& def, const std::vector<std::string>& args) {
347+
if (args.empty())
348+
return new LeafKernel(def);
349+
350+
return new LeafKernel(def, args.front());
351+
}
352+
};
353+
296354
enum KernelID {
297355
ScaledRatio,
298356
Scale,
299357
Truncate,
300358
First,
301-
Sum
359+
Sum,
360+
Leaf
302361
};
303362

304363
const char* sratio_args[] = { "numerator", "denominator", "scale" };
@@ -315,6 +374,7 @@ const QuerySpec::FunctionSignature kernel_signatures[] = {
315374
{ KernelID::Truncate, "truncate", 1, 2, scale_args },
316375
{ KernelID::First, "first", 1, 8, first_args },
317376
{ KernelID::Sum, "sum", 1, 8, first_args },
377+
{ KernelID::Leaf, "leaf", 0, 1, scale_args },
318378

319379
QuerySpec::FunctionSignatureTerminator
320380
};
@@ -326,10 +386,11 @@ const KernelCreateFn kernel_create_fn[] = {
326386
ScaleKernel::create,
327387
TruncateKernel::create,
328388
FirstKernel::create,
329-
SumKernel::create
389+
SumKernel::create,
390+
LeafKernel::create
330391
};
331392

332-
constexpr int MAX_KERNEL_ID = 4;
393+
constexpr int MAX_KERNEL_ID = 5;
333394

334395
}
335396

src/reader/QueryProcessor.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ struct QueryProcessor::QueryProcessorImpl
2323

2424
void
2525
process_record(CaliperMetadataAccessInterface& db, const EntryList& in_rec) {
26-
if (filter.pass(db, in_rec)) {
27-
auto rec = preprocessor.process(db, in_rec);
26+
auto rec = preprocessor.process(db, in_rec);
27+
if (filter.pass(db, rec)) {
2828

2929
if (do_aggregate)
3030
aggregator.add(db, rec);

src/reader/test/test_preprocessor.cpp

+31-1
Original file line numberDiff line numberDiff line change
@@ -432,4 +432,34 @@ TEST(PreprocessorTest, SumKernel)
432432

433433
EXPECT_EQ(a_it->second.value().to_int(), 42);
434434
EXPECT_EQ(s_it->second.value().to_int(), 66);
435-
}
435+
}
436+
437+
TEST(PreprocessorTest, LeafKernel)
438+
{
439+
CaliperMetadataDB db;
440+
441+
Attribute ctx =
442+
db.create_attribute("ctx", CALI_TYPE_STRING, CALI_ATTR_DEFAULT);
443+
444+
Attribute a[2] = { ctx, ctx };
445+
Variant v[2] = { Variant("foo"), Variant("bar") };
446+
447+
Node* n_1 = db.make_tree_entry(2, a, v);
448+
449+
EntryList rec;
450+
rec.push_back(Entry(n_1));
451+
452+
QuerySpec spec;
453+
spec.preprocess_ops.push_back(::make_spec("leaf", ::make_op("leaf", "ctx")));
454+
455+
Preprocessor pp(spec);
456+
EntryList out = pp.process(db, rec);
457+
458+
Attribute leaf_attr = db.get_attribute("leaf");
459+
460+
ASSERT_NE(leaf_attr, Attribute::invalid);
461+
ASSERT_EQ(out.size(), 2u);
462+
EXPECT_EQ(out[1].attribute(), leaf_attr.id());
463+
EXPECT_EQ(out[1].value(), n_1->data());
464+
EXPECT_NE(out[1].node()->parent(), n_1->parent());
465+
}

src/tools/cali-query/cali-query.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,10 @@ int main(int argc, const char* argv[])
302302
else
303303
snap_proc = aggregate;
304304

305-
if (!spec.preprocess_ops.empty())
306-
snap_proc = SnapshotFilterStep(Preprocessor(spec), snap_proc);
307305
if (spec.filter.selection == QuerySpec::FilterSelection::List)
308306
snap_proc = SnapshotFilterStep(RecordSelector(spec), snap_proc);
307+
if (!spec.preprocess_ops.empty())
308+
snap_proc = SnapshotFilterStep(Preprocessor(spec), snap_proc);
309309

310310
if (args.is_set("list-attributes")) {
311311
node_proc = AttributeExtract(snap_proc);

0 commit comments

Comments
 (0)