[PATCH phosphor-event] Add support for limiting the size of the event log DB

OpenBMC Patches openbmc-patches at stwcx.xyz
Thu Mar 17 17:20:27 AEDT 2016


From: Chris Austen <austenc at us.ibm.com>

embedded systems only have so much space.  This feature enables the event deamon to
limit the number of bytes used for logs via an input parameter

Limit the DB to 1k...
    /usr/sbin/phosphor-eventd -s 1000

Without the parameter the db size is unlimited.

When the db hits the limit, the event is NOT logged to the db.  It is however
added (without debug data) to the syslog still AND an error message is posted
in the syslog...

     event logger reached maximum capacity, event not logged

Interfaces exist already to clear the entire db and individual events.
---
 event_messaged.C | 30 +++++++++++++++++--
 message.C        | 87 +++++++++++++++++++++++++++++++++++++++++++++-----------
 message.H        |  5 +++-
 test.C           | 30 +++++++++++++++----
 4 files changed, 128 insertions(+), 24 deletions(-)

diff --git a/event_messaged.C b/event_messaged.C
index 9addd3f..f7249fc 100644
--- a/event_messaged.C
+++ b/event_messaged.C
@@ -1,6 +1,8 @@
 #include <iostream>
 #include "message.H"
 #include "event_messaged_sdbus.h"
+#include <string>
+#include <unistd.h>
 
 const char *path_to_messages = "/var/lib/obmc/events";
 
@@ -44,10 +46,34 @@ int load_existing_events(event_manager *em)
 	return 0;
 }
 
+
+void print_usage(void)
+{
+	cout << "[-s <x>] : Maximum bytes to use for event logger"  << endl;
+	return;
+}
+
+
 int main(int argc, char *argv[])
 {
-	int rc = 0;
-	event_manager em(path_to_messages);
+	unsigned long maxsize=0;
+	int rc, c;
+
+	while ((c = getopt (argc, argv, "s:")) != -1)
+		switch (c) {
+			case 's':
+				maxsize =  strtoul(optarg, NULL, 10);
+				break;
+			case 'h':
+			case '?':
+				print_usage();
+				return 1;
+		}
+
+
+	cout << maxsize <<endl;
+	event_manager em(path_to_messages, maxsize);
+
 
 	rc = build_bus(&em);
 	if (rc < 0) {
diff --git a/message.C b/message.C
index 2e52b67..1bf7d8b 100644
--- a/message.C
+++ b/message.C
@@ -12,6 +12,7 @@
 #include <time.h>
 #include <stddef.h>
 #include <cstdio>
+#include <syslog.h>
 
 const uint32_t g_eyecatcher = 0x4F424D43; // OBMC
 const uint16_t g_version    = 1;
@@ -29,14 +30,21 @@ struct logheader_t {
 	uint16_t debugdatalen;
 };
 
+size_t get_file_size(string fn);
 
-event_manager::event_manager(string path)
+
+event_manager::event_manager(string path, size_t reqmaxsize)
 {
 	uint16_t x;
 	eventpath = path;
 	latestid = 0;
 	dirp = NULL;
 	logcount = 0;
+	maxsize = -1;
+	currentsize = 0;
+
+	if (reqmaxsize)
+		maxsize = reqmaxsize;
 
 	// examine the files being managed and advance latestid to that value
 	while ( (x = next_log()) ) {
@@ -56,6 +64,15 @@ event_manager::~event_manager()
 	return;
 }
 
+
+bool event_manager::is_logid_a_log(uint16_t logid)
+{
+	std::ostringstream buffer;
+	buffer  << int(logid);
+	return is_file_a_log(buffer.str());
+}
+
+
 bool event_manager::is_file_a_log(string str)
 {
 	std::ostringstream buffer;
@@ -161,6 +178,18 @@ inline uint16_t getlen(const char *s)
 }
 
 
+size_t get_file_size(string fn)
+{
+	ifstream f;
+	size_t len=0;
+
+	f.open(fn, ios::in|ios::binary|ios::ate);
+	len = f.tellg();
+	f.close();
+	return (len);
+}
+
+
 size_t event_manager::get_managed_size(void)
 {
 	DIR *dirp;
@@ -178,13 +207,9 @@ size_t event_manager::get_managed_size(void)
 			string str(ent->d_name);
 
 			if (is_file_a_log(str)) {
-
 				buffer.str("");
 				buffer << eventpath << "/" << str.c_str();
-
-				f.open(buffer.str() , ios::in|ios::binary|ios::ate);
-				db_size += f.tellg();
-				f.close();
+				db_size += get_file_size(buffer.str());
 			}
 		}
 	}
@@ -199,6 +224,7 @@ uint16_t event_manager::create_log_event(event_record_t *rec)
 	std::ostringstream buffer;
 	ofstream myfile;
 	logheader_t hdr = {0};
+	size_t event_size=0;
 
 	buffer << eventpath << "/" << int(rec->logid) ;
 
@@ -213,17 +239,35 @@ uint16_t event_manager::create_log_event(event_record_t *rec)
 	hdr.reportedbylen  = getlen(rec->reportedby);
 	hdr.debugdatalen   = rec->n;
 
-	myfile.open(buffer.str() , ios::out|ios::binary);
-	myfile.write((char*) &hdr, sizeof(hdr));
-	myfile.write((char*) rec->message, hdr.messagelen);
-	myfile.write((char*) rec->severity, hdr.severitylen);
-	myfile.write((char*) rec->association, hdr.associationlen);
-	myfile.write((char*) rec->reportedby, hdr.reportedbylen);
-	myfile.write((char*) rec->p, hdr.debugdatalen);
-	myfile.flush();
-	myfile.close();
+	event_size = sizeof(logheader_t) + \
+			hdr.messagelen     + \
+			hdr.severitylen    + \
+			hdr.associationlen + \
+			hdr.reportedbylen  + \
+			hdr.debugdatalen;
 
-	logcount++;
+	if((event_size + currentsize)  >= maxsize) {
+		syslog(LOG_ERR, "event logger reached maximum capacity, event not logged");
+		rec->logid = 0;
+
+	} else {
+		currentsize += event_size;
+		myfile.open(buffer.str() , ios::out|ios::binary);
+		myfile.write((char*) &hdr, sizeof(hdr));
+		myfile.write((char*) rec->message, hdr.messagelen);
+		myfile.write((char*) rec->severity, hdr.severitylen);
+		myfile.write((char*) rec->association, hdr.associationlen);
+		myfile.write((char*) rec->reportedby, hdr.reportedbylen);
+		myfile.write((char*) rec->p, hdr.debugdatalen);
+		myfile.close();
+
+		if (is_logid_a_log(rec->logid)) {
+			logcount++;
+		} else {
+			cout << "Warning: Event not logged, failed to store data" << endl;
+			rec->logid = 0;
+		}
+	}
 
 	return rec->logid;
 }
@@ -288,11 +332,22 @@ int event_manager::remove(uint16_t logid)
 {
 	std::stringstream buffer;
 	string s;
+	size_t event_size;
 
 	buffer << eventpath << "/" << int(logid);
 
 	s = buffer.str();
+
+	event_size = get_file_size(s);
 	std::remove(s.c_str());
 
+	/* If everything is working correctly deleting all the logs would */ 
+	/* result in currentsize being zero.  But  since size_t is unsigned */
+	/* it's kind of dangerous to  assume life happens perfectly */
+	if (currentsize < event_size)
+		currentsize = 0;
+	else
+		currentsize -= event_size;
+
 	return 0;
 }
diff --git a/message.H b/message.H
index 5cc3484..d3a0a26 100644
--- a/message.H
+++ b/message.H
@@ -41,9 +41,11 @@ class event_manager {
 	string   eventpath;
 	DIR      *dirp;
 	uint16_t logcount;
+	size_t   maxsize;
+	size_t   currentsize;
 
 public:
-	event_manager(string path);
+	event_manager(string path, size_t reqmaxsize);
 	~event_manager();
 
 	uint16_t next_log(void);
@@ -63,6 +65,7 @@ private:
 	bool is_file_a_log(string str);
 	uint16_t create_log_event(event_record_t *rec);
 	uint16_t new_log_id(void);
+	bool     is_logid_a_log(uint16_t logid);
 };
 #else
 typedef struct event_manager event_manager;
diff --git a/test.C b/test.C
index 1e00221..ee69b1c 100644
--- a/test.C
+++ b/test.C
@@ -4,7 +4,7 @@
 #include <stdint.h>
 #include <string>
 #include <assert.h>
-
+#include <unistd.h>
 #include "message.H"
 
 using namespace std;
@@ -44,15 +44,17 @@ void setup(void)
 	return;
 }
 
+
 int main(int argc, char *argv[])
 {
 	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
 	event_record_t rec, *prec;
 	string s;
 
+
 	setup();
 
-	event_manager m(eventspath);
+	event_manager m(eventspath, 0);
 
 	assert(m.get_managed_size() == 0);
 
@@ -99,22 +101,40 @@ int main(int argc, char *argv[])
 	m.remove(1);
 	assert(m.get_managed_size() == 75);
 
-	event_manager q(eventspath);
+	event_manager q(eventspath, 0);
 	assert(q.latest_log_id() == 2);
 	assert(q.log_count() == 1);
 	m.next_log_refresh();
 
 	// Travese log list stuff
 	system("exec rm -r ./events/* 2> /dev/null");
-	event_manager a(eventspath);
+	event_manager a(eventspath, 0);
 	assert(a.next_log() == 0);
 
 	build_event_record(&rec,"Testing list", "Info", "Association", "Test", p, 4);
 	a.create(&rec);
 	a.create(&rec);
 
-	event_manager b(eventspath);
+	event_manager b(eventspath, 0);
 	assert(b.next_log() == 1);
 
+
+	/* Testing the max limits for event logs */
+	setup();
+	event_manager d(eventspath, 75);
+	build_event_record(&rec,"Testing Message1", "Info", "Association", "Test", p, 4);
+	assert(d.create(&rec) == 0);
+
+	event_manager e(eventspath, 76);
+	build_event_record(&rec,"Testing Message1", "Info", "Association", "Test", p, 4);
+	assert(e.create(&rec) == 1);
+
+	setup();
+	event_manager f(eventspath, 149);
+	build_event_record(&rec,"Testing Message1", "Info", "Association", "Test", p, 4);
+	assert(f.create(&rec) == 1);
+	assert(f.create(&rec) == 0);
+
+
 	return 0;
 }
\ No newline at end of file
-- 
2.7.1




More information about the openbmc mailing list