xref: /openbmc/phosphor-event/message.cpp (revision acdc2a909e7464111b259fb94509dcf8dab7c626)
1*acdc2a90SMatthew Barth #include <iostream>
2*acdc2a90SMatthew Barth #include <fstream>
3*acdc2a90SMatthew Barth #include <iomanip>
4*acdc2a90SMatthew Barth #include <cstdint>
5*acdc2a90SMatthew Barth #include <string>
6*acdc2a90SMatthew Barth #include <sys/types.h>
7*acdc2a90SMatthew Barth #include <dirent.h>
8*acdc2a90SMatthew Barth #include <sstream>
9*acdc2a90SMatthew Barth #include <sys/stat.h>
10*acdc2a90SMatthew Barth #include <cstring>
11*acdc2a90SMatthew Barth #include "message.hpp"
12*acdc2a90SMatthew Barth #include <time.h>
13*acdc2a90SMatthew Barth #include <stddef.h>
14*acdc2a90SMatthew Barth #include <cstdio>
15*acdc2a90SMatthew Barth #include <syslog.h>
16*acdc2a90SMatthew Barth 
17*acdc2a90SMatthew Barth const uint32_t g_eyecatcher = 0x4F424D43; // OBMC
18*acdc2a90SMatthew Barth const uint16_t g_version    = 1;
19*acdc2a90SMatthew Barth 
20*acdc2a90SMatthew Barth struct logheader_t {
21*acdc2a90SMatthew Barth 	uint32_t eyecatcher;
22*acdc2a90SMatthew Barth 	uint16_t version;
23*acdc2a90SMatthew Barth 	uint16_t logid;
24*acdc2a90SMatthew Barth 	time_t   timestamp;
25*acdc2a90SMatthew Barth 	uint16_t detailsoffset;
26*acdc2a90SMatthew Barth 	uint16_t messagelen;
27*acdc2a90SMatthew Barth 	uint16_t severitylen;
28*acdc2a90SMatthew Barth 	uint16_t associationlen;
29*acdc2a90SMatthew Barth 	uint16_t reportedbylen;
30*acdc2a90SMatthew Barth 	uint16_t debugdatalen;
31*acdc2a90SMatthew Barth };
32*acdc2a90SMatthew Barth 
33*acdc2a90SMatthew Barth size_t get_file_size(string fn);
34*acdc2a90SMatthew Barth 
35*acdc2a90SMatthew Barth 
event_manager(string path,size_t reqmaxsize,uint16_t reqmaxlogs)36*acdc2a90SMatthew Barth event_manager::event_manager(string path, size_t reqmaxsize, uint16_t reqmaxlogs)
37*acdc2a90SMatthew Barth {
38*acdc2a90SMatthew Barth 	uint16_t x;
39*acdc2a90SMatthew Barth 	eventpath = path;
40*acdc2a90SMatthew Barth 	latestid = 0;
41*acdc2a90SMatthew Barth 	dirp = NULL;
42*acdc2a90SMatthew Barth 	logcount = 0;
43*acdc2a90SMatthew Barth 	maxsize = -1;
44*acdc2a90SMatthew Barth 	maxlogs = -1;
45*acdc2a90SMatthew Barth 	currentsize = get_managed_size();
46*acdc2a90SMatthew Barth 
47*acdc2a90SMatthew Barth 	if (reqmaxsize)
48*acdc2a90SMatthew Barth 		maxsize = reqmaxsize;
49*acdc2a90SMatthew Barth 
50*acdc2a90SMatthew Barth 	if (reqmaxlogs)
51*acdc2a90SMatthew Barth 		maxlogs = reqmaxlogs;
52*acdc2a90SMatthew Barth 
53*acdc2a90SMatthew Barth 	// examine the files being managed and advance latestid to that value
54*acdc2a90SMatthew Barth 	while ( (x = next_log()) ) {
55*acdc2a90SMatthew Barth 		logcount++;
56*acdc2a90SMatthew Barth 		if ( x > latestid )
57*acdc2a90SMatthew Barth 			latestid = x;
58*acdc2a90SMatthew Barth 	}
59*acdc2a90SMatthew Barth 
60*acdc2a90SMatthew Barth 	return;
61*acdc2a90SMatthew Barth }
62*acdc2a90SMatthew Barth 
~event_manager()63*acdc2a90SMatthew Barth event_manager::~event_manager()
64*acdc2a90SMatthew Barth {
65*acdc2a90SMatthew Barth 	if (dirp)
66*acdc2a90SMatthew Barth 		closedir(dirp);
67*acdc2a90SMatthew Barth 
68*acdc2a90SMatthew Barth 	return;
69*acdc2a90SMatthew Barth }
70*acdc2a90SMatthew Barth 
71*acdc2a90SMatthew Barth 
is_logid_a_log(uint16_t logid)72*acdc2a90SMatthew Barth bool event_manager::is_logid_a_log(uint16_t logid)
73*acdc2a90SMatthew Barth {
74*acdc2a90SMatthew Barth 	std::ostringstream buffer;
75*acdc2a90SMatthew Barth 	buffer  << int(logid);
76*acdc2a90SMatthew Barth 	return is_file_a_log(buffer.str());
77*acdc2a90SMatthew Barth }
78*acdc2a90SMatthew Barth 
79*acdc2a90SMatthew Barth 
is_file_a_log(string str)80*acdc2a90SMatthew Barth bool event_manager::is_file_a_log(string str)
81*acdc2a90SMatthew Barth {
82*acdc2a90SMatthew Barth 	std::ostringstream buffer;
83*acdc2a90SMatthew Barth 	ifstream f;
84*acdc2a90SMatthew Barth 	logheader_t hdr;
85*acdc2a90SMatthew Barth 
86*acdc2a90SMatthew Barth 	if (!str.compare("."))
87*acdc2a90SMatthew Barth 		return 0;
88*acdc2a90SMatthew Barth 
89*acdc2a90SMatthew Barth 	if (!str.compare(".."))
90*acdc2a90SMatthew Barth 		return 0;
91*acdc2a90SMatthew Barth 
92*acdc2a90SMatthew Barth 	buffer << eventpath << "/" << str;
93*acdc2a90SMatthew Barth 
94*acdc2a90SMatthew Barth 	f.open( buffer.str(), ios::binary);
95*acdc2a90SMatthew Barth 
96*acdc2a90SMatthew Barth 	if (!f.good()) {
97*acdc2a90SMatthew Barth 		f.close();
98*acdc2a90SMatthew Barth 		return 0;
99*acdc2a90SMatthew Barth 	}
100*acdc2a90SMatthew Barth 
101*acdc2a90SMatthew Barth 	f.read((char*)&hdr, sizeof(hdr));
102*acdc2a90SMatthew Barth 	f.close();
103*acdc2a90SMatthew Barth 
104*acdc2a90SMatthew Barth 	if (hdr.eyecatcher != g_eyecatcher)
105*acdc2a90SMatthew Barth 		return 0;
106*acdc2a90SMatthew Barth 
107*acdc2a90SMatthew Barth 	return 1;
108*acdc2a90SMatthew Barth }
109*acdc2a90SMatthew Barth 
log_count(void)110*acdc2a90SMatthew Barth uint16_t event_manager::log_count(void)
111*acdc2a90SMatthew Barth {
112*acdc2a90SMatthew Barth 	return logcount;
113*acdc2a90SMatthew Barth }
latest_log_id(void)114*acdc2a90SMatthew Barth uint16_t event_manager::latest_log_id(void)
115*acdc2a90SMatthew Barth {
116*acdc2a90SMatthew Barth 	return latestid;
117*acdc2a90SMatthew Barth }
new_log_id(void)118*acdc2a90SMatthew Barth uint16_t event_manager::new_log_id(void)
119*acdc2a90SMatthew Barth {
120*acdc2a90SMatthew Barth 	return ++latestid;
121*acdc2a90SMatthew Barth }
next_log_refresh(void)122*acdc2a90SMatthew Barth void event_manager::next_log_refresh(void)
123*acdc2a90SMatthew Barth {
124*acdc2a90SMatthew Barth 	if (dirp) {
125*acdc2a90SMatthew Barth 		closedir(dirp);
126*acdc2a90SMatthew Barth 		dirp = NULL;
127*acdc2a90SMatthew Barth 	}
128*acdc2a90SMatthew Barth 
129*acdc2a90SMatthew Barth 	return;
130*acdc2a90SMatthew Barth }
131*acdc2a90SMatthew Barth 
next_log(void)132*acdc2a90SMatthew Barth uint16_t event_manager::next_log(void)
133*acdc2a90SMatthew Barth {
134*acdc2a90SMatthew Barth 	std::ostringstream buffer;
135*acdc2a90SMatthew Barth 	struct dirent *ent;
136*acdc2a90SMatthew Barth 	uint16_t id;
137*acdc2a90SMatthew Barth 
138*acdc2a90SMatthew Barth 	if (dirp == NULL)
139*acdc2a90SMatthew Barth 		dirp = opendir(eventpath.c_str());
140*acdc2a90SMatthew Barth 
141*acdc2a90SMatthew Barth 	if (dirp) {
142*acdc2a90SMatthew Barth 		do {
143*acdc2a90SMatthew Barth 			ent = readdir(dirp);
144*acdc2a90SMatthew Barth 
145*acdc2a90SMatthew Barth 			if (ent == NULL)
146*acdc2a90SMatthew Barth 				break;
147*acdc2a90SMatthew Barth 
148*acdc2a90SMatthew Barth 			string str(ent->d_name);
149*acdc2a90SMatthew Barth 
150*acdc2a90SMatthew Barth 			if (is_file_a_log(str)) {
151*acdc2a90SMatthew Barth 				id = (uint16_t) atoi(str.c_str());
152*acdc2a90SMatthew Barth 				break;
153*acdc2a90SMatthew Barth 			}
154*acdc2a90SMatthew Barth 
155*acdc2a90SMatthew Barth 		} while( 1 );
156*acdc2a90SMatthew Barth 	} else {
157*acdc2a90SMatthew Barth 		cerr << "Error opening directory " << eventpath << endl;
158*acdc2a90SMatthew Barth 		ent = NULL;
159*acdc2a90SMatthew Barth 		id = 0;
160*acdc2a90SMatthew Barth 	}
161*acdc2a90SMatthew Barth 
162*acdc2a90SMatthew Barth 	if (ent == NULL) {
163*acdc2a90SMatthew Barth 		closedir(dirp);
164*acdc2a90SMatthew Barth 		dirp = NULL;
165*acdc2a90SMatthew Barth 	}
166*acdc2a90SMatthew Barth 
167*acdc2a90SMatthew Barth 	return  ((ent == NULL) ? 0 : id);
168*acdc2a90SMatthew Barth }
169*acdc2a90SMatthew Barth 
170*acdc2a90SMatthew Barth 
create(event_record_t * rec)171*acdc2a90SMatthew Barth uint16_t event_manager::create(event_record_t *rec)
172*acdc2a90SMatthew Barth {
173*acdc2a90SMatthew Barth 	rec->logid = new_log_id();
174*acdc2a90SMatthew Barth 	rec->timestamp = time(NULL);
175*acdc2a90SMatthew Barth 
176*acdc2a90SMatthew Barth 	return create_log_event(rec);
177*acdc2a90SMatthew Barth }
178*acdc2a90SMatthew Barth 
getlen(const char * s)179*acdc2a90SMatthew Barth inline uint16_t getlen(const char *s)
180*acdc2a90SMatthew Barth {
181*acdc2a90SMatthew Barth 	return (uint16_t) (1 + strlen(s));
182*acdc2a90SMatthew Barth }
183*acdc2a90SMatthew Barth 
184*acdc2a90SMatthew Barth 
185*acdc2a90SMatthew Barth /* If everything is working correctly, return file size, */
186*acdc2a90SMatthew Barth /* Otherwise return 0 */
get_file_size(string fn)187*acdc2a90SMatthew Barth size_t get_file_size(string fn)
188*acdc2a90SMatthew Barth {
189*acdc2a90SMatthew Barth 	struct stat f_stat;
190*acdc2a90SMatthew Barth 	int r = -1;
191*acdc2a90SMatthew Barth 
192*acdc2a90SMatthew Barth 	r = stat(fn.c_str(), &f_stat);
193*acdc2a90SMatthew Barth 
194*acdc2a90SMatthew Barth 	if (r < 0) {
195*acdc2a90SMatthew Barth 		fprintf(stderr, "Error get_file_size() for %s, %s\n",
196*acdc2a90SMatthew Barth 				fn.c_str(),
197*acdc2a90SMatthew Barth 				strerror(errno));
198*acdc2a90SMatthew Barth 		return 0;
199*acdc2a90SMatthew Barth 	}
200*acdc2a90SMatthew Barth 
201*acdc2a90SMatthew Barth 	return (f_stat.st_size);
202*acdc2a90SMatthew Barth }
203*acdc2a90SMatthew Barth 
204*acdc2a90SMatthew Barth 
get_managed_size(void)205*acdc2a90SMatthew Barth size_t event_manager::get_managed_size(void)
206*acdc2a90SMatthew Barth {
207*acdc2a90SMatthew Barth 	DIR *dirp;
208*acdc2a90SMatthew Barth 	std::ostringstream buffer;
209*acdc2a90SMatthew Barth 	struct dirent *ent;
210*acdc2a90SMatthew Barth 	ifstream f;
211*acdc2a90SMatthew Barth 
212*acdc2a90SMatthew Barth 	size_t db_size = 0;
213*acdc2a90SMatthew Barth 
214*acdc2a90SMatthew Barth 	dirp = opendir(eventpath.c_str());
215*acdc2a90SMatthew Barth 
216*acdc2a90SMatthew Barth 	if (dirp) {
217*acdc2a90SMatthew Barth 		while ( (ent = readdir(dirp)) != NULL ) {
218*acdc2a90SMatthew Barth 
219*acdc2a90SMatthew Barth 			string str(ent->d_name);
220*acdc2a90SMatthew Barth 
221*acdc2a90SMatthew Barth 			if (is_file_a_log(str)) {
222*acdc2a90SMatthew Barth 				buffer.str("");
223*acdc2a90SMatthew Barth 				buffer << eventpath << "/" << str.c_str();
224*acdc2a90SMatthew Barth 				db_size += get_file_size(buffer.str());
225*acdc2a90SMatthew Barth 			}
226*acdc2a90SMatthew Barth 		}
227*acdc2a90SMatthew Barth 	}
228*acdc2a90SMatthew Barth 
229*acdc2a90SMatthew Barth 	closedir(dirp);
230*acdc2a90SMatthew Barth 
231*acdc2a90SMatthew Barth 	return (db_size);
232*acdc2a90SMatthew Barth }
233*acdc2a90SMatthew Barth 
create_log_event(event_record_t * rec)234*acdc2a90SMatthew Barth uint16_t event_manager::create_log_event(event_record_t *rec)
235*acdc2a90SMatthew Barth {
236*acdc2a90SMatthew Barth 	std::ostringstream buffer;
237*acdc2a90SMatthew Barth 	ofstream myfile;
238*acdc2a90SMatthew Barth 	logheader_t hdr = {0};
239*acdc2a90SMatthew Barth 	size_t event_size=0;
240*acdc2a90SMatthew Barth 
241*acdc2a90SMatthew Barth 	buffer << eventpath << "/" << int(rec->logid) ;
242*acdc2a90SMatthew Barth 
243*acdc2a90SMatthew Barth 	hdr.eyecatcher     = g_eyecatcher;
244*acdc2a90SMatthew Barth 	hdr.version        = g_version;
245*acdc2a90SMatthew Barth 	hdr.logid          = rec->logid;
246*acdc2a90SMatthew Barth 	hdr.timestamp      = rec->timestamp;
247*acdc2a90SMatthew Barth 	hdr.detailsoffset  = offsetof(logheader_t, messagelen);
248*acdc2a90SMatthew Barth 	hdr.messagelen     = getlen(rec->message);
249*acdc2a90SMatthew Barth 	hdr.severitylen    = getlen(rec->severity);
250*acdc2a90SMatthew Barth 	hdr.associationlen = getlen(rec->association);
251*acdc2a90SMatthew Barth 	hdr.reportedbylen  = getlen(rec->reportedby);
252*acdc2a90SMatthew Barth 	hdr.debugdatalen   = rec->n;
253*acdc2a90SMatthew Barth 
254*acdc2a90SMatthew Barth 	event_size = sizeof(logheader_t) + \
255*acdc2a90SMatthew Barth 			hdr.messagelen     + \
256*acdc2a90SMatthew Barth 			hdr.severitylen    + \
257*acdc2a90SMatthew Barth 			hdr.associationlen + \
258*acdc2a90SMatthew Barth 			hdr.reportedbylen  + \
259*acdc2a90SMatthew Barth 			hdr.debugdatalen;
260*acdc2a90SMatthew Barth 
261*acdc2a90SMatthew Barth 	if((event_size + currentsize)  >= maxsize) {
262*acdc2a90SMatthew Barth 		syslog(LOG_ERR, "event logger reached maximum capacity, event not logged");
263*acdc2a90SMatthew Barth 		rec->logid = 0;
264*acdc2a90SMatthew Barth 
265*acdc2a90SMatthew Barth 	} else if (logcount >= maxlogs) {
266*acdc2a90SMatthew Barth 		syslog(LOG_ERR, "event logger reached maximum log events, event not logged");
267*acdc2a90SMatthew Barth 		rec->logid = 0;
268*acdc2a90SMatthew Barth 
269*acdc2a90SMatthew Barth 	} else {
270*acdc2a90SMatthew Barth 		currentsize += event_size;
271*acdc2a90SMatthew Barth 		myfile.open(buffer.str() , ios::out|ios::binary);
272*acdc2a90SMatthew Barth 		myfile.write((char*) &hdr, sizeof(hdr));
273*acdc2a90SMatthew Barth 		myfile.write((char*) rec->message, hdr.messagelen);
274*acdc2a90SMatthew Barth 		myfile.write((char*) rec->severity, hdr.severitylen);
275*acdc2a90SMatthew Barth 		myfile.write((char*) rec->association, hdr.associationlen);
276*acdc2a90SMatthew Barth 		myfile.write((char*) rec->reportedby, hdr.reportedbylen);
277*acdc2a90SMatthew Barth 		myfile.write((char*) rec->p, hdr.debugdatalen);
278*acdc2a90SMatthew Barth 		myfile.close();
279*acdc2a90SMatthew Barth 
280*acdc2a90SMatthew Barth 		if (is_logid_a_log(rec->logid)) {
281*acdc2a90SMatthew Barth 			logcount++;
282*acdc2a90SMatthew Barth 		} else {
283*acdc2a90SMatthew Barth 			cout << "Warning: Event not logged, failed to store data" << endl;
284*acdc2a90SMatthew Barth 			rec->logid = 0;
285*acdc2a90SMatthew Barth 		}
286*acdc2a90SMatthew Barth 	}
287*acdc2a90SMatthew Barth 
288*acdc2a90SMatthew Barth 	return rec->logid;
289*acdc2a90SMatthew Barth }
290*acdc2a90SMatthew Barth 
open(uint16_t logid,event_record_t ** rec)291*acdc2a90SMatthew Barth int event_manager::open(uint16_t logid, event_record_t **rec)
292*acdc2a90SMatthew Barth {
293*acdc2a90SMatthew Barth 	std::ostringstream buffer;
294*acdc2a90SMatthew Barth 	ifstream f;
295*acdc2a90SMatthew Barth 	logheader_t hdr;
296*acdc2a90SMatthew Barth 
297*acdc2a90SMatthew Barth 	buffer << eventpath << "/" << int(logid);
298*acdc2a90SMatthew Barth 
299*acdc2a90SMatthew Barth 	f.open( buffer.str(), ios::binary );
300*acdc2a90SMatthew Barth 
301*acdc2a90SMatthew Barth 	if (!f.good()) {
302*acdc2a90SMatthew Barth 		return 0;
303*acdc2a90SMatthew Barth 	}
304*acdc2a90SMatthew Barth 
305*acdc2a90SMatthew Barth 	*rec = new event_record_t;
306*acdc2a90SMatthew Barth 
307*acdc2a90SMatthew Barth 	f.read((char*)&hdr, sizeof(hdr));
308*acdc2a90SMatthew Barth 
309*acdc2a90SMatthew Barth 	(*rec)->logid     = hdr.logid;
310*acdc2a90SMatthew Barth 	(*rec)->timestamp = hdr.timestamp;
311*acdc2a90SMatthew Barth 
312*acdc2a90SMatthew Barth 
313*acdc2a90SMatthew Barth 	(*rec)->message = new char[hdr.messagelen];
314*acdc2a90SMatthew Barth 	f.read((*rec)->message, hdr.messagelen);
315*acdc2a90SMatthew Barth 
316*acdc2a90SMatthew Barth 	(*rec)->severity = new char[hdr.severitylen];
317*acdc2a90SMatthew Barth 	f.read((*rec)->severity, hdr.severitylen);
318*acdc2a90SMatthew Barth 
319*acdc2a90SMatthew Barth 	(*rec)->association = new char[hdr.associationlen];
320*acdc2a90SMatthew Barth 	f.read((*rec)->association, hdr.associationlen);
321*acdc2a90SMatthew Barth 
322*acdc2a90SMatthew Barth 	(*rec)->reportedby = new char[hdr.reportedbylen];
323*acdc2a90SMatthew Barth 	f.read((*rec)->reportedby, hdr.reportedbylen);
324*acdc2a90SMatthew Barth 
325*acdc2a90SMatthew Barth 	(*rec)->p = new uint8_t[hdr.debugdatalen];
326*acdc2a90SMatthew Barth 	f.read((char*)(*rec)->p, hdr.debugdatalen);
327*acdc2a90SMatthew Barth 	(*rec)->n = hdr.debugdatalen;
328*acdc2a90SMatthew Barth 
329*acdc2a90SMatthew Barth 
330*acdc2a90SMatthew Barth 	f.close();
331*acdc2a90SMatthew Barth 	return logid;
332*acdc2a90SMatthew Barth }
333*acdc2a90SMatthew Barth 
close(event_record_t * rec)334*acdc2a90SMatthew Barth void event_manager::close(event_record_t *rec)
335*acdc2a90SMatthew Barth {
336*acdc2a90SMatthew Barth 	delete[] rec->message;
337*acdc2a90SMatthew Barth 	delete[] rec->severity;
338*acdc2a90SMatthew Barth 	delete[] rec->association;
339*acdc2a90SMatthew Barth 	delete[] rec->reportedby;
340*acdc2a90SMatthew Barth 	delete[] rec->p;
341*acdc2a90SMatthew Barth 	delete rec;
342*acdc2a90SMatthew Barth 
343*acdc2a90SMatthew Barth 	return ;
344*acdc2a90SMatthew Barth }
345*acdc2a90SMatthew Barth 
remove(uint16_t logid)346*acdc2a90SMatthew Barth int event_manager::remove(uint16_t logid)
347*acdc2a90SMatthew Barth {
348*acdc2a90SMatthew Barth 	std::stringstream buffer;
349*acdc2a90SMatthew Barth 	string s;
350*acdc2a90SMatthew Barth 	size_t event_size;
351*acdc2a90SMatthew Barth 
352*acdc2a90SMatthew Barth 	buffer << eventpath << "/" << int(logid);
353*acdc2a90SMatthew Barth 
354*acdc2a90SMatthew Barth 	s = buffer.str();
355*acdc2a90SMatthew Barth 
356*acdc2a90SMatthew Barth 	event_size = get_file_size(s);
357*acdc2a90SMatthew Barth 	std::remove(s.c_str());
358*acdc2a90SMatthew Barth 
359*acdc2a90SMatthew Barth 	/* If everything is working correctly deleting all the logs would */
360*acdc2a90SMatthew Barth 	/* result in currentsize being zero.  But  since size_t is unsigned */
361*acdc2a90SMatthew Barth 	/* it's kind of dangerous to  assume life happens perfectly */
362*acdc2a90SMatthew Barth 	if (currentsize < event_size)
363*acdc2a90SMatthew Barth 		currentsize = 0;
364*acdc2a90SMatthew Barth 	else
365*acdc2a90SMatthew Barth 		currentsize -= event_size;
366*acdc2a90SMatthew Barth 
367*acdc2a90SMatthew Barth 	if (logcount > 0)
368*acdc2a90SMatthew Barth 		logcount--;
369*acdc2a90SMatthew Barth 
370*acdc2a90SMatthew Barth 	return 0;
371*acdc2a90SMatthew Barth }
372