All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH phosphor-event v2] Event Logs to survive a reboot
@ 2016-02-09  3:10 OpenBMC Patches
  2016-02-09  3:10 ` OpenBMC Patches
  0 siblings, 1 reply; 3+ messages in thread
From: OpenBMC Patches @ 2016-02-09  3:10 UTC (permalink / raw)
  To: openbmc

The event service stores the events from the host.  Before this commit all the code was in memory.  That meant once a reboot occured you lost the logs.  With this commit I am storing all logs to the file system.  This refactoring also enables a test suite.  The suite can be invoked by 'make test; ./test'.

1) /var/sys/obmc/events/x
2) logs are stored in binary and saved
3) Each log now has a timestamp of when the log reached the service
4) I added a caching mechanism to reduce the io traffic if the the method is simply being called to capture the next parameter
5) You will notice a mixture of c/c++.  This is because I want the test infrastructure to take advantage of c++ features

Useful REST calls
~~~~~~~~~~~~~~~~~
Note, dont forget to login first

List all events
curl -k https://bmc/org/openbmc/records/events/

Create an event log for testing purposes
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/action/acceptTestMessage

Delete an event
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/1/action/delete

Delete all events
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/action/clear

https://github.com/openbmc/phosphor-event/pull/6

Chris Austen (1):
  Event Logs to survive a reboot

 Makefile               |  30 ++--
 event_messaged.C       |  58 +++++++
 event_messaged.c       | 341 --------------------------------------
 event_messaged_sdbus.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++
 event_messaged_sdbus.h |  14 ++
 message.C              | 291 ++++++++++++++++++++++++++++++++
 message.H              |  89 ++++++++++
 test.C                 | 114 +++++++++++++
 8 files changed, 1027 insertions(+), 352 deletions(-)
 create mode 100644 event_messaged.C
 delete mode 100644 event_messaged.c
 create mode 100644 event_messaged_sdbus.c
 create mode 100644 event_messaged_sdbus.h
 create mode 100644 message.C
 create mode 100644 message.H
 create mode 100644 test.C

-- 
2.6.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH phosphor-event v2] Event Logs to survive a reboot
  2016-02-09  3:10 [PATCH phosphor-event v2] Event Logs to survive a reboot OpenBMC Patches
@ 2016-02-09  3:10 ` OpenBMC Patches
  2016-02-11  6:48   ` Stewart Smith
  0 siblings, 1 reply; 3+ messages in thread
From: OpenBMC Patches @ 2016-02-09  3:10 UTC (permalink / raw)
  To: openbmc

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

The event service stores the events from the host.  Before this commit all the code was in memory.  That meant once a reboot occured you lost the logs.  With this commit I am storing all logs to the file system.  This refactoring also enables a test suite.  The suite can be invoked by 'make test; ./test'.

1) /var/sys/obmc/events/x
2) logs are stored in binary and saved
3) Each log now has a timestamp of when the log reached the service
4) I added a caching mechanism to reduce the io traffic if the the method is simply being called to capture the next parameter
5) You will notice a mixture of c/c++.  This is because I want the test infrastructure to take advantage of c++ features

Useful REST calls
~~~~~~~~~~~~~~~~~
Note, dont forget to login first

List all events
curl -k https://bmc/org/openbmc/records/events/

Create an event log for testing purposes
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/action/acceptTestMessage

Delete an event
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/1/action/delete

Delete all events
curl -c cjar -b cjar -k -H "Content-Type: application/json" -X POST -d "{\"data\": []}" https://bmc/org/openbmc/records/events/action/clear
---
 Makefile               |  30 ++--
 event_messaged.C       |  58 +++++++
 event_messaged.c       | 341 --------------------------------------
 event_messaged_sdbus.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++
 event_messaged_sdbus.h |  14 ++
 message.C              | 291 ++++++++++++++++++++++++++++++++
 message.H              |  89 ++++++++++
 test.C                 | 114 +++++++++++++
 8 files changed, 1027 insertions(+), 352 deletions(-)
 create mode 100644 event_messaged.C
 delete mode 100644 event_messaged.c
 create mode 100644 event_messaged_sdbus.c
 create mode 100644 event_messaged_sdbus.h
 create mode 100644 message.C
 create mode 100644 message.H
 create mode 100644 test.C

diff --git a/Makefile b/Makefile
index 4c2ba9b..0a2248a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,27 +1,35 @@
-TEST      = listfunc
-OBJS_TEST = $(TEST).o
 
-EXE     = event_messaged
+CHECK      = check
 
-OBJS    = $(EXE).o   \
-          list.o 	 \
+EXE       = event_messaged
+EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
 
+OBJS_CHECK = test.o message.o
+
+CPPFLAGS  += -g -fpic -Wall -std=c++11
 
 DEPPKGS = libsystemd
-CC      ?= $(CROSS_COMPILE)gcc
 INCLUDES += $(shell pkg-config --cflags $(DEPPKGS)) 
 LIBS += $(shell pkg-config --libs $(DEPPKGS))
 
+
+
 all: $(EXE)
 
 %.o : %.c 
 	$(CC) -c $< $(CFLAGS) $(INCLUDES) -o $@
 
-$(EXE): $(OBJS)
-	$(CC) $^ $(LDFLAGS) $(LIBS) -o $@
+%.o : %.C
+	$(CXX) -c $< $(CPPFLAGS) -o $@
+
+
+$(EXE): $(EXE_OBJS)
+	$(CXX) $^ $(LDFLAGS) $(LIBS) -o $@
+
 
-$(TEST): $(OBJS_TEST)
-	$(CC) $^ $(LDFLAGS) $(LIBS) -o $@
+$(CHECK): $(OBJS_CHECK)
+	$(CXX) $^ $(LDFLAGS) -o $@
+	./$(CHECK)
 
 clean:
-	rm -f $(OBJS) $(EXE) *.o *.d
+	rm -f $(CHECK) *.o *.so $(EXE)
diff --git a/event_messaged.C b/event_messaged.C
new file mode 100644
index 0000000..0a92f44
--- /dev/null
+++ b/event_messaged.C
@@ -0,0 +1,58 @@
+#include <iostream>
+#include "message.H"
+#include "event_messaged_sdbus.h"
+
+const char *path_to_messages = "/var/lib/obmc/events";
+
+using namespace std;
+
+
+uint16_t message_create_new_log_event(event_manager *em, event_record_t *rec) {
+    return em->create(rec);
+}
+int message_load_log(event_manager *em,uint16_t logid, event_record_t **rec) {
+    return em->open(logid, rec);
+}
+void message_free_log(event_manager *em, event_record_t *rec) {
+    return em->close(rec);
+}
+int message_delete_log(event_manager *em, uint16_t logid) {
+    return em->remove(logid);
+}
+
+int load_existing_events(event_manager *em) {
+
+    uint16_t id;
+
+    while ( (id = em->next_log()) != 0) {
+        send_log_to_dbus(em, id);
+    }
+
+    return 0;
+}
+
+int main(int argc, char *argv[]) {
+
+    int rc = 0;
+    event_manager em(path_to_messages);
+
+
+    rc = build_bus(&em);
+    if (rc < 0) {
+        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
+        goto finish;
+    }
+
+    rc = load_existing_events(&em);
+    if (rc < 0) {
+        fprintf(stderr, "Event Messager failed add previous logs to dbus rc=%d", rc);
+        goto finish;
+    }
+
+    rc = start_event_monitor();
+
+finish:
+    cleanup_event_monitor();
+
+    return rc;
+}
\ No newline at end of file
diff --git a/event_messaged.c b/event_messaged.c
deleted file mode 100644
index 0c75e3a..0000000
--- a/event_messaged.c
+++ /dev/null
@@ -1,341 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stddef.h>
-#include <systemd/sd-bus.h>
-#include "list.h"
-
-uint16_t g_logid = 0;
-sd_bus *bus = NULL;
-List *glist;
-
-
-int create_new_log_event(void *userdata,
-                         const char *message,
-                         const char *severity,
-                         const char *association,
-                         const char *reportedby,
-                         uint8_t *p,
-                         size_t n);
-
-typedef struct messageEntry_t {
-	char    *message;
-	char    *severity;
-	char    *reportedby;
-	char    *association;
-	uint8_t *debugbytes;
-	size_t   debuglength;
-	size_t   logid;
-
-	sd_bus_slot *messageslot;
-	sd_bus_slot *deleteslot;
-
-} messageEntry_t;
-
-
-void message_storage_delete(messageEntry_t *m) {
-
-	char *path;
-	int r;
-
-	asprintf(&path, "/org/openbmc/records/events/%d", m->logid);
-
-
-	printf("Attempting to delete %s\n", path);
-
-	free(m->message);
-	free(m->severity);
-	free(m->reportedby);
-	free(m->association);
-	free(m->debugbytes);
-
-
-	r = sd_bus_emit_object_removed(bus, path);
-	if (r < 0) {
-		fprintf(stderr, "Failed to emit the delete signal %s\n", strerror(-r));
-		return;
-	}
-
-	sd_bus_slot_unref(m->messageslot);
-	sd_bus_slot_unref(m->deleteslot);
-
-	free(m);
-
-	return;
-}
-
-
-
-void message_add(messageEntry_t **n, 
-                const char *message,
-                const char *severity,
-                const char *association,
-                const char *reportedby,
-                size_t      logid,
-                uint8_t    *data,
-                size_t      datalen)
-{
-
-	messageEntry_t *p = *n = malloc(sizeof(messageEntry_t));
-
-	asprintf(&(*n)->message,     "%s", message);
-	asprintf(&(*n)->severity,    "%s", severity);
-	asprintf(&(*n)->association, "%s", association);
-	asprintf(&(*n)->reportedby,  "%s", reportedby);
-
-	(*n)->logid       = logid;
-	(*n)->debugbytes  = (uint8_t*) malloc (datalen);
-	(*n)->debuglength = datalen;
-	memcpy((*n)->debugbytes, data, datalen);
-
-	(*n)->messageslot = NULL;
-	(*n)->deleteslot  = NULL;
-	return;
-}
-
-
-static int get_message_dd(sd_bus *bus,
-                          const char *path,
-                          const char *interface,
-                          const char *property,
-                          sd_bus_message *reply,
-                          void *userdata,
-                          sd_bus_error *error) {
-
-	int r;
-	messageEntry_t *p = (messageEntry_t *)userdata;
-	
-	r = sd_bus_message_append_array(reply, 'y', p->debugbytes, p->debuglength);
-	if (r < 0) {
-	  printf("Error building array for property %s\n", strerror(-r));
-	}
-
-	return r;
-}
-
-
-/////////////////////////////////////////////////////////////
-// Receives an array of bytes as an esel error log
-// returns the messageid in 2 byte format
-//  
-//  S1 - Message - Simple sentence about the fail
-//  S2 - Severity - How bad of a problem is this
-//  S3 - Association - sensor path
-//  ay - Detailed data - developer debug information
-//
-/////////////////////////////////////////////////////////////
-static int method_accept_host_message(sd_bus_message *m, 
-                                      void *userdata, 
-                                      sd_bus_error *ret_error) {
-
-	char *message, *severity, *association;
-	size_t   n = 4;
-	uint8_t *p;
-	int r;
-
-	r = sd_bus_message_read(m, "sss", &message, &severity, &association);
-	if (r < 0) {
-		fprintf(stderr, "Failed to parse the String parameter: %s\n", strerror(-r));
-		return r;
-	}
-
-	r = sd_bus_message_read_array(m, 'y', (const void **)&p, &n);
-	if (r < 0) {
-		fprintf(stderr, "Failed to parse the array of bytes parameter: %s\n", strerror(-r));
-		return r;
-	}
-
-	create_new_log_event(userdata, message, severity, association, "Host", p, n);
-
-	return sd_bus_reply_method_return(m, "q", g_logid);
-}
-
-
-static int method_accept_test_message(sd_bus_message *m, 
-                                      void *userdata, 
-                                      sd_bus_error *ret_error) {
-
-	uint8_t p[] = {0x30, 0x32, 0x34, 0x36};
-
-	create_new_log_event(userdata, "Testing Message", "Info", "Association", "Test", p, 4);
-
-	return sd_bus_reply_method_return(m, "q", g_logid);
-}
-
-
-static int method_clearall(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
-
-	Node *n;
-
-	// This deletes one log at a time and seeing how the
-	// list shrinks using the NULL works fine here
-	while (n = list_get_next_node(glist, NULL)) {
-		message_storage_delete(n->data);
-		list_delete_node(glist, n);
-	}
-
-	return sd_bus_reply_method_return(m, "q", 0);
-}
-
-
-static int method_deletelog(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
-
-	Node *n = (Node*)userdata;
-
-	message_storage_delete(n->data);
-	list_delete_node(glist, n);
-
-	return sd_bus_reply_method_return(m, "q", 0);
-}
-
-
-
-static const sd_bus_vtable recordlog_vtable[] = {
-	SD_BUS_VTABLE_START(0),
-	SD_BUS_METHOD("acceptHostMessage", "sssay", "q", method_accept_host_message, SD_BUS_VTABLE_UNPRIVILEGED),
-	SD_BUS_METHOD("acceptTestMessage", NULL, "q", method_accept_test_message, SD_BUS_VTABLE_UNPRIVILEGED),
-	SD_BUS_METHOD("Clear", NULL, "q", method_clearall, SD_BUS_VTABLE_UNPRIVILEGED),
-	SD_BUS_VTABLE_END
-};
-
-static const sd_bus_vtable log_vtable[] = {
-	SD_BUS_VTABLE_START(0),
-	SD_BUS_PROPERTY("Association", "s", NULL, offsetof(messageEntry_t, association), SD_BUS_VTABLE_PROPERTY_CONST),
-	SD_BUS_PROPERTY("Message",  "s", NULL, offsetof(messageEntry_t, message), SD_BUS_VTABLE_PROPERTY_CONST),
-	SD_BUS_PROPERTY("Severity", "s", NULL, offsetof(messageEntry_t, severity), SD_BUS_VTABLE_PROPERTY_CONST),
-	SD_BUS_PROPERTY("Reported_By", "s", NULL, offsetof(messageEntry_t, reportedby),  SD_BUS_VTABLE_PROPERTY_CONST),
-	SD_BUS_PROPERTY("DevelopmentData", "ay", get_message_dd,0, SD_BUS_VTABLE_PROPERTY_CONST),
-	SD_BUS_VTABLE_END
-};
-
-
-static const sd_bus_vtable recordlog_delete_vtable[] = {
-	SD_BUS_VTABLE_START(0),
-	SD_BUS_METHOD("Delete", NULL, "q", method_deletelog, SD_BUS_VTABLE_UNPRIVILEGED),
-	SD_BUS_VTABLE_END
-};
-
-uint16_t get_new_log_number() {
-	return ++g_logid;
-}
-
-int create_new_log_event(void *userdata,
-                         const char *message,
-                         const char *severity,
-                         const char *association,
-                         const char *reportedby,
-                         uint8_t *p, 
-                         size_t n) {
-	char loglocation[64];
-	int r;
-	messageEntry_t *m;
-	Node *node;
-	uint16_t logid = get_new_log_number();
-
-
-	snprintf(loglocation, sizeof(loglocation), "/org/openbmc/records/events/%d", logid);
-
-	message_add(&m, message, severity, association, reportedby, logid, p, n);
-
-	node = list_add_node(glist, m);
-
-	r = sd_bus_add_object_vtable(bus,
-	                             &m->messageslot,
-	                             loglocation,
-	                             "org.openbmc.record",
-	                             log_vtable,
-	                             m);
-	if (r < 0) {
-		fprintf(stderr, "Failed to acquire service name: %s %s\n", loglocation, strerror(-r));
-		message_storage_delete(m);
-		list_delete_last_node(glist);
-		return 0;
-	}
-
-	r = sd_bus_add_object_vtable(bus,
-	                             &m->deleteslot,
-	                             loglocation,
-	                             "org.openbmc.Object.Delete",
-	                             recordlog_delete_vtable,
-	                             node);
-
-	printf("Event Log added %s\n", loglocation);
-
-	r = sd_bus_emit_object_added(bus, loglocation);
-	if (r < 0) {
-		fprintf(stderr, "Failed to emit signal %s\n", strerror(-r));
-		return 0;
-	}
-
-
-
-	return logid;
-}
-
-
-int start_event_recording(void) {
-
-	int r;
-
-	sd_bus_slot *slot;
-
-	/* Connect to the user bus this time */
-	r = sd_bus_open_system(&bus);
-	if (r < 0) {
-		fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
-		goto finish;
-	}
-
-	/* Install the object */
-	r = sd_bus_add_object_vtable(bus,
-	                             &slot,
-	                             "/org/openbmc/records/events",  /* object path */
-	                             "org.openbmc.recordlog",   /* interface name */
-	                             recordlog_vtable,
-	                             NULL);
-	if (r < 0) {
-		fprintf(stderr, "Failed to issue method call: %s\n", strerror(-r));
-		goto finish;
-	}
-	
-	/* Take a well-known service name so that clients can find us */
-	r = sd_bus_request_name(bus, "org.openbmc.records.events", 0);
-	if (r < 0) {
-		fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
-		goto finish;
-	}
-
-	r = sd_bus_add_object_manager(bus, NULL, "/org/openbmc/records/events") ;
-	if (r < 0) {
-		fprintf(stderr, "Object Manager failure  %s\n", strerror(-r));
-		return 0;
-	}
-
-	for (;;) {
-		r = sd_bus_process(bus, NULL);
-		if (r < 0) {
-			fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
-			goto finish;
-		}
-		if (r > 0)
-			continue;
-
-		r = sd_bus_wait(bus, (uint64_t) -1);
-		if (r < 0) {
-			fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
-			goto finish;
-		}
-	}
-	finish:
-		sd_bus_slot_unref(slot);
-		sd_bus_unref(bus);
-
-	return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-
-int main(int argc, char *argv[]) {
-
-	glist = list_create();
-	return start_event_recording();
-}
\ No newline at end of file
diff --git a/event_messaged_sdbus.c b/event_messaged_sdbus.c
new file mode 100644
index 0000000..1b78179
--- /dev/null
+++ b/event_messaged_sdbus.c
@@ -0,0 +1,442 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+#include <systemd/sd-bus.h>
+#include "message.H"
+#include "list.h"
+#include "event_messaged_sdbus.h"
+#include <syslog.h>
+
+/*****************************************************************************/
+/* This set of functions are responsible for interactions with events over   */
+/* dbus.  Logs come in a couple of different ways...                         */ 
+/*     1) From the calls from acceptHostMessage, acceptTestMessage           */
+/*     2) At startup and logs that exist alreafy are re-added                */
+/*                                                                           */
+/* event_record_t when loaded contain all strings and data stream for a log  */
+/*                                                                           */
+/* Functions naming convention                                               */
+/*     prop_x    : callable dbus properties.                                 */
+/*     method_x  : callable dbus functions.                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+sd_bus      *bus   = NULL;
+sd_bus_slot *slot  = NULL;
+List        *glist = NULL;
+
+event_record_t *gCachedRec = NULL;
+
+static int remove_log_from_dbus(Node *node);
+
+typedef struct messageEntry_t {
+
+	size_t         logid;
+	sd_bus_slot   *messageslot;
+	sd_bus_slot   *deleteslot;
+	event_manager *em;
+
+} messageEntry_t;
+
+
+static void message_entry_close(messageEntry_t *m) {
+	free(m);
+	return;
+}
+
+static void message_entry_new(messageEntry_t **m, uint16_t logid, event_manager *em) {
+	*m          = malloc(sizeof(messageEntry_t));
+	(*m)->logid = logid;
+	(*m)->em    = em;
+	return;
+}
+
+// After calling this function the gCachedRec will be set
+static event_record_t* message_record_open(event_manager *em, uint16_t logid) {
+
+	int r = 0;
+	event_record_t *rec;
+
+	// A simple caching technique because each 
+	// property needs to extract data from the
+	// same data blob.  
+	if (gCachedRec == NULL) {
+		if (message_load_log(em, logid, &rec)) {
+			gCachedRec = rec;
+			return gCachedRec;
+		} else 
+			return NULL;
+	} 
+
+	if (logid == gCachedRec->logid) {
+		r = 1;
+
+	} else {
+		message_free_log(em, gCachedRec);
+		gCachedRec = NULL;
+
+		r = message_load_log(em, logid, &rec);
+		if (r)
+			gCachedRec = rec;
+	}
+
+	return (r ? gCachedRec : NULL);
+}
+
+
+
+static int prop_message(sd_bus *bus,
+                       const char *path,
+                       const char *interface,
+                       const char *property,
+                       sd_bus_message *reply,
+                       void *userdata,
+                       sd_bus_error *error) {
+
+	int r=0;
+	messageEntry_t *m = (messageEntry_t*) userdata;
+	char *p;
+	struct tm *tm_info;
+    char buffer[32];
+    event_record_t *rec;
+
+	rec = message_record_open(m->em, m->logid);
+
+	if (!rec) {
+		fprintf(stderr,"Warning missing evnet log for %d\n", m->logid);
+		sd_bus_error_set(error,  SD_BUS_ERROR_FILE_NOT_FOUND,"Could not find log file");
+        return -1;
+	}
+
+	if (!strncmp("message", property, 7))
+		p = rec->message;
+	else if (!strncmp("severity", property, 8))
+		p = rec->severity;
+	else if (!strncmp("association", property, 11))
+		p = rec->association;
+	else if (!strncmp("reported_by", property, 11))
+		p = rec->reportedby;
+	else if (!strncmp("time", property, 4)) {
+		tm_info = localtime(&rec->timestamp);
+		strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", tm_info);
+		p    = buffer;
+	}
+	else
+		p = "";
+
+	r = sd_bus_message_append(reply, "s", p);
+	if (r < 0) {
+	    fprintf(stderr,"Error building array for property %s\n", strerror(-r));
+	}
+
+
+	return r;
+}
+
+
+static int prop_message_dd(sd_bus *bus,
+                       const char *path,
+                       const char *interface,
+                       const char *property,
+                       sd_bus_message *reply,
+                       void *userdata,
+                       sd_bus_error *error) {
+
+    event_record_t *rec;
+    messageEntry_t *m = (messageEntry_t*) userdata;
+
+
+	rec = message_record_open(m->em, m->logid);
+
+	if (!rec) {
+		sd_bus_error_set(error,  SD_BUS_ERROR_FILE_NOT_FOUND,"Could not find log file");
+        return -1;
+    }
+	return sd_bus_message_append_array(reply, 'y', rec->p, rec->n);
+}
+
+/////////////////////////////////////////////////////////////
+// Receives an array of bytes as an esel error log
+// returns the messageid in 2 byte format
+//  
+//  S1 - Message - Simple sentence about the fail
+//  S2 - Severity - How bad of a problem is this
+//  S3 - Association - sensor path
+//  ay - Detailed data - developer debug information
+//
+/////////////////////////////////////////////////////////////
+static int method_accept_host_message(sd_bus_message *m,
+                                      void *userdata,
+                                      sd_bus_error *ret_error) {
+
+	char *message, *severity, *association, *s;
+	size_t   n = 4;
+	uint8_t *p;
+	int r;
+	uint16_t logid;
+	event_record_t rec;
+	event_manager *em = (event_manager *) userdata;
+
+	r = sd_bus_message_read(m, "sss", &message, &severity, &association);
+	if (r < 0) {
+		fprintf(stderr, "Failed to parse the String parameter: %s\n", strerror(-r));
+		return r;
+	}
+
+	r = sd_bus_message_read_array(m, 'y', (const void **)&p, &n);
+	if (r < 0) {
+		fprintf(stderr, "Failed to parse the array of bytes parameter: %s\n", strerror(-r));
+		return r;
+	}
+
+    rec.message     = (char*) message;
+    rec.severity    = (char*) severity;
+    rec.association = (char*) association;
+    rec.reportedby  = (char*) "Host";
+    rec.p           = (uint8_t*) p;
+    rec.n           = n;
+
+    asprintf(&s, "%s %s (%s)", rec.severity, rec.message, rec.association);
+	syslog(LOG_NOTICE, s);
+	free(s);
+
+	logid = message_create_new_log_event(em, &rec);
+
+	if (logid) 
+		r = send_log_to_dbus(em, logid);
+
+	return sd_bus_reply_method_return(m, "q", logid);
+}
+
+
+static int method_accept_test_message(sd_bus_message *m,
+                                      void *userdata,
+                                      sd_bus_error *ret_error) {
+
+	//  Random debug data including, ascii, null, >signed int, max
+	uint8_t p[] = {0x30, 0x00, 0x13, 0x7F, 0x88, 0xFF};
+	char *s;
+	uint16_t logid;
+	event_record_t rec;
+	event_manager *em = (event_manager *) userdata;
+
+	rec.message     = (char*) "A Test event log just happened";
+	rec.severity    = (char*) "Info";
+	rec.association = (char*) "/org/openbmc/inventory/system/chassis/motherboard/dimm3 " \
+	                          "/org/openbmc/inventory/system/chassis/motherboard/dimm2";
+	rec.reportedby  = (char*) "Test";
+	rec.p           = (uint8_t*) p;
+	rec.n           = 6;
+
+
+	asprintf(&s, "%s %s (%s)", rec.severity, rec.message, rec.association);
+	syslog(LOG_NOTICE, s);
+	free(s);
+
+	logid = message_create_new_log_event(em, &rec);
+	send_log_to_dbus(em, logid);
+
+	return sd_bus_reply_method_return(m, "q", logid);
+}
+
+
+static int method_clearall(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+	Node *n;
+	messageEntry_t *p;
+	
+	// This deletes one log at a time and seeing how the
+	// list shrinks using the NULL works fine here
+	while (n = list_get_next_node(glist, NULL)) {
+		p = (messageEntry_t *) n->data;
+		message_delete_log(p->em, p->logid);
+		remove_log_from_dbus(n);
+	}
+
+	return sd_bus_reply_method_return(m, "q", 0);
+}
+
+
+static int method_deletelog(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
+
+	Node *n = (Node*)userdata;
+	messageEntry_t *p = (messageEntry_t *) n->data;
+
+	message_delete_log(p->em, p->logid);
+	remove_log_from_dbus(n);
+	return sd_bus_reply_method_return(m, "q", 0);
+}
+
+
+
+static const sd_bus_vtable recordlog_vtable[] = {
+	SD_BUS_VTABLE_START(0),
+	SD_BUS_METHOD("acceptHostMessage", "sssay", "q", method_accept_host_message, SD_BUS_VTABLE_UNPRIVILEGED),
+	SD_BUS_METHOD("acceptTestMessage", NULL, "q", method_accept_test_message, SD_BUS_VTABLE_UNPRIVILEGED),
+	SD_BUS_METHOD("clear", NULL, "q", method_clearall, SD_BUS_VTABLE_UNPRIVILEGED),
+	SD_BUS_VTABLE_END
+};
+
+static const sd_bus_vtable log_vtable[] = {
+	SD_BUS_VTABLE_START(0),   
+	SD_BUS_PROPERTY("association",      "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_PROPERTY("message",          "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_PROPERTY("severity",         "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_PROPERTY("reported_by",      "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_PROPERTY("time",             "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_PROPERTY("debug_data", "ay", prop_message_dd ,0, SD_BUS_VTABLE_PROPERTY_CONST),
+	SD_BUS_VTABLE_END
+};
+
+
+static const sd_bus_vtable recordlog_delete_vtable[] = {
+	SD_BUS_VTABLE_START(0),
+	SD_BUS_METHOD("delete", NULL, "q", method_deletelog, SD_BUS_VTABLE_UNPRIVILEGED),
+	SD_BUS_VTABLE_END
+};
+
+static int remove_log_from_dbus(Node *node) {
+
+	messageEntry_t *p = (messageEntry_t *) node->data;
+	int r;
+	char buffer[32];
+
+	snprintf(buffer, sizeof(buffer), "/org/openbmc/records/events/%d", p->logid);
+
+	printf("Attempting to delete %s\n", buffer);
+
+	r = sd_bus_emit_object_removed(bus, buffer);
+	if (r < 0) {
+		fprintf(stderr, "Failed to emit the delete signal %s\n", strerror(-r));
+		return -1;
+	}	
+	sd_bus_slot_unref(p->messageslot);
+	sd_bus_slot_unref(p->deleteslot);
+
+	message_entry_close(p);
+	list_delete_node(glist, node);
+
+	return 0;
+}
+
+int send_log_to_dbus(event_manager *em, const uint16_t logid) {
+
+	char loglocation[64];
+	int r;
+	messageEntry_t *m;
+	Node *node;
+
+
+	snprintf(loglocation, sizeof(loglocation), "/org/openbmc/records/events/%d", logid);
+
+	message_entry_new(&m, logid, em);
+
+	node = list_add_node(glist, m);
+
+	r = sd_bus_add_object_vtable(bus,
+	                             &m->messageslot,
+	                             loglocation,
+	                             "org.openbmc.record",
+	                             log_vtable,
+	                             m);
+	if (r < 0) {
+		fprintf(stderr, "Failed to acquire service name: %s %s\n", loglocation, strerror(-r));
+		message_entry_close(m);
+		list_delete_last_node(glist);
+		return 0;
+	}
+
+	r = sd_bus_add_object_vtable(bus,
+	                             &m->deleteslot,
+	                             loglocation,
+	                             "org.openbmc.Object.Delete",
+	                             recordlog_delete_vtable,
+	                             node);
+	
+	printf("Event Log added %s\n", loglocation);
+
+	r = sd_bus_emit_object_added(bus, loglocation);
+	if (r < 0) {
+		fprintf(stderr, "Failed to emit signal %s\n", strerror(-r));
+		return 0;
+	}
+
+	return logid;
+}
+
+
+int start_event_monitor(void) {
+
+	int r;
+
+	for (;;) {
+
+		r = sd_bus_process(bus, NULL);
+		if (r < 0) {
+			fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
+			break;
+		}
+
+		if (r > 0)
+			continue;
+
+		r = sd_bus_wait(bus, (uint64_t) -1);
+		if (r < 0) {
+			fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
+			break;
+		}
+	}
+
+	return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+
+/* Only thing we are doing in this function is to get a connection on the dbus */
+int build_bus(event_manager *em) {
+
+	int r = 0;
+
+	glist = list_create();
+	/* Connect to the system bus */
+	r = sd_bus_open_system(&bus);
+	if (r < 0) {
+		fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
+		goto finish;
+	}
+
+	/* Install the object */
+	r = sd_bus_add_object_vtable(bus,
+	                             &slot,
+	                             "/org/openbmc/records/events",  /* object path */
+	                             "org.openbmc.recordlog",   /* interface name */
+	                             recordlog_vtable,
+	                             em);
+	if (r < 0) {
+		fprintf(stderr, "Failed to issue method call: %s\n", strerror(-r));
+		goto finish;
+	}
+
+	/* Take a well-known service name so that clients can find us */
+	r = sd_bus_request_name(bus, "org.openbmc.records.events", 0);
+	if (r < 0) {
+		fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
+	}	
+	
+	/* You want to add an object manager to support deleting stuff  */
+	/* without it, dbus can show interfaces that no longer exist */
+	r = sd_bus_add_object_manager(bus, NULL, "/org/openbmc/records/events");
+	if (r < 0) {
+		fprintf(stderr, "Object Manager failure  %s\n", strerror(-r));
+	}
+
+
+	finish:
+	return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+void cleanup_event_monitor(void) {
+	sd_bus_slot_unref(slot);
+	sd_bus_unref(bus);
+}
\ No newline at end of file
diff --git a/event_messaged_sdbus.h b/event_messaged_sdbus.h
new file mode 100644
index 0000000..69a00a6
--- /dev/null
+++ b/event_messaged_sdbus.h
@@ -0,0 +1,14 @@
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C"  {
+#endif
+	int start_event_monitor(void);
+	int build_bus(event_manager *em);
+	int send_log_to_dbus(event_manager *em, const uint16_t logid);
+	void cleanup_event_monitor(void);
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/message.C b/message.C
new file mode 100644
index 0000000..a3fe8b8
--- /dev/null
+++ b/message.C
@@ -0,0 +1,291 @@
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cstdint>
+#include <string>
+#include <sys/types.h> 
+#include <dirent.h> 
+#include <sstream>
+#include <sys/stat.h>
+#include <cstring>
+#include "message.H"
+#include <time.h>
+#include <stddef.h>
+#include <cstdio>
+
+const uint32_t g_eyecatcher = 0x4F424D43; // OBMC
+const uint16_t g_version    = 1;
+
+struct logheader_t {
+    uint32_t eyecatcher;
+    uint16_t version;
+    uint16_t logid;
+    time_t   timestamp;
+    uint16_t detailsoffset;
+    uint16_t messagelen;
+    uint16_t severitylen;
+    uint16_t associationlen;
+    uint16_t reportedbylen;
+    uint16_t debugdatalen;
+};
+
+
+
+event_manager::event_manager(string path) {
+    uint16_t x;
+
+    eventpath = path;
+
+    latestid = 0;
+    dirp = NULL;
+    logcount = 0;
+
+    // examine the files being managed and advance latestid to that value
+    while ( (x = next_log())  ) {
+        logcount++;
+        if ( x > latestid )
+            latestid = x;
+    }
+
+    return;
+}
+
+event_manager::~event_manager() {
+
+    if (dirp) {
+        closedir(dirp);
+    }
+
+    return;
+}
+
+bool event_manager::is_file_a_log(string str) {
+
+    std::ostringstream buffer;
+    ifstream f;
+    logheader_t hdr;
+
+    if (!str.compare("."))
+        return 0;
+    if (!str.compare(".."))
+        return 0;
+
+    buffer << eventpath << "/" << str;
+
+    f.open( buffer.str(), ios::binary);
+
+    if (!f.good()) {
+        return 0;
+    }
+
+    f.read((char*)&hdr, sizeof(hdr));
+
+    if (hdr.eyecatcher != g_eyecatcher)
+        return 0;
+
+    return 1;
+}
+
+uint16_t event_manager::log_count(void) {
+    return logcount;
+}
+uint16_t event_manager::latest_log_id(void) {
+    return latestid;
+}
+uint16_t event_manager::new_log_id(void) {
+    return ++latestid;
+}
+void event_manager::next_log_refresh(void) {
+    if (dirp) {
+        closedir(dirp);
+        dirp = NULL;
+    }
+    return;
+}
+
+uint16_t event_manager::next_log(void) {
+
+    std::ostringstream buffer;
+    struct dirent *ent;
+    uint16_t id;
+
+
+    if (dirp == NULL)
+        dirp = opendir(eventpath.c_str());
+
+    if (dirp) {
+        do {
+            ent = readdir(dirp);
+
+            if (ent == NULL)
+                break;
+
+            string str(ent->d_name);
+
+            if (is_file_a_log(str)) {
+                id = (uint16_t) atoi(str.c_str());
+                break;
+            }
+
+        } while( 1 );
+    } else {
+        cerr << "Error opening directory " << eventpath << endl;
+        ent    = NULL;
+        id = 0;
+    }
+
+    if (ent == NULL) {
+        closedir(dirp);
+        dirp = NULL;
+    }
+
+    return  ((ent == NULL) ? 0 : id);
+}
+
+
+uint16_t event_manager::create(event_record_t *rec) {
+
+    rec->logid = new_log_id();
+    rec->timestamp = time(NULL);
+    return create_log_event(rec);
+}
+
+inline uint16_t getlen(const char *s) {
+    return (uint16_t) (1 + strlen(s));
+}
+
+
+
+size_t event_manager::get_managed_size(void) {
+    DIR *dirp;
+    std::ostringstream buffer;
+    struct dirent *ent;
+    ifstream f;
+
+    size_t db_size = 0;
+
+    dirp = opendir(eventpath.c_str());
+
+    if (dirp) {
+        while ( (ent = readdir(dirp)) != NULL ) {
+
+            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();
+            }
+        }
+    }
+
+    closedir(dirp);
+
+    return  (db_size);
+}
+
+uint16_t event_manager::create_log_event(event_record_t *rec) {
+
+    std::ostringstream buffer;
+    ofstream myfile;
+    logheader_t hdr = {0};
+
+    buffer << eventpath << "/" << int(rec->logid) ;
+
+    hdr.eyecatcher     = g_eyecatcher;
+    hdr.version        = g_version;
+    hdr.logid          = rec->logid;
+    hdr.timestamp      = rec->timestamp;
+    hdr.detailsoffset  = offsetof(logheader_t, messagelen);
+    hdr.messagelen     = getlen(rec->message);
+    hdr.severitylen    = getlen(rec->severity);
+    hdr.associationlen = getlen(rec->association);
+    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.close();
+
+    logcount++;
+
+    return rec->logid;
+}
+
+int event_manager::open(uint16_t logid, event_record_t **rec) {
+
+    std::ostringstream buffer;
+    ifstream f;
+    logheader_t hdr;
+
+    buffer << eventpath << "/" << int(logid);
+
+    f.open( buffer.str(), ios::binary );
+
+    if (!f.good()) {
+        return 0;
+    }
+
+    *rec = new event_record_t;
+
+    f.read((char*)&hdr, sizeof(hdr));
+
+    (*rec)->logid     = hdr.logid;
+    (*rec)->timestamp = hdr.timestamp;
+
+
+    (*rec)->message = new char[hdr.messagelen];
+    f.read((*rec)->message, hdr.messagelen);
+
+    (*rec)->severity = new char[hdr.severitylen];
+    f.read((*rec)->severity, hdr.severitylen);
+
+    (*rec)->association = new char[hdr.associationlen];
+    f.read((*rec)->association, hdr.associationlen);
+
+    (*rec)->reportedby = new char[hdr.reportedbylen];
+    f.read((*rec)->reportedby, hdr.reportedbylen);
+
+    (*rec)->p = new uint8_t[hdr.debugdatalen];
+    f.read((char*)(*rec)->p, hdr.debugdatalen);
+    (*rec)->n = hdr.debugdatalen;
+
+
+    f.close();
+    return logid;
+}
+
+void event_manager::close(event_record_t *rec) {
+
+    delete[] rec->message;
+    delete[] rec->severity;
+    delete[] rec->association;
+    delete[] rec->reportedby;
+    delete[] rec->p;
+    delete rec;
+
+    logcount--;
+    return ;
+}
+
+int event_manager::remove(uint16_t logid) {
+
+    std::stringstream buffer;
+    string s;
+
+    buffer << eventpath << "/" << int(logid);
+
+    s = buffer.str();
+    std::remove(s.c_str());
+
+    return 0;
+}
diff --git a/message.H b/message.H
new file mode 100644
index 0000000..96c7544
--- /dev/null
+++ b/message.H
@@ -0,0 +1,89 @@
+
+#include <dirent.h>
+#include <time.h>
+
+#ifdef __cplusplus
+    #include <cstdint>
+    #include <string>
+
+    using namespace std;
+
+#else
+    #include <stdint.h>
+#endif
+
+
+
+#ifdef __cplusplus
+    struct event_record_t {
+#else     
+    typedef struct _event_record_t {
+#endif
+        char *message;
+        char *severity;
+        char *association;
+        char *reportedby;
+        uint8_t *p;
+        size_t n;
+
+        // These get filled in for you
+        time_t  timestamp;        
+        int16_t logid;
+#ifdef __cplusplus
+    };
+
+#else     
+    } event_record_t;
+#endif
+
+
+
+#ifdef __cplusplus
+
+class event_manager {
+    uint16_t latestid;
+    string   eventpath;
+    DIR      *dirp;
+    uint16_t logcount;
+
+public:
+    event_manager(string path);
+    ~event_manager();
+
+    uint16_t next_log(void);
+    void     next_log_refresh(void);
+
+    uint16_t latest_log_id(void);
+    uint16_t log_count(void);
+    size_t   get_managed_size(void);
+
+    int      open(uint16_t logid, event_record_t **rec); // must call close
+    void     close(event_record_t *rec);
+
+    uint16_t create(event_record_t *rec);
+    int      remove(uint16_t logid);
+
+private:
+    bool is_file_a_log(string str);
+    uint16_t create_log_event(event_record_t *rec);
+    uint16_t new_log_id(void);
+};
+#else
+typedef struct event_manager event_manager;
+#endif
+
+#ifdef __cplusplus
+extern "C"  {
+#endif
+
+
+uint16_t message_create_new_log_event(event_manager *em, event_record_t *rec);
+int      message_load_log(event_manager *em, uint16_t logid, event_record_t **rec);
+void     message_free_log(event_manager *em, event_record_t *rec);
+int      message_delete_log(event_manager *em, uint16_t logid);
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/test.C b/test.C
new file mode 100644
index 0000000..f731fd1
--- /dev/null
+++ b/test.C
@@ -0,0 +1,114 @@
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string>
+
+#include "message.H"
+
+using namespace std;
+
+string eventspath = "./events";
+
+#define ASSERT(a,b,c)  if(b!=c) {cout << "ASSERT ERROR: line " << __LINE__ << endl; exit(1);} else { cout << "Passed: " << a << endl;}
+
+void build_event_record(event_record_t *rec,
+						const char *message,
+                        const char *severity,
+                        const char *association,
+                        const char *reportedby,
+                        const uint8_t *p,
+                        size_t n) {
+
+
+    rec->message     = (char*) message;
+    rec->severity    = (char*) severity;
+    rec->association = (char*) association;
+    rec->reportedby  = (char*) reportedby;
+    rec->p           = (uint8_t*) p;
+    rec->n           = n;
+
+    return;
+}
+
+int main(int argc, char *argv[]) {
+
+	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
+	event_record_t rec, *prec;
+	string s;
+
+
+	system("exec rm -r ./events/* 2> /dev/null");
+
+	event_manager m(eventspath);
+
+	ASSERT("Empty DB", m.get_managed_size(), 0);
+
+	ASSERT("No Logs", m.next_log(), 0);
+	ASSERT("Double No Logs", m.next_log(), 0);
+	m.next_log_refresh();
+	ASSERT("No Logs Refresh", m.next_log(), 0);
+	ASSERT("latest log 0", m.latest_log_id(), 0);
+	ASSERT("Log Entries 0", m.log_count(), 0);
+
+	// Building 1 Event log
+	build_event_record(&rec,"Testing Message1", "Info", "Association", "Test", p, 4);
+	ASSERT("Create log 1", m.create(&rec), 1);
+	ASSERT("1 log is 36 byte", m.get_managed_size(), 75);
+	ASSERT("Log Entries 0", m.log_count(), 1);
+	ASSERT("latest log 1", m.latest_log_id(), 1);
+	m.next_log_refresh();
+	ASSERT("Next log w/ 1", m.next_log(), 1);
+	m.next_log_refresh();
+
+	// Building 2nd Event log
+	build_event_record(&rec,"Testing Message2", "Info", "Association", "Test", p, 4);
+	ASSERT("Create log 2", m.create(&rec), 2);
+	ASSERT("double event manager size", m.get_managed_size(), 150);
+	ASSERT("Log Entries 0", m.log_count(), 2);
+	ASSERT("latest log 2", m.latest_log_id(), 2);
+	m.next_log_refresh();
+	ASSERT("Next Logs scan 1", m.next_log(), 1);
+	ASSERT("Next Logs scan 2", m.next_log(), 2);
+
+	// Read Log 1
+	ASSERT("Log 1 load", m.open(1, &prec), 1);
+	s = prec->message;
+	ASSERT("Log 1 validation", s.compare("Testing Message1"), 0);
+	m.close(prec);
+
+	// Read Log 2
+	ASSERT("Log 2 load", m.open(2, &prec), 2);
+	s = prec->message;
+	ASSERT("Log 2 validation", s.compare("Testing Message2"), 0);
+	m.close(prec);
+
+	// Lets delete the earlier log, then create a new event manager
+	// the latest_log_id should still be 2
+	m.remove(1);
+	ASSERT("manage size with deletion", m.get_managed_size(), 75);
+
+	event_manager q(eventspath);
+	ASSERT("latest log 2", q.latest_log_id(), 2);
+	ASSERT("Log Entries 0", q.log_count(), 1);
+	m.next_log_refresh();
+
+
+	// Travese log list stuff
+	system("exec rm -r ./events/* 2> /dev/null");
+	event_manager a(eventspath);
+	ASSERT("init next log with no logs", 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);
+	ASSERT("init next log with 1 log", b.next_log(), 1);
+
+
+
+
+
+	return 0;
+}
\ No newline at end of file
-- 
2.6.4

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH phosphor-event v2] Event Logs to survive a reboot
  2016-02-09  3:10 ` OpenBMC Patches
@ 2016-02-11  6:48   ` Stewart Smith
  0 siblings, 0 replies; 3+ messages in thread
From: Stewart Smith @ 2016-02-11  6:48 UTC (permalink / raw)
  To: OpenBMC Patches, openbmc

OpenBMC Patches <openbmc-patches@stwcx.xyz> writes:

> From: Chris Austen <austenc@us.ibm.com>
>
> The event service stores the events from the host.  Before this commit all the code was in memory.  That meant once a reboot occured you lost the logs.  With this commit I am storing all logs to the file system.  This refactoring also enables a test suite.  The suite can be invoked by 'make test; ./test'.
>
> 1) /var/sys/obmc/events/x

/var/sys ?

> --- /dev/null
> +++ b/event_messaged.C
> @@ -0,0 +1,58 @@
> +#include <iostream>
> +#include "message.H"
> +#include "event_messaged_sdbus.h"

missing (C) header.

> --- /dev/null
> +++ b/event_messaged_sdbus.c
> @@ -0,0 +1,442 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <stddef.h>
> +#include <systemd/sd-bus.h>
> +#include "message.H"
> +#include "list.h"
> +#include "event_messaged_sdbus.h"
> +#include <syslog.h>
> +
> +/*****************************************************************************/
> +/* This set of functions are responsible for interactions with events over   */
> +/* dbus.  Logs come in a couple of different ways...                         */ 
> +/*     1) From the calls from acceptHostMessage, acceptTestMessage           */
> +/*     2) At startup and logs that exist alreafy are re-added                */
> +/*                                                                           */
> +/* event_record_t when loaded contain all strings and data stream for a log  */
> +/*                                                                           */
> +/* Functions naming convention                                               */
> +/*     prop_x    : callable dbus properties.                                 */
> +/*     method_x  : callable dbus functions.                                  */
> +/*                                                                           */
> +/*****************************************************************************/
> +
> +
> +
> +sd_bus      *bus   = NULL;
> +sd_bus_slot *slot  = NULL;
> +List        *glist = NULL;
> +
> +event_record_t *gCachedRec = NULL;
> +
> +static int remove_log_from_dbus(Node *node);
> +
> +typedef struct messageEntry_t {
> +
> +	size_t         logid;
> +	sd_bus_slot   *messageslot;
> +	sd_bus_slot   *deleteslot;
> +	event_manager *em;
> +
> +} messageEntry_t;
> +
> +
> +static void message_entry_close(messageEntry_t *m) {
> +	free(m);
> +	return;
> +}
> +
> +static void message_entry_new(messageEntry_t **m, uint16_t logid, event_manager *em) {
> +	*m          = malloc(sizeof(messageEntry_t));
> +	(*m)->logid = logid;
> +	(*m)->em    = em;
> +	return;
> +}
> +
> +// After calling this function the gCachedRec will be set
> +static event_record_t* message_record_open(event_manager *em, uint16_t logid) {
> +
> +	int r = 0;
> +	event_record_t *rec;
> +
> +	// A simple caching technique because each 
> +	// property needs to extract data from the
> +	// same data blob.  
> +	if (gCachedRec == NULL) {
> +		if (message_load_log(em, logid, &rec)) {
> +			gCachedRec = rec;
> +			return gCachedRec;
> +		} else 
> +			return NULL;
> +	}

trailing whitespace.


> +static int prop_message(sd_bus *bus,
> +                       const char *path,
> +                       const char *interface,
> +                       const char *property,
> +                       sd_bus_message *reply,
> +                       void *userdata,
> +                       sd_bus_error *error) {
> +
> +	int r=0;
> +	messageEntry_t *m = (messageEntry_t*) userdata;
> +	char *p;
> +	struct tm *tm_info;
> +    char buffer[32];
> +    event_record_t *rec;

Looks like indentation is inconsistent.

> +
> +	rec = message_record_open(m->em, m->logid);
> +
> +	if (!rec) {
> +		fprintf(stderr,"Warning missing evnet log for %d\n", m->logid);
> +		sd_bus_error_set(error,  SD_BUS_ERROR_FILE_NOT_FOUND,"Could not find log file");
> +        return -1;
> +	}
> +
> +	if (!strncmp("message", property, 7))
> +		p = rec->message;
> +	else if (!strncmp("severity", property, 8))
> +		p = rec->severity;
> +	else if (!strncmp("association", property, 11))
> +		p = rec->association;
> +	else if (!strncmp("reported_by", property, 11))
> +		p = rec->reportedby;
> +	else if (!strncmp("time", property, 4)) {
> +		tm_info = localtime(&rec->timestamp);
> +		strftime(buffer, 26, "%Y:%m:%d %H:%M:%S", tm_info);
> +		p    = buffer;
> +	}
> +	else
> +		p = "";
> +
> +	r = sd_bus_message_append(reply, "s", p);
> +	if (r < 0) {
> +	    fprintf(stderr,"Error building array for property %s\n", strerror(-r));
> +	}
> +
> +
> +	return r;
> +}
> +
> +
> +static int prop_message_dd(sd_bus *bus,
> +                       const char *path,
> +                       const char *interface,
> +                       const char *property,
> +                       sd_bus_message *reply,
> +                       void *userdata,
> +                       sd_bus_error *error) {
> +
> +    event_record_t *rec;
> +    messageEntry_t *m = (messageEntry_t*) userdata;
> +
> +
> +	rec = message_record_open(m->em, m->logid);
> +
> +	if (!rec) {
> +		sd_bus_error_set(error,  SD_BUS_ERROR_FILE_NOT_FOUND,"Could not find log file");
> +        return -1;
> +    }
> +	return sd_bus_message_append_array(reply, 'y', rec->p, rec->n);
> +}
> +
> +/////////////////////////////////////////////////////////////
> +// Receives an array of bytes as an esel error log
> +// returns the messageid in 2 byte format
> +//  

trailing whitespace

> +//  S1 - Message - Simple sentence about the fail
> +//  S2 - Severity - How bad of a problem is this
> +//  S3 - Association - sensor path
> +//  ay - Detailed data - developer debug information
> +//
> +/////////////////////////////////////////////////////////////

Use /* */ for multi-line comments.

> +static int method_accept_host_message(sd_bus_message *m,
> +                                      void *userdata,
> +                                      sd_bus_error *ret_error) {
> +
> +	char *message, *severity, *association, *s;
> +	size_t   n = 4;
> +	uint8_t *p;
> +	int r;
> +	uint16_t logid;
> +	event_record_t rec;
> +	event_manager *em = (event_manager *) userdata;
> +
> +	r = sd_bus_message_read(m, "sss", &message, &severity, &association);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to parse the String parameter: %s\n", strerror(-r));
> +		return r;
> +	}
> +
> +	r = sd_bus_message_read_array(m, 'y', (const void **)&p, &n);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to parse the array of bytes parameter: %s\n", strerror(-r));
> +		return r;
> +	}
> +
> +    rec.message     = (char*) message;
> +    rec.severity    = (char*) severity;
> +    rec.association = (char*) association;
> +    rec.reportedby  = (char*) "Host";
> +    rec.p           = (uint8_t*) p;
> +    rec.n           = n;
> +
> +    asprintf(&s, "%s %s (%s)", rec.severity, rec.message, rec.association);
> +	syslog(LOG_NOTICE, s);
> +	free(s);
> +
> +	logid = message_create_new_log_event(em, &rec);
> +
> +	if (logid) 
> +		r = send_log_to_dbus(em, logid);
> +
> +	return sd_bus_reply_method_return(m, "q", logid);
> +}
> +
> +
> +static int method_accept_test_message(sd_bus_message *m,
> +                                      void *userdata,
> +                                      sd_bus_error *ret_error) {
> +
> +	//  Random debug data including, ascii, null, >signed int, max
> +	uint8_t p[] = {0x30, 0x00, 0x13, 0x7F, 0x88, 0xFF};
> +	char *s;
> +	uint16_t logid;
> +	event_record_t rec;
> +	event_manager *em = (event_manager *) userdata;
> +
> +	rec.message     = (char*) "A Test event log just happened";
> +	rec.severity    = (char*) "Info";
> +	rec.association = (char*) "/org/openbmc/inventory/system/chassis/motherboard/dimm3 " \
> +	                          "/org/openbmc/inventory/system/chassis/motherboard/dimm2";
> +	rec.reportedby  = (char*) "Test";
> +	rec.p           = (uint8_t*) p;
> +	rec.n           = 6;
> +
> +
> +	asprintf(&s, "%s %s (%s)", rec.severity, rec.message, rec.association);
> +	syslog(LOG_NOTICE, s);
> +	free(s);
> +
> +	logid = message_create_new_log_event(em, &rec);
> +	send_log_to_dbus(em, logid);
> +
> +	return sd_bus_reply_method_return(m, "q", logid);
> +}
> +
> +
> +static int method_clearall(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
> +	Node *n;
> +	messageEntry_t *p;
> +	
> +	// This deletes one log at a time and seeing how the
> +	// list shrinks using the NULL works fine here
> +	while (n = list_get_next_node(glist, NULL)) {
> +		p = (messageEntry_t *) n->data;
> +		message_delete_log(p->em, p->logid);
> +		remove_log_from_dbus(n);
> +	}
> +
> +	return sd_bus_reply_method_return(m, "q", 0);
> +}
> +
> +
> +static int method_deletelog(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
> +
> +	Node *n = (Node*)userdata;
> +	messageEntry_t *p = (messageEntry_t *) n->data;
> +
> +	message_delete_log(p->em, p->logid);
> +	remove_log_from_dbus(n);
> +	return sd_bus_reply_method_return(m, "q", 0);
> +}
> +
> +
> +
> +static const sd_bus_vtable recordlog_vtable[] = {
> +	SD_BUS_VTABLE_START(0),
> +	SD_BUS_METHOD("acceptHostMessage", "sssay", "q", method_accept_host_message, SD_BUS_VTABLE_UNPRIVILEGED),
> +	SD_BUS_METHOD("acceptTestMessage", NULL, "q", method_accept_test_message, SD_BUS_VTABLE_UNPRIVILEGED),
> +	SD_BUS_METHOD("clear", NULL, "q", method_clearall, SD_BUS_VTABLE_UNPRIVILEGED),
> +	SD_BUS_VTABLE_END
> +};
> +
> +static const sd_bus_vtable log_vtable[] = {
> +	SD_BUS_VTABLE_START(0),   
> +	SD_BUS_PROPERTY("association",      "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_PROPERTY("message",          "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_PROPERTY("severity",         "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_PROPERTY("reported_by",      "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_PROPERTY("time",             "s", prop_message, 0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_PROPERTY("debug_data", "ay", prop_message_dd ,0, SD_BUS_VTABLE_PROPERTY_CONST),
> +	SD_BUS_VTABLE_END
> +};
> +
> +
> +static const sd_bus_vtable recordlog_delete_vtable[] = {
> +	SD_BUS_VTABLE_START(0),
> +	SD_BUS_METHOD("delete", NULL, "q", method_deletelog, SD_BUS_VTABLE_UNPRIVILEGED),
> +	SD_BUS_VTABLE_END
> +};
> +
> +static int remove_log_from_dbus(Node *node) {
> +
> +	messageEntry_t *p = (messageEntry_t *) node->data;
> +	int r;
> +	char buffer[32];
> +
> +	snprintf(buffer, sizeof(buffer), "/org/openbmc/records/events/%d", p->logid);
> +
> +	printf("Attempting to delete %s\n", buffer);
> +
> +	r = sd_bus_emit_object_removed(bus, buffer);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to emit the delete signal %s\n", strerror(-r));
> +		return -1;
> +	}	
> +	sd_bus_slot_unref(p->messageslot);
> +	sd_bus_slot_unref(p->deleteslot);
> +
> +	message_entry_close(p);
> +	list_delete_node(glist, node);
> +
> +	return 0;
> +}
> +
> +int send_log_to_dbus(event_manager *em, const uint16_t logid) {
> +
> +	char loglocation[64];
> +	int r;
> +	messageEntry_t *m;
> +	Node *node;
> +
> +
> +	snprintf(loglocation, sizeof(loglocation), "/org/openbmc/records/events/%d", logid);
> +
> +	message_entry_new(&m, logid, em);
> +
> +	node = list_add_node(glist, m);
> +
> +	r = sd_bus_add_object_vtable(bus,
> +	                             &m->messageslot,
> +	                             loglocation,
> +	                             "org.openbmc.record",
> +	                             log_vtable,
> +	                             m);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to acquire service name: %s %s\n", loglocation, strerror(-r));
> +		message_entry_close(m);
> +		list_delete_last_node(glist);
> +		return 0;
> +	}
> +
> +	r = sd_bus_add_object_vtable(bus,
> +	                             &m->deleteslot,
> +	                             loglocation,
> +	                             "org.openbmc.Object.Delete",
> +	                             recordlog_delete_vtable,
> +	                             node);
> +	
> +	printf("Event Log added %s\n", loglocation);
> +
> +	r = sd_bus_emit_object_added(bus, loglocation);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to emit signal %s\n", strerror(-r));
> +		return 0;
> +	}
> +
> +	return logid;
> +}
> +
> +
> +int start_event_monitor(void) {
> +
> +	int r;
> +
> +	for (;;) {
> +
> +		r = sd_bus_process(bus, NULL);
> +		if (r < 0) {
> +			fprintf(stderr, "Failed to process bus: %s\n", strerror(-r));
> +			break;
> +		}
> +
> +		if (r > 0)
> +			continue;
> +
> +		r = sd_bus_wait(bus, (uint64_t) -1);
> +		if (r < 0) {
> +			fprintf(stderr, "Failed to wait on bus: %s\n", strerror(-r));
> +			break;
> +		}
> +	}
> +
> +	return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
> +}
> +
> +
> +/* Only thing we are doing in this function is to get a connection on the dbus */
> +int build_bus(event_manager *em) {
> +
> +	int r = 0;
> +
> +	glist = list_create();
> +	/* Connect to the system bus */
> +	r = sd_bus_open_system(&bus);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to connect to system bus: %s\n", strerror(-r));
> +		goto finish;
> +	}
> +
> +	/* Install the object */
> +	r = sd_bus_add_object_vtable(bus,
> +	                             &slot,
> +	                             "/org/openbmc/records/events",  /* object path */
> +	                             "org.openbmc.recordlog",   /* interface name */
> +	                             recordlog_vtable,
> +	                             em);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to issue method call: %s\n", strerror(-r));
> +		goto finish;
> +	}
> +
> +	/* Take a well-known service name so that clients can find us */
> +	r = sd_bus_request_name(bus, "org.openbmc.records.events", 0);
> +	if (r < 0) {
> +		fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-r));
> +	}	
> +	
> +	/* You want to add an object manager to support deleting stuff  */
> +	/* without it, dbus can show interfaces that no longer exist */
> +	r = sd_bus_add_object_manager(bus, NULL, "/org/openbmc/records/events");
> +	if (r < 0) {
> +		fprintf(stderr, "Object Manager failure  %s\n", strerror(-r));
> +	}
> +
> +
> +	finish:
> +	return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
> +}
> +
> +void cleanup_event_monitor(void) {
> +	sd_bus_slot_unref(slot);
> +	sd_bus_unref(bus);
> +}
> \ No newline at end of file
> diff --git a/event_messaged_sdbus.h b/event_messaged_sdbus.h
> new file mode 100644
> index 0000000..69a00a6
> --- /dev/null
> +++ b/event_messaged_sdbus.h
> @@ -0,0 +1,14 @@
> +#include <stddef.h>
> +
> +#ifdef __cplusplus
> +extern "C"  {
> +#endif
> +	int start_event_monitor(void);
> +	int build_bus(event_manager *em);
> +	int send_log_to_dbus(event_manager *em, const uint16_t logid);
> +	void cleanup_event_monitor(void);
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +
> diff --git a/message.C b/message.C
> new file mode 100644
> index 0000000..a3fe8b8
> --- /dev/null
> +++ b/message.C
> @@ -0,0 +1,291 @@
> +#include <iostream>
> +#include <fstream>
> +#include <iomanip>
> +#include <cstdint>
> +#include <string>
> +#include <sys/types.h> 
> +#include <dirent.h> 
> +#include <sstream>
> +#include <sys/stat.h>
> +#include <cstring>
> +#include "message.H"
> +#include <time.h>
> +#include <stddef.h>
> +#include <cstdio>
> +
> +const uint32_t g_eyecatcher = 0x4F424D43; // OBMC
> +const uint16_t g_version    = 1;
> +
> +struct logheader_t {
> +    uint32_t eyecatcher;
> +    uint16_t version;
> +    uint16_t logid;
> +    time_t   timestamp;
> +    uint16_t detailsoffset;
> +    uint16_t messagelen;
> +    uint16_t severitylen;
> +    uint16_t associationlen;
> +    uint16_t reportedbylen;
> +    uint16_t debugdatalen;
> +};
> +
> +
> +
> +event_manager::event_manager(string path) {
> +    uint16_t x;
> +
> +    eventpath = path;
> +
> +    latestid = 0;
> +    dirp = NULL;
> +    logcount = 0;
> +
> +    // examine the files being managed and advance latestid to that value
> +    while ( (x = next_log())  ) {
> +        logcount++;
> +        if ( x > latestid )
> +            latestid = x;
> +    }
> +
> +    return;
> +}

If there's an error reading dir, you'll return 0 into latestId and then
when a log is written, you'll overwrite log id 1.

> +
> +event_manager::~event_manager() {
> +
> +    if (dirp) {
> +        closedir(dirp);
> +    }
> +
> +    return;
> +}
> +
> +bool event_manager::is_file_a_log(string str) {
> +
> +    std::ostringstream buffer;
> +    ifstream f;
> +    logheader_t hdr;
> +
> +    if (!str.compare("."))
> +        return 0;
> +    if (!str.compare(".."))
> +        return 0;
> +
> +    buffer << eventpath << "/" << str;
> +
> +    f.open( buffer.str(), ios::binary);
> +
> +    if (!f.good()) {
> +        return 0;
> +    }
> +
> +    f.read((char*)&hdr, sizeof(hdr));

How do you handle EIO and others?

> +
> +    if (hdr.eyecatcher != g_eyecatcher)
> +        return 0;
> +
> +    return 1;

You're returning a number where the method returns bool.

> +}
> +
> +uint16_t event_manager::log_count(void) {
> +    return logcount;
> +}
> +uint16_t event_manager::latest_log_id(void) {
> +    return latestid;
> +}
> +uint16_t event_manager::new_log_id(void) {
> +    return ++latestid;
> +}

How are these going to cope if the underlying FS is modified?

> +void event_manager::next_log_refresh(void) {
> +    if (dirp) {
> +        closedir(dirp);
> +        dirp = NULL;
> +    }
> +    return;
> +}
> +
> +uint16_t event_manager::next_log(void) {
> +
> +    std::ostringstream buffer;
> +    struct dirent *ent;
> +    uint16_t id;
> +
> +
> +    if (dirp == NULL)
> +        dirp = opendir(eventpath.c_str());
> +
> +    if (dirp) {
> +        do {
> +            ent = readdir(dirp);
> +
> +            if (ent == NULL)
> +                break;
> +
> +            string str(ent->d_name);
> +
> +            if (is_file_a_log(str)) {
> +                id = (uint16_t) atoi(str.c_str());
> +                break;
> +            }
> +
> +        } while( 1 );

Why not use scandir instead?

> +    } else {
> +        cerr << "Error opening directory " << eventpath << endl;
> +        ent    = NULL;
> +        id = 0;
> +    }
> +
> +    if (ent == NULL) {
> +        closedir(dirp);
> +        dirp = NULL;
> +    }
> +
> +    return  ((ent == NULL) ? 0 : id);
> +}

What if directory is empty?

> +
> +
> +uint16_t event_manager::create(event_record_t *rec) {
> +
> +    rec->logid = new_log_id();
> +    rec->timestamp = time(NULL);
> +    return create_log_event(rec);
> +}
> +
> +inline uint16_t getlen(const char *s) {
> +    return (uint16_t) (1 + strlen(s));
> +}

Why not size_t - that's kind of what it's for.

> +size_t event_manager::get_managed_size(void) {
> +    DIR *dirp;
> +    std::ostringstream buffer;
> +    struct dirent *ent;
> +    ifstream f;
> +
> +    size_t db_size = 0;
> +
> +    dirp = opendir(eventpath.c_str());
> +
> +    if (dirp) {
> +        while ( (ent = readdir(dirp)) != NULL ) {
> +
> +            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();
> +            }
> +        }
> +    }
> +
> +    closedir(dirp);
> +
> +    return  (db_size);
> +}
> +
> +uint16_t event_manager::create_log_event(event_record_t *rec) {
> +
> +    std::ostringstream buffer;
> +    ofstream myfile;
> +    logheader_t hdr = {0};
> +
> +    buffer << eventpath << "/" << int(rec->logid) ;
> +
> +    hdr.eyecatcher     = g_eyecatcher;
> +    hdr.version        = g_version;
> +    hdr.logid          = rec->logid;
> +    hdr.timestamp      = rec->timestamp;
> +    hdr.detailsoffset  = offsetof(logheader_t, messagelen);
> +    hdr.messagelen     = getlen(rec->message);
> +    hdr.severitylen    = getlen(rec->severity);
> +    hdr.associationlen = getlen(rec->association);
> +    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.close();
> +
> +    logcount++;
> +
> +    return rec->logid;
> +}

If you hit ENOSPC, you'll die really badly. Same with EIO and others.

with no limit on the number you can store, the host could just fill up
the BMC disk and probably cause it to not boot anymore.


> +int event_manager::open(uint16_t logid, event_record_t **rec) {
> +
> +    std::ostringstream buffer;
> +    ifstream f;
> +    logheader_t hdr;
> +
> +    buffer << eventpath << "/" << int(logid);
> +
> +    f.open( buffer.str(), ios::binary );
> +
> +    if (!f.good()) {
> +        return 0;
> +    }
> +
> +    *rec = new event_record_t;
> +
> +    f.read((char*)&hdr, sizeof(hdr));
> +
> +    (*rec)->logid     = hdr.logid;
> +    (*rec)->timestamp = hdr.timestamp;
> +
> +
> +    (*rec)->message = new char[hdr.messagelen];
> +    f.read((*rec)->message, hdr.messagelen);
> +
> +    (*rec)->severity = new char[hdr.severitylen];
> +    f.read((*rec)->severity, hdr.severitylen);
> +
> +    (*rec)->association = new char[hdr.associationlen];
> +    f.read((*rec)->association, hdr.associationlen);
> +
> +    (*rec)->reportedby = new char[hdr.reportedbylen];
> +    f.read((*rec)->reportedby, hdr.reportedbylen);
> +
> +    (*rec)->p = new uint8_t[hdr.debugdatalen];
> +    f.read((char*)(*rec)->p, hdr.debugdatalen);
> +    (*rec)->n = hdr.debugdatalen;
> +
> +
> +    f.close();
> +    return logid;
> +}

Endian conversion?

> +void event_manager::close(event_record_t *rec) {
> +
> +    delete[] rec->message;
> +    delete[] rec->severity;
> +    delete[] rec->association;
> +    delete[] rec->reportedby;
> +    delete[] rec->p;
> +    delete rec;
> +
> +    logcount--;
> +    return ;
> +}
> +
> +int event_manager::remove(uint16_t logid) {
> +
> +    std::stringstream buffer;
> +    string s;
> +
> +    buffer << eventpath << "/" << int(logid);
> +
> +    s = buffer.str();
> +    std::remove(s.c_str());
> +
> +    return 0;
> +}

Error handling?

> diff --git a/message.H b/message.H
> new file mode 100644
> index 0000000..96c7544
> --- /dev/null
> +++ b/message.H
> @@ -0,0 +1,89 @@
> +

(C) header missing

> +#include <dirent.h>
> +#include <time.h>
> +
> +#ifdef __cplusplus
> +    #include <cstdint>
> +    #include <string>
> +
> +    using namespace std;
> +
> +#else
> +    #include <stdint.h>
> +#endif
> +
> +
> +
> +#ifdef __cplusplus
> +    struct event_record_t {
> +#else     
> +    typedef struct _event_record_t {
> +#endif
> +        char *message;
> +        char *severity;
> +        char *association;
> +        char *reportedby;
> +        uint8_t *p;
> +        size_t n;
> +
> +        // These get filled in for you
> +        time_t  timestamp;        
> +        int16_t logid;
> +#ifdef __cplusplus
> +    };
> +
> +#else     
> +    } event_record_t;
> +#endif

Trailing whitespace. The #ifdef is incredibly ugly and you don't need it.

> diff --git a/test.C b/test.C
> new file mode 100644
> index 0000000..f731fd1
> --- /dev/null
> +++ b/test.C
> @@ -0,0 +1,114 @@
> +#include <iostream>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <string>
> +
> +#include "message.H"
> +
> +using namespace std;
> +
> +string eventspath = "./events";
> +
> +#define ASSERT(a,b,c)  if(b!=c) {cout << "ASSERT ERROR: line " <<
> __LINE__ << endl; exit(1);} else { cout << "Passed: " << a << endl;}

err... #include <assert.h>


-- 
Stewart Smith
OPAL Architect, IBM.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-02-11  6:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-09  3:10 [PATCH phosphor-event v2] Event Logs to survive a reboot OpenBMC Patches
2016-02-09  3:10 ` OpenBMC Patches
2016-02-11  6:48   ` Stewart Smith

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.