1 #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 
10 namespace openpower
11 {
12 namespace pels
13 {
14 
15 namespace fs = std::filesystem;
16 using namespace phosphor::logging;
17 
18 constexpr uint32_t startingLogID = 1;
19 constexpr uint32_t bmcLogIDPrefix = 0x50000000;
20 
21 namespace detail
22 {
23 
24 uint32_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 
30 uint32_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 
44 uint32_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
98