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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
#include "utils/journal_read_state.hpp"
#include "logging.hpp"
#include <systemd/sd-journal.h>
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
namespace redfish
{
JournalReadState::JournalReadState() = default;
std::optional<JournalReadState> JournalReadState::openDefaults()
{
JournalReadState state;
int ret = sd_journal_open(&state.journal, SD_JOURNAL_LOCAL_ONLY);
if (ret < 0)
{
BMCWEB_LOG_ERROR("failed to open journal: {}", ret);
return std::nullopt;
}
return state;
}
std::optional<JournalReadState> JournalReadState::openFile(
const std::string& path)
{
JournalReadState state;
std::array<const char*, 2> paths{path.c_str(), nullptr};
int ret = sd_journal_open_files(&state.journal, paths.data(), 0);
if (ret < 0)
{
BMCWEB_LOG_ERROR("failed to open journal file: {} {}", path, ret);
return std::nullopt;
}
return state;
}
int JournalReadState::next() const
{
return sd_journal_next(journal);
}
int JournalReadState::nextSkip(size_t skip) const
{
return sd_journal_next_skip(journal, skip);
}
int JournalReadState::previous() const
{
return sd_journal_previous(journal);
}
int JournalReadState::seekTail() const
{
return sd_journal_seek_tail(journal);
}
int JournalReadState::seekHead() const
{
return sd_journal_seek_head(journal);
}
int JournalReadState::seekCursor(const std::string& cursor) const
{
return sd_journal_seek_cursor(journal, cursor.c_str());
}
int JournalReadState::testCursor(const std::string& cursor) const
{
return sd_journal_test_cursor(journal, cursor.c_str());
}
std::string JournalReadState::getCursor() const
{
char* cursor = nullptr;
if (sd_journal_get_cursor(journal, &cursor) < 0)
{
return "";
}
if (cursor == nullptr)
{
return "";
}
std::unique_ptr<char, decltype(&free)> cursorPtr(cursor, &free);
return {cursorPtr.get()};
}
std::optional<uint64_t> JournalReadState::getRealtimeUsec() const
{
uint64_t timestamp = 0;
int ret = sd_journal_get_realtime_usec(journal, ×tamp);
if (ret < 0)
{
return std::nullopt;
}
return timestamp;
}
std::string JournalReadState::getData(const char* field) const
{
const void* dataVoid = nullptr;
size_t length = 0;
int ret = sd_journal_get_data(journal, field, &dataVoid, &length);
if (ret < 0)
{
BMCWEB_LOG_ERROR("failed to get data for field {}: {}", field, ret);
return {};
}
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::string_view data(reinterpret_cast<const char*>(dataVoid), length);
std::string_view fieldView(field);
if (data.size() < fieldView.size() + 1)
{
return {};
}
if (data.starts_with(fieldView) && data[fieldView.size()] == '=')
{
data.remove_prefix(fieldView.size() + 1);
}
return std::string{data};
}
int JournalReadState::getSeqnum(uint64_t& seqnum) const
{
#if LIBSYSTEMD_VERSION >= 254
return sd_journal_get_seqnum(journal, &seqnum, nullptr);
#else
return -1;
#endif
}
JournalReadState::~JournalReadState()
{
if (journal != nullptr)
{
sd_journal_close(journal);
}
}
} // namespace redfish
|