/src/zeek/src/input/ReaderBackend.cc
Line | Count | Source |
1 | | // See the file "COPYING" in the main distribution directory for copyright. |
2 | | |
3 | | #include "zeek/input/ReaderBackend.h" |
4 | | |
5 | | #include "zeek/input/Manager.h" |
6 | | #include "zeek/input/ReaderFrontend.h" |
7 | | |
8 | | using zeek::threading::Field; |
9 | | using zeek::threading::Value; |
10 | | |
11 | | namespace zeek::input { |
12 | | |
13 | | class PutMessage final : public threading::OutputMessage<ReaderFrontend> { |
14 | | public: |
15 | | PutMessage(ReaderFrontend* reader, Value** val) |
16 | 0 | : threading::OutputMessage<ReaderFrontend>("Put", reader), val(val) {} |
17 | | |
18 | 0 | bool Process() override { |
19 | 0 | input_mgr->Put(Object(), val); |
20 | 0 | return true; |
21 | 0 | } |
22 | | |
23 | | private: |
24 | | Value** val; |
25 | | }; |
26 | | |
27 | | class DeleteMessage final : public threading::OutputMessage<ReaderFrontend> { |
28 | | public: |
29 | | DeleteMessage(ReaderFrontend* reader, Value** val) |
30 | 0 | : threading::OutputMessage<ReaderFrontend>("Delete", reader), val(val) {} |
31 | | |
32 | 0 | bool Process() override { return input_mgr->Delete(Object(), val); } |
33 | | |
34 | | private: |
35 | | Value** val; |
36 | | }; |
37 | | |
38 | | class ClearMessage final : public threading::OutputMessage<ReaderFrontend> { |
39 | | public: |
40 | 0 | ClearMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("Clear", reader) {} |
41 | | |
42 | 0 | bool Process() override { |
43 | 0 | input_mgr->Clear(Object()); |
44 | 0 | return true; |
45 | 0 | } |
46 | | |
47 | | private: |
48 | | }; |
49 | | |
50 | | class ReaderErrorMessage final : public threading::OutputMessage<ReaderFrontend> { |
51 | | public: |
52 | | enum Type : uint8_t { INFO, WARNING, ERROR }; |
53 | | |
54 | | ReaderErrorMessage(ReaderFrontend* reader, Type arg_type, const char* arg_msg) |
55 | 0 | : threading::OutputMessage<ReaderFrontend>("ReaderErrorMessage", reader) { |
56 | 0 | type = arg_type; |
57 | 0 | msg = util::copy_string(arg_msg); |
58 | 0 | } |
59 | | |
60 | 0 | ~ReaderErrorMessage() override { delete[] msg; } |
61 | | |
62 | | bool Process() override; |
63 | | |
64 | | private: |
65 | | const char* msg; |
66 | | Type type; |
67 | | }; |
68 | | |
69 | | class SendEntryMessage final : public threading::OutputMessage<ReaderFrontend> { |
70 | | public: |
71 | | SendEntryMessage(ReaderFrontend* reader, Value** val) |
72 | 0 | : threading::OutputMessage<ReaderFrontend>("SendEntry", reader), val(val) {} |
73 | | |
74 | 0 | bool Process() override { |
75 | 0 | input_mgr->SendEntry(Object(), val); |
76 | 0 | return true; |
77 | 0 | } |
78 | | |
79 | | private: |
80 | | Value** val; |
81 | | }; |
82 | | |
83 | | class EndCurrentSendMessage final : public threading::OutputMessage<ReaderFrontend> { |
84 | | public: |
85 | | EndCurrentSendMessage(ReaderFrontend* reader) |
86 | 0 | : threading::OutputMessage<ReaderFrontend>("EndCurrentSend", reader) {} |
87 | | |
88 | 0 | bool Process() override { |
89 | 0 | input_mgr->EndCurrentSend(Object()); |
90 | 0 | return true; |
91 | 0 | } |
92 | | |
93 | | private: |
94 | | }; |
95 | | |
96 | | class EndOfDataMessage final : public threading::OutputMessage<ReaderFrontend> { |
97 | | public: |
98 | 0 | EndOfDataMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("EndOfData", reader) {} |
99 | | |
100 | 0 | bool Process() override { |
101 | 0 | input_mgr->SendEndOfData(Object()); |
102 | 0 | return true; |
103 | 0 | } |
104 | | |
105 | | private: |
106 | | }; |
107 | | |
108 | | class ReaderClosedMessage final : public threading::OutputMessage<ReaderFrontend> { |
109 | | public: |
110 | 0 | ReaderClosedMessage(ReaderFrontend* reader) : threading::OutputMessage<ReaderFrontend>("ReaderClosed", reader) {} |
111 | | |
112 | 0 | bool Process() override { |
113 | 0 | Object()->SetDisable(); |
114 | 0 | return input_mgr->RemoveStreamContinuation(Object()); |
115 | 0 | } |
116 | | |
117 | | private: |
118 | | }; |
119 | | |
120 | | class DisableMessage final : public threading::OutputMessage<ReaderFrontend> { |
121 | | public: |
122 | 0 | DisableMessage(ReaderFrontend* writer) : threading::OutputMessage<ReaderFrontend>("Disable", writer) {} |
123 | | |
124 | 0 | bool Process() override { |
125 | 0 | Object()->SetDisable(); |
126 | | // And - because we do not need disabled objects any more - |
127 | | // there is no way to re-enable them, so simply delete them. |
128 | | // This avoids the problem of having to periodically check if |
129 | | // there are any disabled readers out there. As soon as a |
130 | | // reader disables itself, it deletes itself. |
131 | 0 | input_mgr->RemoveStream(Object()); |
132 | 0 | return true; |
133 | 0 | } |
134 | | }; |
135 | | |
136 | 0 | bool ReaderErrorMessage::Process() { |
137 | 0 | switch ( type ) { |
138 | 0 | case INFO: input_mgr->Info(Object(), msg); break; |
139 | | |
140 | 0 | case WARNING: input_mgr->Warning(Object(), msg); break; |
141 | | |
142 | 0 | case ERROR: input_mgr->Error(Object(), msg); break; |
143 | 0 | } |
144 | | |
145 | 0 | return true; |
146 | 0 | } |
147 | | |
148 | | using namespace input; |
149 | | |
150 | 0 | ReaderBackend::ReaderBackend(ReaderFrontend* arg_frontend) : MsgThread() { |
151 | 0 | disabled = true; // disabled will be set correctly in init. |
152 | 0 | frontend = arg_frontend; |
153 | 0 | info = new ReaderInfo(frontend->Info()); |
154 | 0 | num_fields = 0; |
155 | 0 | fields = nullptr; |
156 | |
|
157 | 0 | SetName(frontend->Name()); |
158 | 0 | } |
159 | | |
160 | 0 | ReaderBackend::~ReaderBackend() { delete info; } |
161 | | |
162 | 0 | void ReaderBackend::Put(Value** val) { SendOut(new PutMessage(frontend, val)); } |
163 | | |
164 | 0 | void ReaderBackend::Delete(Value** val) { SendOut(new DeleteMessage(frontend, val)); } |
165 | | |
166 | 0 | void ReaderBackend::Clear() { SendOut(new ClearMessage(frontend)); } |
167 | | |
168 | 0 | void ReaderBackend::EndCurrentSend() { SendOut(new EndCurrentSendMessage(frontend)); } |
169 | | |
170 | 0 | void ReaderBackend::EndOfData() { SendOut(new EndOfDataMessage(frontend)); } |
171 | | |
172 | 0 | void ReaderBackend::SendEntry(Value** vals) { SendOut(new SendEntryMessage(frontend, vals)); } |
173 | | |
174 | 0 | bool ReaderBackend::Init(const int arg_num_fields, const threading::Field* const* arg_fields) { |
175 | 0 | if ( Failed() ) |
176 | 0 | return true; |
177 | | |
178 | 0 | disabled = false; |
179 | |
|
180 | 0 | SetOSName(Fmt("zk.%s", Name())); |
181 | |
|
182 | 0 | num_fields = arg_num_fields; |
183 | 0 | fields = arg_fields; |
184 | | |
185 | | // disable if DoInit returns error. |
186 | 0 | int success = DoInit(*info, arg_num_fields, arg_fields); |
187 | |
|
188 | 0 | if ( ! success ) { |
189 | 0 | Error("Init failed"); |
190 | 0 | DisableFrontend(); |
191 | 0 | } |
192 | |
|
193 | 0 | return success; |
194 | 0 | } |
195 | | |
196 | 0 | bool ReaderBackend::OnFinish(double network_time) { |
197 | 0 | if ( ! Failed() ) |
198 | 0 | DoClose(); |
199 | |
|
200 | 0 | disabled = true; // frontend disables itself when it gets the Close-message. |
201 | 0 | SendOut(new ReaderClosedMessage(frontend)); |
202 | |
|
203 | 0 | if ( fields ) { |
204 | 0 | for ( unsigned int i = 0; i < num_fields; i++ ) |
205 | 0 | delete (fields[i]); |
206 | |
|
207 | 0 | delete[] (fields); |
208 | 0 | fields = nullptr; |
209 | 0 | } |
210 | |
|
211 | 0 | return true; |
212 | 0 | } |
213 | | |
214 | 0 | bool ReaderBackend::Update() { |
215 | 0 | if ( disabled ) |
216 | 0 | return false; |
217 | | |
218 | 0 | if ( Failed() ) |
219 | 0 | return true; |
220 | | |
221 | 0 | bool success = DoUpdate(); |
222 | 0 | if ( ! success ) |
223 | 0 | DisableFrontend(); |
224 | |
|
225 | 0 | return ! disabled; // always return failure if we have been disabled in the meantime |
226 | 0 | } |
227 | | |
228 | 0 | void ReaderBackend::DisableFrontend() { |
229 | | // We might already have been disabled - e.g., due to a call to |
230 | | // error. In that case, ignore this... |
231 | 0 | if ( disabled ) |
232 | 0 | return; |
233 | | |
234 | | // We also set disabled here, because there still may be other |
235 | | // messages queued and we will dutifully ignore these from now. |
236 | 0 | disabled = true; |
237 | 0 | SendOut(new DisableMessage(frontend)); |
238 | 0 | } |
239 | | |
240 | 0 | bool ReaderBackend::OnHeartbeat(double network_time, double current_time) { |
241 | 0 | if ( Failed() ) |
242 | 0 | return true; |
243 | | |
244 | 0 | return DoHeartbeat(network_time, current_time); |
245 | 0 | } |
246 | | |
247 | 0 | void ReaderBackend::Info(const char* msg) { |
248 | 0 | SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::INFO, msg)); |
249 | 0 | MsgThread::Info(msg); |
250 | 0 | } |
251 | | |
252 | 0 | void ReaderBackend::StopWarningSuppression() { |
253 | 0 | suppress_warnings = false; |
254 | 0 | if ( warnings_suppressed > 0 ) |
255 | 0 | Warning(Fmt("Suppressed %zu warning(s)", warnings_suppressed)); |
256 | 0 | warnings_suppressed = 0; |
257 | 0 | } |
258 | | |
259 | 0 | void ReaderBackend::FailWarn(bool is_error, const char* msg, bool suppress_future) { |
260 | 0 | if ( is_error ) |
261 | 0 | Error(msg); |
262 | 0 | else { |
263 | 0 | Warning(msg); |
264 | |
|
265 | 0 | if ( suppress_future ) |
266 | 0 | suppress_warnings = true; |
267 | 0 | } |
268 | 0 | } |
269 | 0 | void ReaderBackend::Warning(const char* msg) { |
270 | 0 | if ( suppress_warnings ) { |
271 | 0 | warnings_suppressed++; |
272 | 0 | return; |
273 | 0 | } |
274 | | |
275 | 0 | SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::WARNING, msg)); |
276 | 0 | MsgThread::Warning(msg); |
277 | 0 | } |
278 | | |
279 | 0 | void ReaderBackend::Error(const char* msg) { |
280 | 0 | SendOut(new ReaderErrorMessage(frontend, ReaderErrorMessage::ERROR, msg)); |
281 | 0 | MsgThread::Error(msg); |
282 | | |
283 | | // Force errors to be fatal. |
284 | 0 | DisableFrontend(); |
285 | 0 | } |
286 | | |
287 | | } // namespace zeek::input |