1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 */
15 #include "event_source_example.h"
16
17 #include <fstream>
18 #include <iostream>
19 #include <string>
20
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/epoll.h>
24 #include <sys/inotify.h>
25
26 #include "event_loop.h"
27 #include "plugin_factory.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 REGISTER(EventSourceExample);
32 std::set<std::string> EventSourceExample::count = std::set<std::string>();
33 std::mutex EventSourceExample::mutex_;
EventSourceExample()34 EventSourceExample::EventSourceExample() : inotifyFd_(0)
35 {
36 printf("EventSourceExample::EventSourceExample()\n");
37 count.insert("EventSourceExample");
38 }
39
~EventSourceExample()40 EventSourceExample::~EventSourceExample()
41 {
42 printf("EventSourceExample::~EventSourceExample()\n");
43 count.erase("EventSourceExample");
44 }
45
OnLoad()46 void EventSourceExample::OnLoad()
47 {
48 printf("EventSourceExample::OnLoad.\n");
49
50 int isCreate = ::mkdir(SYSTEM_FAULT_LOG_PATH.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO);
51 if (!isCreate) {
52 printf("create path:%s \n", SYSTEM_FAULT_LOG_PATH.c_str());
53 }
54
55 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/aaa");
56 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/bbb");
57 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/ccc");
58
59 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/testaa");
60 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/testbb");
61 CreateWatchFile(SYSTEM_FAULT_LOG_PATH + "/testcc");
62 }
63
CreateWatchFile(const std::string & path)64 void EventSourceExample::CreateWatchFile(const std::string& path)
65 {
66 std::ofstream file(path);
67 if (!file.good()) {
68 printf("Fail to create watch file:%s.\n", path.c_str());
69 return;
70 }
71 file << "" << std::endl;
72 file.close();
73 }
74
OnUnload()75 void EventSourceExample::OnUnload()
76 {
77 printf("EventSourceExample::OnUnload.\n");
78 }
79
StartEventSource()80 void EventSourceExample::StartEventSource()
81 {
82 printf("EventSourceExample::StartEventSource.\n");
83 GetWorkLoop()->AddFileDescriptorEventCallback("EventSourceExample",
84 std::static_pointer_cast<EventSourceExample>(shared_from_this()));
85 }
86
OnFileDescriptorEvent(int fd,int type)87 bool EventSourceExample::OnFileDescriptorEvent(int fd, int type)
88 {
89 printf("EventSourceExample::OnEvent fd:%d, type:%d, inotifyFd_:%d.\n", fd, type, inotifyFd_);
90 const int bufSize = 2048;
91 char buffer[bufSize] = {0};
92 char *offset = nullptr;
93 struct inotify_event *event = nullptr;
94 if (inotifyFd_ < 0) {
95 printf("EventSourceExample Invalid inotify fd:%d", inotifyFd_);
96 return false;
97 }
98
99 int len = read(inotifyFd_, buffer, bufSize);
100 if (len < 0) {
101 printf("EventSourceExample failed to read event");
102 return false;
103 }
104
105 offset = buffer;
106 event = reinterpret_cast<struct inotify_event*>(buffer);
107 while ((reinterpret_cast<char *>(event) - buffer) < len) {
108 for (const auto &it : fileMap_) {
109 if (it.second != event->wd) {
110 continue;
111 }
112
113 if (event->name[event->len - 1] != '\0') {
114 event->name[event->len - 1] = '\0';
115 }
116 std::string filePath = it.first + "/" + std::string(event->name);
117 printf("handle file event in %s \n", filePath.c_str());
118 std::ifstream fileS(filePath);
119 if (!fileS) {
120 continue;
121 }
122 std::string fileStr;
123 fileS >> fileStr;
124 if (fileStr.empty()) {
125 printf("fileStr.empty()\n");
126 continue;
127 }
128 fileS.close();
129 CreateAndPublishEvent(filePath);
130 }
131 auto tmpLen = sizeof(struct inotify_event) + event->len;
132 event = reinterpret_cast<struct inotify_event*>(offset + tmpLen);
133 offset += tmpLen;
134 }
135 return true;
136 }
137
GetPollFd()138 int32_t EventSourceExample::GetPollFd()
139 {
140 printf("EventSourceExample::GetPollFd.\n");
141 if (inotifyFd_ > 0) {
142 return inotifyFd_;
143 }
144
145 inotifyFd_ = inotify_init();
146 if (inotifyFd_ == -1) {
147 printf("failed to init inotify: %s.\n", strerror(errno));
148 return -1;
149 }
150
151 int wd = inotify_add_watch(inotifyFd_, SYSTEM_FAULT_LOG_PATH.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO);
152 if (wd < 0) {
153 printf("failed to add watch entry : %s(%s).\n", strerror(errno), SYSTEM_FAULT_LOG_PATH.c_str());
154 close(inotifyFd_);
155 inotifyFd_ = -1;
156 return -1;
157 }
158
159 printf("GetPollFd %d \n", inotifyFd_);
160 fileMap_[SYSTEM_FAULT_LOG_PATH] = wd;
161 return inotifyFd_;
162 }
163
GetPollType()164 int32_t EventSourceExample::GetPollType()
165 {
166 printf("EventSourceExample::GetPollType.\n");
167 return EPOLLIN;
168 }
169
CreateAndPublishEvent(const std::string & file)170 void EventSourceExample::CreateAndPublishEvent(const std::string &file)
171 {
172 // create a pipeline event
173 auto event = std::make_shared<EventSourceExampleEvent>(file, static_cast<PipelineEventProducer *>(this));
174
175 // add general information
176 const int demoBufSize = 128;
177 auto bufPtr = reinterpret_cast<char *>(malloc(demoBufSize));
178 if (bufPtr == nullptr) {
179 return;
180 }
181 event->data_ = bufPtr;
182 event->addon_ = file;
183 event->isPipeline_ = true;
184 // add special information
185 event->messageType_ = Event::MessageType::FAULT_EVENT;
186 if (file == (SYSTEM_FAULT_LOG_PATH + "/aaa")) {
187 event->eventId_ = PIPELINE_EVENT_ID_AAA;
188 } else if (file == (SYSTEM_FAULT_LOG_PATH + "/bbb")) {
189 event->eventId_ = PIPELINE_EVENT_ID_BBB;
190 } else if (file == (SYSTEM_FAULT_LOG_PATH + "/ccc")) {
191 event->eventId_ = PIPELINE_EVENT_ID_CCC;
192 event->SetValue("Pipeline", "Repack");
193 } else if (file == (SYSTEM_FAULT_LOG_PATH + "/testaa")) {
194 event->eventId_ = PIPELINE_EVENT_ID_TAA;
195 event->eventName_ = "testaa";
196 } else if (file == (SYSTEM_FAULT_LOG_PATH + "/testbb")) {
197 event->eventId_ = 0;
198 event->eventName_ = "testbb";
199 } else if (file == (SYSTEM_FAULT_LOG_PATH + "/testcc")) {
200 event->eventId_ = 0;
201 event->eventName_ = "testcc";
202 } else {
203 return;
204 }
205 PublishPipelineEvent(std::dynamic_pointer_cast<PipelineEvent>(event));
206 }
207
Recycle(PipelineEvent * event)208 void EventSourceExample::Recycle(PipelineEvent *event)
209 {
210 printf("EventSourceExample::Recycle.\n");
211 auto eventPtr = static_cast<EventSourceExampleEvent *>(event);
212 if (eventPtr == nullptr || eventPtr->data_ == nullptr) {
213 return;
214 }
215 free(eventPtr->data_);
216 eventPtr->data_ = nullptr;
217 printf("Recycle event:%s.\n", eventPtr->addon_.c_str());
218 }
219
PauseDispatch(std::weak_ptr<Plugin> plugin)220 void EventSourceExample::PauseDispatch(std::weak_ptr<Plugin> plugin)
221 {
222 auto requester = plugin.lock();
223 if (requester != nullptr) {
224 printf("process pause dispatch event from plugin:%s.\n", requester->GetName().c_str());
225 }
226 }
227 } // namespace HiviewDFX
228 } // namespace OHOS
229