1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include <util/memory/tempbuf.h>
#include <util/string/cast.h>
#include <util/stream/output.h>
#include "evdecoder.h"
#include "logparser.h"
static const char* const UNKNOWN_EVENT_CLASS = "Unknown event class";
static inline void LogError(ui64 frameAddr, const char* msg, bool strict) {
if (!strict) {
Cerr << "EventDecoder warning @" << frameAddr << ": " << msg << Endl;
} else {
ythrow yexception() << "EventDecoder error @" << frameAddr << ": " << msg;
}
}
static inline bool SkipData(IInputStream& s, size_t amount) {
return (amount == s.Skip(amount));
}
// There are 2 log fomats: the one, that allows event skip without event decode (it has stored event length)
// and another, that requires each event decode just to seek over stream. needRead == true means the latter format.
static inline THolder<TEvent> DoDecodeEvent(IInputStream& s, const TEventFilter* const filter, const bool needRead, IEventFactory* fac) {
TEventTimestamp ts;
TEventClass c;
THolder<TEvent> e;
::Load(&s, ts);
::Load(&s, c);
bool needReturn = false;
if (!filter || filter->EventAllowed(c)) {
needReturn = true;
}
if (needRead || needReturn) {
e.Reset(fac->CreateLogEvent(c));
if (!!e) {
e->Timestamp = ts;
e->Load(s);
} else if (needReturn) {
e.Reset(new TUnknownEvent(ts, c));
}
if (!needReturn) {
e.Reset(nullptr);
}
}
return e;
}
THolder<TEvent> DecodeFramed(IInputStream& inp, ui64 frameAddr, const TEventFilter* const filter, IEventFactory* fac, bool strict) {
ui32 len;
::Load(&inp, len);
if (len < sizeof(ui32)) {
ythrow TEventDecoderError() << "invalid event length";
}
TLengthLimitedInput s(&inp, len - sizeof(ui32));
try {
THolder<TEvent> e = DoDecodeEvent(s, filter, false, fac);
if (!!e) {
if (!s.Left()) {
return e;
} else if (e->Class == 0) {
if (!SkipData(s, s.Left())) {
ythrow TEventDecoderError() << "cannot skip bad event";
}
return e;
}
LogError(frameAddr, "Event is not fully read", strict);
}
} catch (const TLoadEOF&) {
if (s.Left()) {
throw;
}
LogError(frameAddr, "Unexpected event end", strict);
}
if (!SkipData(s, s.Left())) {
ythrow TEventDecoderError() << "cannot skip bad event";
}
return nullptr;
}
THolder<TEvent> DecodeEvent(IInputStream& s, bool framed, ui64 frameAddr, const TEventFilter* const filter, IEventFactory* fac, bool strict) {
try {
if (framed) {
return DecodeFramed(s, frameAddr, filter, fac, strict);
} else {
THolder<TEvent> e = DoDecodeEvent(s, filter, true, fac);
// e(0) means event, skipped by filter. Not an error.
if (!!e && !e->Class) {
ythrow TEventDecoderError() << UNKNOWN_EVENT_CLASS;
}
return e;
}
} catch (const TLoadEOF&) {
ythrow TEventDecoderError() << "unexpected frame end";
}
}
|