blob: eb26d64888fe0bcccfdbe97c9ece0eafddd63556 [file] [log] [blame]
Matt Spinler23818bb2018-05-23 11:00:15 -05001/** Copyright © 2018 IBM Corporation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
Matt Spinler66e07072018-09-12 10:36:14 -050015#include "config.h"
16
17#include "callout.hpp"
18
19#include "dbus.hpp"
20
Matt Spinleref3b86f2018-05-23 11:19:10 -050021#include <cereal/archives/binary.hpp>
22#include <cereal/types/string.hpp>
Matt Spinleref3b86f2018-05-23 11:19:10 -050023#include <cereal/types/tuple.hpp>
Matt Spinler66e07072018-09-12 10:36:14 -050024#include <cereal/types/vector.hpp>
Matt Spinleref3b86f2018-05-23 11:19:10 -050025#include <experimental/filesystem>
26#include <fstream>
27#include <phosphor-logging/log.hpp>
Matt Spinleref3b86f2018-05-23 11:19:10 -050028
29CEREAL_CLASS_VERSION(ibm::logging::Callout, CALLOUT_CLASS_VERSION);
Matt Spinler23818bb2018-05-23 11:00:15 -050030
31namespace ibm
32{
33namespace logging
34{
35
Matt Spinleref3b86f2018-05-23 11:19:10 -050036using namespace phosphor::logging;
37
38/**
39 * Function required by Cereal for saving data
40 *
41 * @param[in] archive - the Cereal archive object
42 * @param[in] callout - the object to save
43 * @param[in] version - the version of the persisted data
44 */
45template <class Archive>
46void save(Archive& archive, const Callout& callout, const std::uint32_t version)
47{
48 archive(callout.id(), callout.ts(), callout.path(), callout.buildDate(),
49 callout.manufacturer(), callout.model(), callout.partNumber(),
50 callout.serialNumber());
51}
52
53/**
54 * Function required by Cereal for restoring data into an object
55 *
56 * @param[in] archive - the Cereal archive object
57 * @param[in] callout - the callout object to restore
58 * @param[in] version - the version of the persisted data
59 */
60template <class Archive>
61void load(Archive& archive, Callout& callout, const std::uint32_t version)
62{
63 size_t id;
64 uint64_t timestamp;
65 std::string inventoryPath;
66 std::string build;
67 std::string mfgr;
68 std::string model;
69 std::string pn;
70 std::string sn;
71
72 archive(id, timestamp, inventoryPath, build, mfgr, model, pn, sn);
73
74 callout.id(id);
75 callout.ts(timestamp);
76 callout.path(inventoryPath);
77 callout.buildDate(build);
78 callout.manufacturer(mfgr);
79 callout.model(model);
80 callout.partNumber(pn);
81 callout.serialNumber(sn);
82}
83
Matt Spinler23818bb2018-05-23 11:00:15 -050084Callout::Callout(sdbusplus::bus::bus& bus, const std::string& objectPath,
85 size_t id, uint64_t timestamp) :
86 CalloutObject(bus, objectPath.c_str(), true),
87 entryID(id), timestamp(timestamp)
88{
89}
90
91Callout::Callout(sdbusplus::bus::bus& bus, const std::string& objectPath,
92 const std::string& inventoryPath, size_t id,
93 uint64_t timestamp, const DbusPropertyMap& properties) :
94 CalloutObject(bus, objectPath.c_str(), true),
95 entryID(id), timestamp(timestamp)
96{
97 path(inventoryPath);
98
99 auto it = properties.find("BuildDate");
100 if (it != properties.end())
101 {
102 buildDate(it->second.get<std::string>());
103 }
104
105 it = properties.find("Manufacturer");
106 if (it != properties.end())
107 {
108 manufacturer(it->second.get<std::string>());
109 }
110
111 it = properties.find("Model");
112 if (it != properties.end())
113 {
114 model(it->second.get<std::string>());
115 }
116
117 it = properties.find("PartNumber");
118 if (it != properties.end())
119 {
120 partNumber(it->second.get<std::string>());
121 }
122
123 it = properties.find("SerialNumber");
124 if (it != properties.end())
125 {
126 serialNumber(it->second.get<std::string>());
127 }
128
129 emit_object_added();
130}
Matt Spinleref3b86f2018-05-23 11:19:10 -0500131
132void Callout::serialize(const fs::path& dir)
133{
134 auto path = getFilePath(dir);
135 std::ofstream stream(path.c_str(), std::ios::binary);
136 cereal::BinaryOutputArchive oarchive(stream);
137
138 oarchive(*this);
139}
140
141bool Callout::deserialize(const fs::path& dir)
142{
143 auto path = getFilePath(dir);
144
145 if (!fs::exists(path))
146 {
147 return false;
148 }
149
150 // Save the current ID and timestamp and then use them after
151 // deserialization to check that the data we are restoring
152 // is for the correct error log.
153
154 auto originalID = entryID;
155 auto originalTS = timestamp;
156
157 try
158 {
159 std::ifstream stream(path.c_str(), std::ios::binary);
160 cereal::BinaryInputArchive iarchive(stream);
161
162 iarchive(*this);
163 }
164 catch (std::exception& e)
165 {
166 log<level::ERR>(e.what());
167 log<level::ERR>("Failed trying to restore a Callout object",
168 entry("PATH=%s", path.c_str()));
169 fs::remove(path);
170 return false;
171 }
172
173 if ((entryID != originalID) || (timestamp != originalTS))
174 {
175 log<level::INFO>(
176 "Timestamp or ID mismatch in persisted Callout. Discarding",
177 entry("PATH=%s", path.c_str()), entry("PERSISTED_ID=%lu", entryID),
178 entry("EXPECTED_ID=%lu", originalID),
179 entry("PERSISTED_TS=%llu", timestamp),
180 entry("EXPECTED_TS=%llu", originalTS));
181 fs::remove(path);
182 return false;
183 }
184
185 return true;
186}
Matt Spinler66e07072018-09-12 10:36:14 -0500187} // namespace logging
188} // namespace ibm