blob: 5fda994ccc8734b9c7d9ce2179cfd9a96323236b [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050016#include "log_id.hpp"
17
18#include "paths.hpp"
19
Arya K Padman5bc26532024-04-10 06:19:25 -050020#include <phosphor-logging/lg2.hpp>
Patrick Williams2544b412022-10-04 08:41:06 -050021
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050022#include <chrono>
23#include <filesystem>
24#include <fstream>
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050025
26namespace openpower
27{
28namespace pels
29{
30
31namespace fs = std::filesystem;
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050032
33constexpr uint32_t startingLogID = 1;
34constexpr uint32_t bmcLogIDPrefix = 0x50000000;
35
36namespace detail
37{
38
39uint32_t addLogIDPrefix(uint32_t id)
40{
41 // If redundant BMCs are ever a thing, may need a different prefix.
42 return (id & 0x00FFFFFF) | bmcLogIDPrefix;
43}
44
45uint32_t getTimeBasedLogID()
46{
47 using namespace std::chrono;
48
49 // Use 3 bytes of the nanosecond count since the epoch.
50 uint32_t id =
51 duration_cast<nanoseconds>(system_clock::now().time_since_epoch())
52 .count();
53
54 return addLogIDPrefix(id);
55}
56
57} // namespace detail
58
59uint32_t generatePELID()
60{
61 // Note: there isn't a need to be thread safe.
62
63 static std::string idFilename;
64 if (idFilename.empty())
65 {
66 idFilename = getPELIDFile();
Sumit Kumarf380c512021-11-19 06:07:31 -060067 checkFileForZeroData(idFilename);
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050068 }
69
70 uint32_t id = 0;
71
72 if (!fs::exists(idFilename))
73 {
74 auto path = fs::path(idFilename).parent_path();
75 if (!fs::exists(path))
76 {
77 fs::create_directories(path);
78 }
79
80 id = startingLogID;
81 }
82 else
83 {
84 std::ifstream idFile{idFilename};
85 idFile >> id;
86 if (idFile.fail())
87 {
88 // Just make up an ID
Arya K Padman5bc26532024-04-10 06:19:25 -050089 lg2::error("Unable to read PEL ID File!");
Matt Spinlerdf13bdb2019-07-10 16:54:13 -050090 return detail::getTimeBasedLogID();
91 }
92 }
93
94 // Wrapping shouldn't be a problem, but check anyway
95 if (id == 0x00FFFFFF)
96 {
97 id = startingLogID;
98 }
99
100 std::ofstream idFile{idFilename};
101 idFile << (id + 1);
102 if (idFile.fail())
103 {
104 // Just make up an ID so we don't reuse one next time
Arya K Padman5bc26532024-04-10 06:19:25 -0500105 lg2::error("Unable to write PEL ID File!");
Matt Spinlerdf13bdb2019-07-10 16:54:13 -0500106 return detail::getTimeBasedLogID();
107 }
108
109 return detail::addLogIDPrefix(id);
110}
111
Sumit Kumarf380c512021-11-19 06:07:31 -0600112void checkFileForZeroData(const std::string& filename)
113{
114 if (fs::exists(filename))
115 {
116 char ch;
117
118 std::ifstream rf{filename, std::ios::binary};
119 rf.read(&ch, sizeof(ch));
120 while (ch == '\0')
121 {
122 if (rf.eof())
123 {
124 fs::remove(filename);
Arya K Padman5bc26532024-04-10 06:19:25 -0500125 lg2::warning("PEL ID file seems corrupted. Deleting it.");
Sumit Kumarf380c512021-11-19 06:07:31 -0600126 break;
127 }
128 rf.read(&ch, sizeof(ch));
129 }
130 }
131}
Matt Spinlerdf13bdb2019-07-10 16:54:13 -0500132} // namespace pels
133} // namespace openpower