blob: debcc9974abdeda9acec853b455012949753295e [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
20#include <chrono>
21#include <filesystem>
22#include <fstream>
23#include <phosphor-logging/log.hpp>
24
25namespace openpower
26{
27namespace pels
28{
29
30namespace fs = std::filesystem;
31using namespace phosphor::logging;
32
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();
67 }
68
69 uint32_t id = 0;
70
71 if (!fs::exists(idFilename))
72 {
73 auto path = fs::path(idFilename).parent_path();
74 if (!fs::exists(path))
75 {
76 fs::create_directories(path);
77 }
78
79 id = startingLogID;
80 }
81 else
82 {
83 std::ifstream idFile{idFilename};
84 idFile >> id;
85 if (idFile.fail())
86 {
87 // Just make up an ID
88 log<level::ERR>("Unable to read PEL ID File!");
89 return detail::getTimeBasedLogID();
90 }
91 }
92
93 // Wrapping shouldn't be a problem, but check anyway
94 if (id == 0x00FFFFFF)
95 {
96 id = startingLogID;
97 }
98
99 std::ofstream idFile{idFilename};
100 idFile << (id + 1);
101 if (idFile.fail())
102 {
103 // Just make up an ID so we don't reuse one next time
104 log<level::ERR>("Unable to write PEL ID File!");
105 return detail::getTimeBasedLogID();
106 }
107
108 return detail::addLogIDPrefix(id);
109}
110
111} // namespace pels
112} // namespace openpower