Skip to content

Commit 6bbeaf9

Browse files
authored
Fix validator service (LLNL#242)
1 parent 0b8325a commit 6bbeaf9

File tree

4 files changed

+221
-81
lines changed

4 files changed

+221
-81
lines changed

src/services/validator/validator.cpp

+85-61
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "caliper/SnapshotRecord.h"
1111

1212
#include "caliper/common/Log.h"
13+
#include "caliper/common/Node.h"
1314
#include "caliper/common/OutputStream.h"
1415

1516
#include "caliper/reader/Expand.h"
@@ -53,21 +54,45 @@ class ValidatorService
5354
{
5455
std::map< Attribute, std::vector<Variant> > m_region_stack;
5556
bool m_error_found;
57+
Node m_root_node;
58+
59+
void push(Caliper* c, const Attribute& attr, const Variant& value) {
60+
Variant v_copy = value;
61+
62+
if (!attr.store_as_value())
63+
v_copy = c->make_tree_entry(attr, value, &m_root_node)->data();
64+
65+
m_region_stack[attr].push_back(v_copy);
66+
}
67+
68+
Variant pop(const Attribute& attr) {
69+
Variant ret;
70+
71+
auto it = m_region_stack.find(attr);
72+
if (it == m_region_stack.end())
73+
return ret;
74+
if (it->second.empty())
75+
return ret;
76+
77+
ret = it->second.back();
78+
it->second.pop_back();
79+
80+
if (it->second.empty())
81+
m_region_stack.erase(it);
82+
83+
return ret;
84+
}
5685

5786
public:
5887

59-
bool check_begin(const Attribute& attr, const Variant& value) {
88+
bool check_begin(Caliper* c, const Attribute& attr, const Variant& value) {
6089
if (m_error_found)
6190
return true;
6291

63-
m_region_stack[attr].push_back(value);
92+
push(c, attr, value);
6493

65-
if (attr.is_nested()) {
66-
cali_id_t id = attr.id();
67-
Variant v_id(CALI_TYPE_UINT, &id, sizeof(cali_id_t));
68-
69-
m_region_stack[s_class_nested_attr].push_back(Variant(attr.id()));
70-
}
94+
if (attr.is_nested())
95+
push(c, s_class_nested_attr, Variant(attr.id()));
7196

7297
return false;
7398
}
@@ -76,9 +101,9 @@ class ValidatorService
76101
if (m_error_found)
77102
return true;
78103

79-
auto it = m_region_stack.find(attr);
104+
Variant v_stack_val = pop(attr);
80105

81-
if (it == m_region_stack.end() || it->second.empty()) {
106+
if (v_stack_val.empty()) {
82107
// We currently can't actually check this situation because
83108
// the Caliper runtime prevents events being executed in
84109
// "empty stack" situations :-/
@@ -93,17 +118,8 @@ class ValidatorService
93118
} else {
94119
Variant v_stack_attr;
95120

96-
if (attr.is_nested()) {
97-
auto n_it = m_region_stack.find(s_class_nested_attr);
98-
99-
if (n_it != m_region_stack.end() && !n_it->second.empty()) {
100-
v_stack_attr = n_it->second.back();
101-
n_it->second.pop_back();
102-
}
103-
}
104-
105-
Variant v_stack_val = it->second.back();
106-
it->second.pop_back();
121+
if (attr.is_nested())
122+
v_stack_attr = pop(s_class_nested_attr);
107123

108124
if (attr.is_nested() && attr.id() != v_stack_attr.to_id()) {
109125
m_error_found = true;
@@ -132,15 +148,18 @@ class ValidatorService
132148

133149
bool check_final() {
134150
for (auto const &p : m_region_stack) {
135-
if (p.second.size() > 0) {
151+
if (p.first == s_class_nested_attr)
152+
continue;
153+
154+
if (!p.second.empty()) {
136155
std::ostringstream os;
137156

138157
os << "validator: Regions not closed: "
139158
<< p.first.name() << "=";
140159

141160
int cv = 0;
142-
for (auto const &v : p.second)
143-
os << (cv++ > 0 ? "/" : "") << v;
161+
for (const Variant& v : p.second)
162+
os << (cv++ > 0 ? "/" : "") << v.to_string();
144163

145164
Log(0).stream() << os.str() << std::endl;
146165

@@ -152,7 +171,7 @@ class ValidatorService
152171
}
153172

154173
StackValidator()
155-
: m_error_found(false)
174+
: m_error_found(false), m_root_node(CALI_INV_ID, CALI_INV_ID, Variant())
156175
{ }
157176
}; // class StackValidator
158177

@@ -162,39 +181,29 @@ class ValidatorService
162181

163182
std::atomic<int> global_errors;
164183

165-
struct ThreadData {
166-
std::vector<StackValidator*> exp_validators;
184+
Attribute thread_stack_attr;
167185

168-
~ThreadData() {
169-
for (StackValidator* v : exp_validators)
170-
if (v) {
171-
v->check_final();
172-
delete v;
173-
}
174-
}
186+
std::vector<StackValidator*> thread_stacks;
187+
std::mutex thread_stacks_mutex;
175188

176-
StackValidator* get_validator(Channel* chn) {
177-
size_t expI = chn->id();
178-
StackValidator* v = nullptr;
179189

180-
if (expI < exp_validators.size())
181-
v = exp_validators[expI];
190+
StackValidator* aquire_thread_stack(Caliper* c, Channel* chn) {
191+
StackValidator* tstack =
192+
static_cast<StackValidator*>(c->get(thread_stack_attr).value().get_ptr());
182193

183-
if (!v) {
184-
v = new StackValidator;
194+
if (!tstack) {
195+
tstack = new StackValidator;
185196

186-
if (exp_validators.size() <= expI)
187-
exp_validators.resize(expI + 1);
197+
c->set(thread_stack_attr, Variant(cali_make_variant_from_ptr(tstack)));
188198

189-
exp_validators[expI] = v;
190-
}
199+
std::lock_guard<std::mutex>
200+
g(thread_stacks_mutex);
191201

192-
return v;
202+
thread_stacks.push_back(tstack);
193203
}
194-
};
195-
196-
static thread_local ThreadData sT;
197204

205+
return tstack;
206+
}
198207

199208
void finalize_cb(Caliper*, Channel* chn) {
200209
{
@@ -208,10 +217,19 @@ class ValidatorService
208217
proc_stack = nullptr;
209218
}
210219

211-
// StackValidator* v = sT.get_validator(chn);
220+
{
221+
std::lock_guard<std::mutex>
222+
g(thread_stacks_mutex);
223+
224+
for (StackValidator* v : thread_stacks) {
225+
if (v->check_final())
226+
++global_errors;
227+
228+
delete v;
229+
}
212230

213-
// if (v && v->check_final())
214-
// ++global_errors;
231+
thread_stacks.clear();
232+
}
215233

216234
if (global_errors.load() > 0)
217235
Log(0).stream() << "validator: Annotation nesting errors found"
@@ -226,12 +244,12 @@ class ValidatorService
226244
std::lock_guard<std::mutex>
227245
g(proc_stack_mutex);
228246

229-
if (proc_stack->check_begin(attr, value))
247+
if (proc_stack->check_begin(c, attr, value))
230248
++global_errors;
231249
} else {
232-
StackValidator* v = sT.get_validator(chn);
250+
StackValidator* v = aquire_thread_stack(c, chn);
233251

234-
if (v && v->check_begin(attr, value))
252+
if (v && v->check_begin(c, attr, value))
235253
++global_errors;
236254
}
237255
}
@@ -244,23 +262,31 @@ class ValidatorService
244262
if (proc_stack->check_end(c, chn, attr, value))
245263
++global_errors;
246264
} else {
247-
StackValidator* v = sT.get_validator(chn);
265+
StackValidator* v = aquire_thread_stack(c, chn);
248266

249267
if (v && v->check_end(c, chn, attr, value))
250268
++global_errors;
251269
}
252270
}
253271

254-
ValidatorService(Caliper* c, Channel*)
272+
ValidatorService(Caliper* c, Channel* chn)
255273
: proc_stack(new StackValidator), global_errors(0)
256-
{ }
274+
{
275+
thread_stack_attr =
276+
c->create_attribute(std::string("validator.stack.")+std::to_string(chn->id()),
277+
CALI_TYPE_PTR,
278+
CALI_ATTR_SCOPE_THREAD |
279+
CALI_ATTR_ASVALUE |
280+
CALI_ATTR_SKIP_EVENTS |
281+
CALI_ATTR_HIDDEN);
282+
}
257283

258284
public:
259285

260286
static void validator_register(Caliper* c, Channel* chn) {
261287
if (s_class_nested_attr == Attribute::invalid)
262288
s_class_nested_attr =
263-
c->create_attribute("validator.nested", CALI_TYPE_UINT, CALI_ATTR_DEFAULT);
289+
c->create_attribute("validator.nested", CALI_TYPE_UINT, CALI_ATTR_ASVALUE | CALI_ATTR_HIDDEN);
264290

265291
ValidatorService* instance = new ValidatorService(c, chn);
266292

@@ -283,8 +309,6 @@ class ValidatorService
283309

284310
};
285311

286-
thread_local ValidatorService::ThreadData ValidatorService::sT;
287-
288312
Attribute ValidatorService::s_class_nested_attr { Attribute::invalid };
289313

290314
} // namespace [anonymous]

0 commit comments

Comments
 (0)