Skip to content

Commit aa23f24

Browse files
committed
Fix case with unsorted events (#9)
* Fix case with unsorted events
1 parent 4cbc9a0 commit aa23f24

File tree

2 files changed

+93
-28
lines changed

2 files changed

+93
-28
lines changed

source/citnames/source/Citnames.cc

Lines changed: 73 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <filesystem>
3030
#include <set>
31+
#include <map>
3132

3233
#ifdef HAVE_FMT_STD_H
3334
#include <fmt/std.h>
@@ -44,6 +45,11 @@ template <> struct fmt::formatter<cs::Configuration> : ostream_formatter {};
4445

4546
namespace {
4647

48+
struct EventEntries {
49+
std::list<cs::Entry> compile;
50+
std::list<cs::Entry> link;
51+
};
52+
4753
std::list<fs::path> to_abspath(const std::list<fs::path> &paths, const fs::path &root) {
4854
std::list<fs::path> results;
4955
for (const auto &path : paths) {
@@ -194,15 +200,49 @@ namespace {
194200
});
195201
}
196202

197-
rust::Result<size_t> transform(
198-
cs::semantic::Build &build,
203+
bool transform_event(
204+
const cs::semantic::Build &build,
205+
const rpc::Event &event,
206+
std::map<size_t, EventEntries> &pid_entries,
207+
const bool with_link
208+
) {
209+
const auto get_entries = [](const auto &semantic) -> std::list<cs::Entry> {
210+
const auto candidate = dynamic_cast<const cs::semantic::CompilerCall *>(semantic.get());
211+
return (candidate != nullptr) ? candidate->into_entries() : std::list<cs::Entry>();
212+
};
213+
214+
const size_t pid = event.started().pid();
215+
bool is_written = false;
216+
217+
auto entries_compile = build.recognize(event, cs::semantic::BuildTarget::COMPILER).map<std::list<cs::Entry>>(get_entries).unwrap_or({});
218+
if (!entries_compile.empty()) {
219+
is_written = true;
220+
std::move(entries_compile.begin(), entries_compile.end(), std::back_inserter(pid_entries[pid].compile));
221+
}
222+
if (with_link) {
223+
auto entries_link = build.recognize(event, cs::semantic::BuildTarget::LINKER).map<std::list<cs::Entry>>(get_entries).unwrap_or({});
224+
if (!entries_link.empty()) {
225+
is_written = true;
226+
std::move(entries_link.begin(), entries_link.end(), std::back_inserter(pid_entries[pid].link));
227+
}
228+
}
229+
230+
return is_written;
231+
}
232+
233+
size_t transform(
234+
const cs::semantic::Build &build,
199235
const db::EventsDatabaseReader::Ptr& events,
200236
std::list<cs::Entry> &output_compile,
201237
std::list<cs::Entry> &output_link,
202238
const bool with_link
203239
) {
204-
std::set<size_t> all_ppid;
205-
std::set<size_t> writed_command_pids;
240+
std::set<size_t> writed_event_pids;
241+
std::map<size_t, std::set<size_t>> pid_children;
242+
std::set<size_t> pids_without_parent;
243+
std::set<size_t> pids_with_parent;
244+
245+
std::map<size_t, EventEntries> pid_entries;
206246

207247
for (const rpc::Event &event : *events) {
208248
const size_t pid = event.started().pid();
@@ -211,38 +251,43 @@ namespace {
211251
continue;
212252
}
213253

214-
if (all_ppid.find(pid) != all_ppid.end()) {
215-
return rust::Err(std::runtime_error("Processes in events database are not sorted!"));
254+
pid_children[ppid].insert(pid);
255+
pids_without_parent.erase(pid);
256+
pids_with_parent.insert(pid);
257+
if (pids_with_parent.find(ppid) == pids_with_parent.end()) {
258+
pids_without_parent.insert(ppid);
216259
}
217-
all_ppid.insert(ppid);
218260

219-
if (writed_command_pids.find(ppid) != writed_command_pids.end()) {
220-
writed_command_pids.insert(pid);
221-
continue;
261+
if (writed_event_pids.find(ppid) != writed_event_pids.end()) {
262+
writed_event_pids.insert(pid);
263+
}
264+
else if (transform_event(build, event, pid_entries, with_link)) {
265+
writed_event_pids.insert(pid);
222266
}
267+
}
223268

224-
const auto get_entries = [](const auto &semantic) -> std::list<cs::Entry> {
225-
const auto candidate = dynamic_cast<const cs::semantic::CompilerCall *>(semantic.get());
226-
return (candidate != nullptr) ? candidate->into_entries() : std::list<cs::Entry>();
227-
};
269+
for (const auto &p : pids_without_parent) {
270+
std::vector<size_t> pids;
271+
std::copy(pid_children[p].rbegin(), pid_children[p].rend(), std::back_inserter(pids));
228272

229-
const auto entries_compile = build.recognize(event, cs::semantic::BuildTarget::COMPILER)
230-
.map<std::list<cs::Entry>>(get_entries).unwrap_or({});
231-
if (!entries_compile.empty()) {
232-
writed_command_pids.insert(pid);
233-
std::copy(entries_compile.begin(), entries_compile.end(), std::back_inserter(output_compile));
234-
}
273+
while (!pids.empty()) {
274+
const auto cur_pid = pids.back();
275+
pids.pop_back();
235276

236-
if (with_link) {
237-
const auto entries_link = build.recognize(event, cs::semantic::BuildTarget::LINKER)
238-
.map<std::list<cs::Entry>>(get_entries).unwrap_or({});
239-
if (!entries_link.empty()) {
240-
writed_command_pids.insert(pid);
241-
std::copy(entries_link.begin(), entries_link.end(), std::back_inserter(output_link));
277+
auto entries_iter = pid_entries.find(cur_pid);
278+
// tree before meaningful event
279+
if (entries_iter == pid_entries.end()) {
280+
std::copy(pid_children[cur_pid].rbegin(), pid_children[cur_pid].rend(), std::back_inserter(pids));
281+
}
282+
// meaningful event, children should not be written
283+
else {
284+
std::move(entries_iter->second.compile.begin(), entries_iter->second.compile.end(), std::back_inserter(output_compile));
285+
std::move(entries_iter->second.link.begin(), entries_iter->second.link.end(), std::back_inserter(output_link));
242286
}
243287
}
244288
}
245-
return rust::Ok(output_compile.size() + output_link.size());
289+
290+
return output_compile.size() + output_link.size();
246291
}
247292

248293
rust::Result<size_t> complete_entries_from_json(
@@ -286,7 +331,7 @@ namespace cs {
286331
std::list<cs::Entry> entries_link;
287332

288333
return db::EventsDatabaseReader::from(arguments_.input)
289-
.and_then<size_t>([this, &entries_compile, &entries_link](const auto &commands) {
334+
.map<size_t>([this, &entries_compile, &entries_link](const auto &commands) {
290335
cs::semantic::Build build(configuration_.compilation);
291336
return transform(build, commands, entries_compile, entries_link, arguments_.with_link);
292337
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env sh
2+
3+
# RUN: cd %T; %{shell} %s %t
4+
# RUN: %{citnames} --verbose --input %t.commands.json --output-compile %t.compilations.json
5+
# RUN: assert_compilation %t.compilations.json count -eq 1
6+
7+
cat << EOF > "$1.commands.json"
8+
{"rid":"5208588700335725496","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.573991Z"}
9+
{"rid":"5982815742339840829","started":{"execution":{"executable":"/usr/lib/gcc/x86_64-linux-gnu/11/collect2","arguments":["/usr/lib/gcc/x86_64-linux-gnu/11/collect2"],"working_dir":"example/build","environment":{}},"pid":13896,"ppid":13868},"timestamp":"2023-05-26T11:42:25.580038Z"}
10+
{"rid":"16827070368060185859","started":{"execution":{"executable":"/usr/bin/ld","arguments":["/usr/bin/ld"],"working_dir":"example/build","environment":{}},"pid":13904,"ppid":13896},"timestamp":"2023-05-26T11:42:25.585572Z"}
11+
{"rid":"16827070368060185859","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.638394Z"}
12+
{"rid":"5982815742339840829","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.639796Z"}
13+
{"rid":"11620369640675796770","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.641203Z"}
14+
{"rid":"3208622825367537157","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.642386Z"}
15+
{"rid":"3208622825367537157","started":{"execution":{"executable":"/usr/bin/make","arguments":["make","-f","../Makefile"],"working_dir":"example/build","environment":{}},"pid":13860,"ppid":13847},"timestamp":"2023-05-26T11:42:25.322304Z"}
16+
{"rid":"11620369640675796770","started":{"execution":{"executable":"/usr/bin/g++","arguments":["g++","../main.cpp"],"working_dir":"example/build","environment":{}},"pid":13868,"ppid":13860},"timestamp":"2023-05-26T11:42:25.332432Z"}
17+
{"rid":"1195915605071429231","started":{"execution":{"executable":"/usr/lib/gcc/x86_64-linux-gnu/11/cc1plus","arguments":["/usr/lib/gcc/x86_64-linux-gnu/11/cc1plus"],"working_dir":"example/build","environment":{}},"pid":13876,"ppid":13868},"timestamp":"2023-05-26T11:42:25.345192Z"}
18+
{"rid":"1195915605071429231","terminated":{"status":"0"},"timestamp":"2023-05-26T11:42:25.563234Z"}
19+
{"rid":"5208588700335725496","started":{"execution":{"executable":"/usr/bin/as","arguments":["as"],"working_dir":"example/build","environment":{}},"pid":13888,"ppid":13868},"timestamp":"2023-05-26T11:42:25.568801Z"}
20+
EOF

0 commit comments

Comments
 (0)