xref: /openbmc/ibm-logging/callout.cpp (revision 6a2b8956487404dd2f7e4aa06055c24a2b7271e1)
123818bb0SMatt Spinler /** Copyright © 2018 IBM Corporation
223818bb0SMatt Spinler  *
323818bb0SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
423818bb0SMatt Spinler  * you may not use this file except in compliance with the License.
523818bb0SMatt Spinler  * You may obtain a copy of the License at
623818bb0SMatt Spinler  *
723818bb0SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
823818bb0SMatt Spinler  *
923818bb0SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
1023818bb0SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
1123818bb0SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1223818bb0SMatt Spinler  * See the License for the specific language governing permissions and
1323818bb0SMatt Spinler  * limitations under the License.
1423818bb0SMatt Spinler  */
1566e07073SMatt Spinler #include "config.h"
1666e07073SMatt Spinler 
1766e07073SMatt Spinler #include "callout.hpp"
1866e07073SMatt Spinler 
1966e07073SMatt Spinler #include "dbus.hpp"
2066e07073SMatt Spinler 
21ef3b86f2SMatt Spinler #include <cereal/archives/binary.hpp>
22ef3b86f2SMatt Spinler #include <cereal/types/string.hpp>
23ef3b86f2SMatt Spinler #include <cereal/types/tuple.hpp>
2466e07073SMatt Spinler #include <cereal/types/vector.hpp>
25*6a2b8956SPatrick Williams #include <phosphor-logging/log.hpp>
26*6a2b8956SPatrick Williams 
27ef3b86f2SMatt Spinler #include <experimental/filesystem>
28ef3b86f2SMatt Spinler #include <fstream>
29ef3b86f2SMatt Spinler 
30ef3b86f2SMatt Spinler CEREAL_CLASS_VERSION(ibm::logging::Callout, CALLOUT_CLASS_VERSION);
3123818bb0SMatt Spinler 
3223818bb0SMatt Spinler namespace ibm
3323818bb0SMatt Spinler {
3423818bb0SMatt Spinler namespace logging
3523818bb0SMatt Spinler {
3623818bb0SMatt Spinler 
37ef3b86f2SMatt Spinler using namespace phosphor::logging;
38ef3b86f2SMatt Spinler 
39ef3b86f2SMatt Spinler /**
40ef3b86f2SMatt Spinler  * Function required by Cereal for saving data
41ef3b86f2SMatt Spinler  *
42ef3b86f2SMatt Spinler  * @param[in] archive - the Cereal archive object
43ef3b86f2SMatt Spinler  * @param[in] callout - the object to save
44ef3b86f2SMatt Spinler  * @param[in] version - the version of the persisted data
45ef3b86f2SMatt Spinler  */
46ef3b86f2SMatt Spinler template <class Archive>
save(Archive & archive,const Callout & callout,const std::uint32_t version)47ef3b86f2SMatt Spinler void save(Archive& archive, const Callout& callout, const std::uint32_t version)
48ef3b86f2SMatt Spinler {
49ef3b86f2SMatt Spinler     archive(callout.id(), callout.ts(), callout.path(), callout.buildDate(),
50ef3b86f2SMatt Spinler             callout.manufacturer(), callout.model(), callout.partNumber(),
51ef3b86f2SMatt Spinler             callout.serialNumber());
52ef3b86f2SMatt Spinler }
53ef3b86f2SMatt Spinler 
54ef3b86f2SMatt Spinler /**
55ef3b86f2SMatt Spinler  * Function required by Cereal for restoring data into an object
56ef3b86f2SMatt Spinler  *
57ef3b86f2SMatt Spinler  * @param[in] archive - the Cereal archive object
58ef3b86f2SMatt Spinler  * @param[in] callout - the callout object to restore
59ef3b86f2SMatt Spinler  * @param[in] version - the version of the persisted data
60ef3b86f2SMatt Spinler  */
61ef3b86f2SMatt Spinler template <class Archive>
load(Archive & archive,Callout & callout,const std::uint32_t version)62ef3b86f2SMatt Spinler void load(Archive& archive, Callout& callout, const std::uint32_t version)
63ef3b86f2SMatt Spinler {
64ef3b86f2SMatt Spinler     size_t id;
65ef3b86f2SMatt Spinler     uint64_t timestamp;
66ef3b86f2SMatt Spinler     std::string inventoryPath;
67ef3b86f2SMatt Spinler     std::string build;
68ef3b86f2SMatt Spinler     std::string mfgr;
69ef3b86f2SMatt Spinler     std::string model;
70ef3b86f2SMatt Spinler     std::string pn;
71ef3b86f2SMatt Spinler     std::string sn;
72ef3b86f2SMatt Spinler 
73ef3b86f2SMatt Spinler     archive(id, timestamp, inventoryPath, build, mfgr, model, pn, sn);
74ef3b86f2SMatt Spinler 
75ef3b86f2SMatt Spinler     callout.id(id);
76ef3b86f2SMatt Spinler     callout.ts(timestamp);
77ef3b86f2SMatt Spinler     callout.path(inventoryPath);
78ef3b86f2SMatt Spinler     callout.buildDate(build);
79ef3b86f2SMatt Spinler     callout.manufacturer(mfgr);
80ef3b86f2SMatt Spinler     callout.model(model);
81ef3b86f2SMatt Spinler     callout.partNumber(pn);
82ef3b86f2SMatt Spinler     callout.serialNumber(sn);
83ef3b86f2SMatt Spinler }
84ef3b86f2SMatt Spinler 
Callout(sdbusplus::bus_t & bus,const std::string & objectPath,size_t id,uint64_t timestamp)858123a713SPatrick Williams Callout::Callout(sdbusplus::bus_t& bus, const std::string& objectPath,
8623818bb0SMatt Spinler                  size_t id, uint64_t timestamp) :
87c0763620SPatrick Williams     CalloutObject(bus, objectPath.c_str(), CalloutObject::action::defer_emit),
8823818bb0SMatt Spinler     entryID(id), timestamp(timestamp)
89*6a2b8956SPatrick Williams {}
9023818bb0SMatt Spinler 
Callout(sdbusplus::bus_t & bus,const std::string & objectPath,const std::string & inventoryPath,size_t id,uint64_t timestamp,const DbusPropertyMap & properties)918123a713SPatrick Williams Callout::Callout(sdbusplus::bus_t& bus, const std::string& objectPath,
9223818bb0SMatt Spinler                  const std::string& inventoryPath, size_t id,
9323818bb0SMatt Spinler                  uint64_t timestamp, const DbusPropertyMap& properties) :
94c0763620SPatrick Williams     CalloutObject(bus, objectPath.c_str(), CalloutObject::action::defer_emit),
9523818bb0SMatt Spinler     entryID(id), timestamp(timestamp)
9623818bb0SMatt Spinler {
9723818bb0SMatt Spinler     path(inventoryPath);
9823818bb0SMatt Spinler 
9923818bb0SMatt Spinler     auto it = properties.find("BuildDate");
10023818bb0SMatt Spinler     if (it != properties.end())
10123818bb0SMatt Spinler     {
102b5af3a3fSPatrick Williams         buildDate(std::get<std::string>(it->second));
10323818bb0SMatt Spinler     }
10423818bb0SMatt Spinler 
10523818bb0SMatt Spinler     it = properties.find("Manufacturer");
10623818bb0SMatt Spinler     if (it != properties.end())
10723818bb0SMatt Spinler     {
108b5af3a3fSPatrick Williams         manufacturer(std::get<std::string>(it->second));
10923818bb0SMatt Spinler     }
11023818bb0SMatt Spinler 
11123818bb0SMatt Spinler     it = properties.find("Model");
11223818bb0SMatt Spinler     if (it != properties.end())
11323818bb0SMatt Spinler     {
114b5af3a3fSPatrick Williams         model(std::get<std::string>(it->second));
11523818bb0SMatt Spinler     }
11623818bb0SMatt Spinler 
11723818bb0SMatt Spinler     it = properties.find("PartNumber");
11823818bb0SMatt Spinler     if (it != properties.end())
11923818bb0SMatt Spinler     {
120b5af3a3fSPatrick Williams         partNumber(std::get<std::string>(it->second));
12123818bb0SMatt Spinler     }
12223818bb0SMatt Spinler 
12323818bb0SMatt Spinler     it = properties.find("SerialNumber");
12423818bb0SMatt Spinler     if (it != properties.end())
12523818bb0SMatt Spinler     {
126b5af3a3fSPatrick Williams         serialNumber(std::get<std::string>(it->second));
12723818bb0SMatt Spinler     }
12823818bb0SMatt Spinler 
12923818bb0SMatt Spinler     emit_object_added();
13023818bb0SMatt Spinler }
131ef3b86f2SMatt Spinler 
serialize(const fs::path & dir)132ef3b86f2SMatt Spinler void Callout::serialize(const fs::path& dir)
133ef3b86f2SMatt Spinler {
134ef3b86f2SMatt Spinler     auto path = getFilePath(dir);
135ef3b86f2SMatt Spinler     std::ofstream stream(path.c_str(), std::ios::binary);
136ef3b86f2SMatt Spinler     cereal::BinaryOutputArchive oarchive(stream);
137ef3b86f2SMatt Spinler 
138ef3b86f2SMatt Spinler     oarchive(*this);
139ef3b86f2SMatt Spinler }
140ef3b86f2SMatt Spinler 
deserialize(const fs::path & dir)141ef3b86f2SMatt Spinler bool Callout::deserialize(const fs::path& dir)
142ef3b86f2SMatt Spinler {
143ef3b86f2SMatt Spinler     auto path = getFilePath(dir);
144ef3b86f2SMatt Spinler 
145ef3b86f2SMatt Spinler     if (!fs::exists(path))
146ef3b86f2SMatt Spinler     {
147ef3b86f2SMatt Spinler         return false;
148ef3b86f2SMatt Spinler     }
149ef3b86f2SMatt Spinler 
150ef3b86f2SMatt Spinler     // Save the current ID and timestamp and then use them after
151ef3b86f2SMatt Spinler     // deserialization to check that the data we are restoring
152ef3b86f2SMatt Spinler     // is for the correct error log.
153ef3b86f2SMatt Spinler 
154ef3b86f2SMatt Spinler     auto originalID = entryID;
155ef3b86f2SMatt Spinler     auto originalTS = timestamp;
156ef3b86f2SMatt Spinler 
157ef3b86f2SMatt Spinler     try
158ef3b86f2SMatt Spinler     {
159ef3b86f2SMatt Spinler         std::ifstream stream(path.c_str(), std::ios::binary);
160ef3b86f2SMatt Spinler         cereal::BinaryInputArchive iarchive(stream);
161ef3b86f2SMatt Spinler 
162ef3b86f2SMatt Spinler         iarchive(*this);
163ef3b86f2SMatt Spinler     }
164bf9ea8adSPatrick Williams     catch (const std::exception& e)
165ef3b86f2SMatt Spinler     {
166ef3b86f2SMatt Spinler         log<level::ERR>(e.what());
167ef3b86f2SMatt Spinler         log<level::ERR>("Failed trying to restore a Callout object",
168ef3b86f2SMatt Spinler                         entry("PATH=%s", path.c_str()));
169ef3b86f2SMatt Spinler         fs::remove(path);
170ef3b86f2SMatt Spinler         return false;
171ef3b86f2SMatt Spinler     }
172ef3b86f2SMatt Spinler 
173ef3b86f2SMatt Spinler     if ((entryID != originalID) || (timestamp != originalTS))
174ef3b86f2SMatt Spinler     {
175ef3b86f2SMatt Spinler         log<level::INFO>(
176ef3b86f2SMatt Spinler             "Timestamp or ID mismatch in persisted Callout. Discarding",
177ef3b86f2SMatt Spinler             entry("PATH=%s", path.c_str()), entry("PERSISTED_ID=%lu", entryID),
178ef3b86f2SMatt Spinler             entry("EXPECTED_ID=%lu", originalID),
179ef3b86f2SMatt Spinler             entry("PERSISTED_TS=%llu", timestamp),
180ef3b86f2SMatt Spinler             entry("EXPECTED_TS=%llu", originalTS));
181ef3b86f2SMatt Spinler         fs::remove(path);
182ef3b86f2SMatt Spinler         return false;
183ef3b86f2SMatt Spinler     }
184ef3b86f2SMatt Spinler 
185ef3b86f2SMatt Spinler     return true;
186ef3b86f2SMatt Spinler }
18766e07073SMatt Spinler } // namespace logging
18866e07073SMatt Spinler } // namespace ibm
189