1 /**
2 * Copyright © 2017 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 */
16
17 #include "config.h"
18
19 #include "event_manager.hpp"
20
21 #include "event.hpp"
22 #include "event_serialize.hpp"
23
24 #include <filesystem>
25
26 namespace phosphor
27 {
28 namespace events
29 {
30
create(const std::string & eventName,const std::string & eventMessage,const std::string & objectPath,const std::string & propertyName,const std::string & propertyValue)31 void Manager::create(const std::string& eventName,
32 const std::string& eventMessage,
33 const std::string& objectPath,
34 const std::string& propertyName,
35 const std::string& propertyValue)
36 {
37 using namespace std::string_literals;
38 namespace fs = std::filesystem;
39
40 auto msg = eventMessage;
41 std::vector<std::string> additionalData;
42
43 auto propVal = propertyName + "=" + propertyValue;
44 auto path = "path="s + objectPath;
45
46 additionalData.push_back(std::move(path));
47 additionalData.push_back(std::move(propVal));
48
49 auto& eventQueue = eventMap[eventName];
50
51 // get the last event entry for this event
52 // to generate the id.
53 auto id = 0;
54 if (eventQueue.size() > 0)
55 {
56 fs::path eventPath(eventQueue.back()->objectPath);
57 id = std::stoi(std::string(eventPath.filename().c_str()));
58 id++;
59 }
60
61 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
62 std::chrono::system_clock::now().time_since_epoch())
63 .count();
64
65 auto objPath = std::string(OBJ_EVENT) + '/' + eventName + '/' +
66 std::to_string(id);
67
68 // check for capping of the events,if cap reached then erase the oldest
69 // event.
70 if (eventQueue.size() == MAX_EVENTS)
71 {
72 fs::path eventPath(EVENTS_PERSIST_PATH);
73 eventPath /= eventName;
74 eventPath /= std::to_string(eventQueue.front()->timestamp());
75 eventQueue.pop();
76 std::error_code ec;
77 fs::remove(eventPath, ec);
78 }
79
80 auto event = std::make_unique<Entry>(
81 objPath,
82 ms, // Milliseconds since 1970
83 std::move(msg), std::move(additionalData));
84 serialize(*event, eventName);
85 eventQueue.push(std::move(event));
86 }
87
restore()88 void Manager::restore()
89 {
90 if (!fs::exists(EVENTS_PERSIST_PATH) || fs::is_empty(EVENTS_PERSIST_PATH))
91 {
92 return;
93 }
94
95 for (auto& eventFile :
96 fs::recursive_directory_iterator(EVENTS_PERSIST_PATH))
97 {
98 if (!fs::is_regular_file(eventFile))
99 {
100 continue;
101 }
102
103 EventQueue events;
104
105 auto eventPath = eventFile.path().string();
106 auto pos1 = eventPath.rfind("/");
107 auto pos2 = eventPath.rfind("/", pos1 - 1) + 1;
108 auto eventName = eventPath.substr(pos2, (pos1 - pos2));
109 auto validEvent = false;
110 auto timestamp = eventFile.path().filename().string();
111 auto tsNum = std::stoll(timestamp);
112 auto objPath = std::string(OBJ_EVENT) + '/' + eventName + '/' +
113 timestamp;
114
115 auto event = std::make_unique<Entry>(objPath, tsNum);
116 if (deserialize(eventFile.path(), *event))
117 {
118 event->emit_object_added();
119 events.push(std::move(event));
120 validEvent = true;
121 }
122
123 if (validEvent)
124 {
125 eventMap[eventName] = std::move(events);
126 }
127 }
128 }
129
getManager()130 Manager& getManager()
131 {
132 static Manager mgr;
133 return mgr;
134 }
135
136 } // namespace events
137 } // namespace phosphor
138