/src/zeek/src/file_analysis/AnalyzerSet.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // See the file "COPYING" in the main distribution directory for copyright. |
2 | | |
3 | | #include "zeek/file_analysis/AnalyzerSet.h" |
4 | | |
5 | | #include "zeek/CompHash.h" |
6 | | #include "zeek/Val.h" |
7 | | #include "zeek/file_analysis/Analyzer.h" |
8 | | #include "zeek/file_analysis/File.h" |
9 | | #include "zeek/file_analysis/Manager.h" |
10 | | |
11 | | namespace zeek::file_analysis::detail { |
12 | | |
13 | 0 | static void analyzer_del_func(void* v) { |
14 | 0 | file_analysis::Analyzer* a = (file_analysis::Analyzer*)v; |
15 | |
|
16 | 0 | a->Done(); |
17 | 0 | delete a; |
18 | 0 | } |
19 | | |
20 | 936k | AnalyzerSet::AnalyzerSet(File* arg_file) : file(arg_file) { analyzer_map.SetDeleteFunc(analyzer_del_func); } |
21 | | |
22 | 936k | AnalyzerSet::~AnalyzerSet() { |
23 | 936k | while ( ! mod_queue.empty() ) { |
24 | 0 | Modification* mod = mod_queue.front(); |
25 | 0 | mod->Abort(); |
26 | 0 | delete mod; |
27 | 0 | mod_queue.pop(); |
28 | 0 | } |
29 | 936k | } |
30 | | |
31 | 0 | Analyzer* AnalyzerSet::Find(const zeek::Tag& tag, RecordValPtr args) { |
32 | 0 | auto key = GetKey(tag, std::move(args)); |
33 | 0 | Analyzer* rval = analyzer_map.Lookup(key.get()); |
34 | 0 | return rval; |
35 | 0 | } |
36 | | |
37 | 0 | bool AnalyzerSet::Add(const zeek::Tag& tag, RecordValPtr args) { |
38 | 0 | auto key = GetKey(tag, args); |
39 | |
|
40 | 0 | if ( analyzer_map.Lookup(key.get()) ) { |
41 | 0 | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Instantiate analyzer %s skipped: already exists", file->GetID().c_str(), |
42 | 0 | file_mgr->GetComponentName(tag).c_str()); |
43 | |
|
44 | 0 | return true; |
45 | 0 | } |
46 | | |
47 | 0 | file_analysis::Analyzer* a = InstantiateAnalyzer(tag, std::move(args)); |
48 | |
|
49 | 0 | if ( ! a ) |
50 | 0 | return false; |
51 | | |
52 | 0 | Insert(a, std::move(key)); |
53 | |
|
54 | 0 | return true; |
55 | 0 | } |
56 | | |
57 | 3.77M | Analyzer* AnalyzerSet::QueueAdd(const zeek::Tag& tag, RecordValPtr args) { |
58 | 3.77M | auto key = GetKey(tag, args); |
59 | 3.77M | file_analysis::Analyzer* a = InstantiateAnalyzer(tag, std::move(args)); |
60 | | |
61 | 3.77M | if ( ! a ) |
62 | 0 | return nullptr; |
63 | | |
64 | 3.77M | mod_queue.push(new AddMod(a, std::move(key))); |
65 | | |
66 | 3.77M | return a; |
67 | 3.77M | } |
68 | | |
69 | 3.77M | bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set) { |
70 | 3.77M | if ( set->analyzer_map.Lookup(key.get()) ) { |
71 | 842k | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s skipped: already exists", a->GetFile()->GetID().c_str(), |
72 | 842k | file_mgr->GetComponentName(a->Tag()).c_str()); |
73 | | |
74 | 842k | Abort(); |
75 | 842k | return true; |
76 | 842k | } |
77 | | |
78 | 2.93M | set->Insert(a, std::move(key)); |
79 | | |
80 | 2.93M | return true; |
81 | 3.77M | } |
82 | | |
83 | 842k | void AnalyzerSet::AddMod::Abort() { delete a; } |
84 | | |
85 | 0 | bool AnalyzerSet::Remove(const zeek::Tag& tag, RecordValPtr args) { return Remove(tag, GetKey(tag, std::move(args))); } |
86 | | |
87 | 2.93M | bool AnalyzerSet::Remove(const zeek::Tag& tag, std::unique_ptr<zeek::detail::HashKey> key) { |
88 | 2.93M | auto a = (file_analysis::Analyzer*)analyzer_map.Remove(key.get()); |
89 | | |
90 | 2.93M | if ( ! a ) { |
91 | 0 | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip remove analyzer %s", file->GetID().c_str(), |
92 | 0 | file_mgr->GetComponentName(tag).c_str()); |
93 | 0 | return false; |
94 | 0 | } |
95 | | |
96 | 2.93M | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Remove analyzer %s", file->GetID().c_str(), |
97 | 2.93M | file_mgr->GetComponentName(tag).c_str()); |
98 | | |
99 | 2.93M | a->Done(); |
100 | | |
101 | | // We don't delete the analyzer object right here because the remove |
102 | | // operation may execute at a time when it can still be accessed. |
103 | | // Instead we let the file know to delete the analyzer later. |
104 | 2.93M | file->DoneWithAnalyzer(a); |
105 | | |
106 | 2.93M | return true; |
107 | 2.93M | } |
108 | | |
109 | 2.93M | bool AnalyzerSet::QueueRemove(const zeek::Tag& tag, RecordValPtr args) { |
110 | 2.93M | auto key = GetKey(tag, std::move(args)); |
111 | 2.93M | auto rval = analyzer_map.Lookup(key.get()); |
112 | 2.93M | mod_queue.push(new RemoveMod(tag, std::move(key))); |
113 | 2.93M | return rval; |
114 | 2.93M | } |
115 | | |
116 | 2.93M | bool AnalyzerSet::RemoveMod::Perform(AnalyzerSet* set) { return set->Remove(tag, std::move(key)); } |
117 | | |
118 | 6.71M | std::unique_ptr<zeek::detail::HashKey> AnalyzerSet::GetKey(const zeek::Tag& t, RecordValPtr args) const { |
119 | 6.71M | auto lv = make_intrusive<ListVal>(TYPE_ANY); |
120 | 6.71M | lv->Append(t.AsVal()); |
121 | 6.71M | lv->Append(std::move(args)); |
122 | 6.71M | auto key = file_mgr->GetAnalyzerHash()->MakeHashKey(*lv, true); |
123 | | |
124 | 6.71M | if ( ! key ) |
125 | 0 | reporter->InternalError("AnalyzerArgs type mismatch"); |
126 | | |
127 | 6.71M | return key; |
128 | 6.71M | } |
129 | | |
130 | 3.77M | file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag, RecordValPtr args) const { |
131 | 3.77M | auto a = file_mgr->InstantiateAnalyzer(tag, std::move(args), file); |
132 | | |
133 | 3.77M | if ( ! a ) { |
134 | 0 | auto c = file_mgr->Lookup(tag); |
135 | |
|
136 | 0 | if ( c && ! c->Enabled() ) |
137 | 0 | return nullptr; |
138 | | |
139 | 0 | reporter->Error("[%s] Failed file analyzer %s instantiation", file->GetID().c_str(), |
140 | 0 | file_mgr->GetComponentName(tag).c_str()); |
141 | 0 | return nullptr; |
142 | 0 | } |
143 | | |
144 | 3.77M | return a; |
145 | 3.77M | } |
146 | | |
147 | 2.93M | void AnalyzerSet::Insert(file_analysis::Analyzer* a, std::unique_ptr<zeek::detail::HashKey> key) { |
148 | 2.93M | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s", file->GetID().c_str(), |
149 | 2.93M | file_mgr->GetComponentName(a->Tag()).c_str()); |
150 | 2.93M | analyzer_map.Insert(key.get(), a); |
151 | | |
152 | 2.93M | a->Init(); |
153 | 2.93M | } |
154 | | |
155 | 98.1M | void AnalyzerSet::DrainModifications() { |
156 | 98.1M | if ( mod_queue.empty() ) |
157 | 95.5M | return; |
158 | | |
159 | 2.54M | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Start analyzer mod queue flush", file->GetID().c_str()); |
160 | 6.71M | do { |
161 | 6.71M | Modification* mod = mod_queue.front(); |
162 | 6.71M | mod->Perform(this); |
163 | 6.71M | delete mod; |
164 | 6.71M | mod_queue.pop(); |
165 | 6.71M | } while ( ! mod_queue.empty() ); |
166 | 2.54M | DBG_LOG(DBG_FILE_ANALYSIS, "[%s] End flushing analyzer mod queue.", file->GetID().c_str()); |
167 | 2.54M | } |
168 | | |
169 | | } // namespace zeek::file_analysis::detail |