blob: cbe1247d0ed13bc5a4df1cb0ae08d24a4962748c [file] [log] [blame]
Matt Spinlerdf13bdb2019-07-10 16:54:13 -05001#include "log_id.hpp"
2
3#include "paths.hpp"
4
5#include <chrono>
6#include <filesystem>
7#include <fstream>
8#include <phosphor-logging/log.hpp>
9
10namespace openpower
11{
12namespace pels
13{
14
15namespace fs = std::filesystem;
16using namespace phosphor::logging;
17
18constexpr uint32_t startingLogID = 1;
19constexpr uint32_t bmcLogIDPrefix = 0x50000000;
20
21namespace detail
22{
23
24uint32_t addLogIDPrefix(uint32_t id)
25{
26 // If redundant BMCs are ever a thing, may need a different prefix.
27 return (id & 0x00FFFFFF) | bmcLogIDPrefix;
28}
29
30uint32_t getTimeBasedLogID()
31{
32 using namespace std::chrono;
33
34 // Use 3 bytes of the nanosecond count since the epoch.
35 uint32_t id =
36 duration_cast<nanoseconds>(system_clock::now().time_since_epoch())
37 .count();
38
39 return addLogIDPrefix(id);
40}
41
42} // namespace detail
43
44uint32_t generatePELID()
45{
46 // Note: there isn't a need to be thread safe.
47
48 static std::string idFilename;
49 if (idFilename.empty())
50 {
51 idFilename = getPELIDFile();
52 }
53
54 uint32_t id = 0;
55
56 if (!fs::exists(idFilename))
57 {
58 auto path = fs::path(idFilename).parent_path();
59 if (!fs::exists(path))
60 {
61 fs::create_directories(path);
62 }
63
64 id = startingLogID;
65 }
66 else
67 {
68 std::ifstream idFile{idFilename};
69 idFile >> id;
70 if (idFile.fail())
71 {
72 // Just make up an ID
73 log<level::ERR>("Unable to read PEL ID File!");
74 return detail::getTimeBasedLogID();
75 }
76 }
77
78 // Wrapping shouldn't be a problem, but check anyway
79 if (id == 0x00FFFFFF)
80 {
81 id = startingLogID;
82 }
83
84 std::ofstream idFile{idFilename};
85 idFile << (id + 1);
86 if (idFile.fail())
87 {
88 // Just make up an ID so we don't reuse one next time
89 log<level::ERR>("Unable to write PEL ID File!");
90 return detail::getTimeBasedLogID();
91 }
92
93 return detail::addLogIDPrefix(id);
94}
95
96} // namespace pels
97} // namespace openpower