All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH phosphor-event] Event Logs to survive a reboot
@ 2016-02-02 16:40 OpenBMC Patches
  2016-02-02 16:40 ` OpenBMC Patches
  0 siblings, 1 reply; 7+ messages in thread
From: OpenBMC Patches @ 2016-02-02 16:40 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               |  29 ++--
 event_messaged.C       |  44 +++++
 event_messaged.c       | 341 ---------------------------------------
 event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
 event_messaged_sdbus.h |  14 ++
 message.C              | 224 ++++++++++++++++++++++++++
 message.H              |  60 +++++++
 test.C                 |  92 +++++++++++
 8 files changed, 878 insertions(+), 351 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] 7+ messages in thread

* [PATCH phosphor-event] Event Logs to survive a reboot
  2016-02-02 16:40 [PATCH phosphor-event] Event Logs to survive a reboot OpenBMC Patches
@ 2016-02-02 16:40 ` OpenBMC Patches
  2016-02-03  5:48   ` Daniel Axtens
                     ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: OpenBMC Patches @ 2016-02-02 16:40 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               |  29 ++--
 event_messaged.C       |  44 +++++
 event_messaged.c       | 341 ---------------------------------------
 event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
 event_messaged_sdbus.h |  14 ++
 message.C              | 224 ++++++++++++++++++++++++++
 message.H              |  60 +++++++
 test.C                 |  92 +++++++++++
 8 files changed, 878 insertions(+), 351 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..903ac06 100644
--- a/Makefile
+++ b/Makefile
@@ -1,27 +1,36 @@
-TEST      = listfunc
-OBJS_TEST = $(TEST).o
 
-EXE     = event_messaged
+TEST      = test
 
-OBJS    = $(EXE).o   \
-          list.o 	 \
+EXE       = event_messaged
+EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
 
+OBJS_TEST = $(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 $@
+	$(CXX) $^ $(LDFLAGS) -o $@
 
 clean:
-	rm -f $(OBJS) $(EXE) *.o *.d
+	rm -f $(TEST) *.o *.so $(EXE)
+
+
diff --git a/event_messaged.C b/event_messaged.C
new file mode 100644
index 0000000..4376431
--- /dev/null
+++ b/event_messaged.C
@@ -0,0 +1,44 @@
+#include <iostream>
+#include "message.H"
+#include "event_messaged_sdbus.h"
+
+const char *glogname = "/var/lib/obmc/events";
+
+using namespace std;
+
+
+// Walk through all the saved logs and reload them in to dbus objects
+// Needed because on a reboot the existing logs need to be reloaded
+int load_existing_events(void) {
+
+    event_log_list log_list;
+    uint16_t       logid=0;
+
+    while (message_get_next_log(&logid, &log_list)) {
+        send_log_to_dbus(logid);
+    }
+    
+    return 0;
+}
+
+int main(int argc, char *argv[]) {
+
+    int rc = 0;
+
+    if ((rc = build_bus()) < 0) {
+        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
+        goto finish;
+    }
+
+    if ((rc = load_existing_events()) < 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..fa83e5c
--- /dev/null
+++ b/event_messaged_sdbus.c
@@ -0,0 +1,425 @@
+#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"
+
+/*****************************************************************************/
+/* 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;
+
+} messageEntry_t;
+
+
+static void message_entry_close(messageEntry_t *m) {
+	free(m);
+	return;
+}
+
+static void message_entry_new(messageEntry_t **m, uint16_t logid) {
+	*m          = malloc(sizeof(messageEntry_t));
+	(*m)->logid = logid;
+	return;
+}
+
+// After calling this function the gCachedRec will be set
+static event_record_t* message_record_open(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(logid, &rec)) {
+			gCachedRec = rec;
+			return gCachedRec;
+		} else 
+			return NULL;
+	} 
+
+	if (logid == gCachedRec->logid) {
+		r = 1;
+
+	} else {
+		message_free_log(gCachedRec);
+		gCachedRec = NULL;
+
+		r = message_load_log(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->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->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;
+	size_t   n = 4;
+	uint8_t *p;
+	int r;
+	uint16_t logid;
+	event_record_t rec;
+
+	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;
+
+
+	logid = message_create_new_log_event(&rec);
+
+	if (logid) 
+		r = send_log_to_dbus(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) {
+
+	uint8_t p[] = {0x30, 0x32, 0x34, 0x36};
+	uint16_t logid;
+	event_record_t rec;
+
+    rec.message     = (char*) "Testing Message";
+    rec.severity    = (char*) "Info";
+    rec.association = (char*) "Association";
+    rec.reportedby  = (char*) "Test";
+    rec.p           = (uint8_t*) p;
+    rec.n           = sizeof(*p);
+
+	logid = message_create_new_log_event(&rec);
+	send_log_to_dbus(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->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->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("DevelopmentData", "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(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);
+
+	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(void) {
+
+	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,
+	                             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));
+	}	
+	
+	/* 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..a6aac94
--- /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(void);
+	int send_log_to_dbus(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..31a545a
--- /dev/null
+++ b/message.C
@@ -0,0 +1,224 @@
+#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>
+
+using namespace std;
+
+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;
+};
+
+uint16_t g_logid = 0;
+
+extern const char *glogname;
+
+static uint16_t get_new_log_number(void) {
+    return ++g_logid;
+}
+
+static void update_latest_logid(uint16_t logid) {
+    if (logid > g_logid)
+        g_logid = logid;
+    return;
+}
+
+inline uint16_t GETLEN(const char *s) {
+    return (uint16_t) (1 + strlen(s));
+}
+
+static uint16_t create_log_event(event_record_t *rec) {
+
+    std::ostringstream buffer;
+    ofstream myfile;
+    logheader_t hdr;
+
+
+    buffer << glogname << "/" << int(rec->logid) ;
+
+    cout << buffer.str() << endl;
+
+    hdr.eyecatcher     = g_eyecatcher;
+    hdr.version        = g_version;
+    hdr.logid          = rec->logid;
+    hdr.timestamp      = time(NULL);
+    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();
+
+    return rec->logid;
+}
+
+static int 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 << glogname << "/" << 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;
+}
+
+
+
+int message_load_log(uint16_t logid, event_record_t **rec) {
+
+    std::ostringstream buffer;
+    ifstream f;
+    logheader_t hdr;
+
+    buffer << glogname << "/" << 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 message_free_log(event_record_t *rec) {
+
+    delete[] rec->message;
+    delete[] rec->severity;
+    delete[] rec->association;
+    delete[] rec->reportedby;
+    delete[] rec->p;
+    delete rec;
+
+    return ;
+}
+
+int message_delete_log(uint16_t logid) {
+
+    std::stringstream buffer;
+    string s;
+
+    buffer << glogname << "/" << int(logid);
+
+    s = buffer.str();
+    std::remove(s.c_str());
+
+    return 0;
+}
+
+
+int message_get_next_log(uint16_t *logid, event_log_list *log_list) {
+
+    std::ostringstream buffer;
+    struct dirent *ent;
+
+    if (*logid==0)
+        log_list->dirp = opendir(glogname);
+
+    if(log_list->dirp)
+    {
+        do {
+            ent = readdir(log_list->dirp);
+
+            if (ent == NULL)
+                break;
+
+            string str(ent->d_name);
+
+            if (is_file_a_log(str)) {
+                *logid = (uint16_t) atoi(str.c_str());
+                update_latest_logid(*logid);
+                break;
+            }
+
+        } while( 1 );
+    } 
+    else
+    { 
+        cerr << "Error opening directory" << glogname << endl;
+        ent    = NULL;
+        *logid = 0;
+    }
+    return  ((ent == NULL) ? 0 : 1);
+}
+
+
+uint16_t message_create_new_log_event(event_record_t *rec) {
+
+    rec->logid = get_new_log_number();
+    return create_log_event(rec);
+}
diff --git a/message.H b/message.H
new file mode 100644
index 0000000..26ebe19
--- /dev/null
+++ b/message.H
@@ -0,0 +1,60 @@
+
+#include <dirent.h>
+#include <time.h>
+
+#ifdef __cplusplus
+    #include <cstdint>
+#else
+    #include <stdint.h>
+#endif
+
+
+#ifdef __cplusplus
+    struct event_log_list {
+#else
+    typedef struct _event_log_list {        
+#endif
+        DIR *dirp;
+#ifdef __cplusplus
+    };
+#else    
+    } event_log_list;
+#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
+extern "C"  {
+#endif
+
+
+uint16_t message_create_new_log_event(event_record_t *rec);
+int      message_load_log(uint16_t logid, event_record_t **rec);
+void     message_free_log(event_record_t *rec);
+int      message_get_next_log(uint16_t *logid, event_log_list *log_list);
+int      message_delete_log(uint16_t logid);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test.C b/test.C
new file mode 100644
index 0000000..afd834e
--- /dev/null
+++ b/test.C
@@ -0,0 +1,92 @@
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "message.H"
+using namespace std;
+
+const char *glogname = "./events";
+
+#define ASSERT(a,b)  if(a!=b) {cout << "ASSERT ERROR: line " << __LINE__ << endl; exit(1);}
+
+void build_event_record(event_record_t *rec,
+						uint16_t logid,
+                        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 load_existing_events(void) {
+
+	event_log_list log_list;
+	uint16_t       logid=0;
+	event_record_t *rec;
+
+	cout << "Loading event log... ";
+
+	while (message_get_next_log(&logid, &log_list)) {
+		cout << " " << int(logid);
+		message_load_log(logid, &rec);
+
+		cout << rec->message << endl;
+
+		message_free_log(rec);
+	}
+	cout << endl;
+	
+	return 0;
+}
+
+
+int main(int argc, char *argv[]) {
+
+	int rc = 0;
+
+	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
+	event_record_t rec, *prec;
+	event_log_list log_list;
+	uint16_t logid=0;
+	int i;
+
+	build_event_record(&rec,0, "Testing Message1", "Info", "Association", "Test", p, 4);
+	ASSERT(message_create_new_log_event(&rec),1);
+	build_event_record(&rec,0, "Testing Message2", "Info", "/dev", "Test", p, 4);
+	ASSERT(message_create_new_log_event(&rec),2);
+	build_event_record(&rec,0, "Testing Message3", "Info", "Association", "Test", p, 4);
+	ASSERT(message_create_new_log_event(&rec),3);
+
+	ASSERT(message_load_log(13, &prec), 0);
+	ASSERT(message_load_log(1, &prec), 1); message_free_log(prec);
+
+	// Test the number of valid logs so far
+	i = 0;
+	while (message_get_next_log(&logid, &log_list)) {
+
+
+		cout << int(logid) << endl;
+		i++;
+	}
+	//ASSERT(i,3);
+
+	cout << "LOADLOG TEST" << endl;
+
+	load_existing_events();
+
+	message_delete_log(1);
+
+	return rc;
+}
\ No newline at end of file
-- 
2.6.4

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

* Re: [PATCH phosphor-event] Event Logs to survive a reboot
  2016-02-02 16:40 ` OpenBMC Patches
@ 2016-02-03  5:48   ` Daniel Axtens
  2016-02-03  6:08   ` Joel Stanley
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Daniel Axtens @ 2016-02-03  5:48 UTC (permalink / raw)
  To: OpenBMC Patches, openbmc

[-- Attachment #1: Type: text/plain, Size: 40095 bytes --]

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
> 2) logs are stored in binary and saved

A couple of broad design questions, and apologies if I've missed some of
the 'backstory' here:

 - Can this log grow unboundedly? Do we need to support logrotate? Do we
   need to enable it now? Will this code deal with the file changing
   underneath it when it's rotated?

 - Is there a compelling reason to store the logs in binary? Can we
   store then in text? Or do we have existing tooling to decode them?

Regards,
Daniel
> 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               |  29 ++--
>  event_messaged.C       |  44 +++++
>  event_messaged.c       | 341 ---------------------------------------
>  event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
>  event_messaged_sdbus.h |  14 ++
>  message.C              | 224 ++++++++++++++++++++++++++
>  message.H              |  60 +++++++
>  test.C                 |  92 +++++++++++
>  8 files changed, 878 insertions(+), 351 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..903ac06 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,27 +1,36 @@
> -TEST      = listfunc
> -OBJS_TEST = $(TEST).o
>  
> -EXE     = event_messaged
> +TEST      = test
>  
> -OBJS    = $(EXE).o   \
> -          list.o 	 \
> +EXE       = event_messaged
> +EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
>  
> +OBJS_TEST = $(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 $@
> +	$(CXX) $^ $(LDFLAGS) -o $@
>  
>  clean:
> -	rm -f $(OBJS) $(EXE) *.o *.d
> +	rm -f $(TEST) *.o *.so $(EXE)
> +
> +
> diff --git a/event_messaged.C b/event_messaged.C
> new file mode 100644
> index 0000000..4376431
> --- /dev/null
> +++ b/event_messaged.C
> @@ -0,0 +1,44 @@
> +#include <iostream>
> +#include "message.H"
> +#include "event_messaged_sdbus.h"
> +
> +const char *glogname = "/var/lib/obmc/events";
> +
> +using namespace std;
> +
> +
> +// Walk through all the saved logs and reload them in to dbus objects
> +// Needed because on a reboot the existing logs need to be reloaded
> +int load_existing_events(void) {
> +
> +    event_log_list log_list;
> +    uint16_t       logid=0;
> +
> +    while (message_get_next_log(&logid, &log_list)) {
> +        send_log_to_dbus(logid);
> +    }
> +    
> +    return 0;
> +}
> +
> +int main(int argc, char *argv[]) {
> +
> +    int rc = 0;
> +
> +    if ((rc = build_bus()) < 0) {
> +        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    if ((rc = load_existing_events()) < 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..fa83e5c
> --- /dev/null
> +++ b/event_messaged_sdbus.c
> @@ -0,0 +1,425 @@
> +#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"
> +
> +/*****************************************************************************/
> +/* 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;
> +
> +} messageEntry_t;
> +
> +
> +static void message_entry_close(messageEntry_t *m) {
> +	free(m);
> +	return;
> +}
> +
> +static void message_entry_new(messageEntry_t **m, uint16_t logid) {
> +	*m          = malloc(sizeof(messageEntry_t));
> +	(*m)->logid = logid;
> +	return;
> +}
> +
> +// After calling this function the gCachedRec will be set
> +static event_record_t* message_record_open(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(logid, &rec)) {
> +			gCachedRec = rec;
> +			return gCachedRec;
> +		} else 
> +			return NULL;
> +	} 
> +
> +	if (logid == gCachedRec->logid) {
> +		r = 1;
> +
> +	} else {
> +		message_free_log(gCachedRec);
> +		gCachedRec = NULL;
> +
> +		r = message_load_log(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->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->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;
> +	size_t   n = 4;
> +	uint8_t *p;
> +	int r;
> +	uint16_t logid;
> +	event_record_t rec;
> +
> +	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;
> +
> +
> +	logid = message_create_new_log_event(&rec);
> +
> +	if (logid) 
> +		r = send_log_to_dbus(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) {
> +
> +	uint8_t p[] = {0x30, 0x32, 0x34, 0x36};
> +	uint16_t logid;
> +	event_record_t rec;
> +
> +    rec.message     = (char*) "Testing Message";
> +    rec.severity    = (char*) "Info";
> +    rec.association = (char*) "Association";
> +    rec.reportedby  = (char*) "Test";
> +    rec.p           = (uint8_t*) p;
> +    rec.n           = sizeof(*p);
> +
> +	logid = message_create_new_log_event(&rec);
> +	send_log_to_dbus(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->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->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("DevelopmentData", "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(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);
> +
> +	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(void) {
> +
> +	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,
> +	                             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));
> +	}	
> +	
> +	/* 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..a6aac94
> --- /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(void);
> +	int send_log_to_dbus(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..31a545a
> --- /dev/null
> +++ b/message.C
> @@ -0,0 +1,224 @@
> +#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>
> +
> +using namespace std;
> +
> +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;
> +};
> +
> +uint16_t g_logid = 0;
> +
> +extern const char *glogname;
> +
> +static uint16_t get_new_log_number(void) {
> +    return ++g_logid;
> +}
> +
> +static void update_latest_logid(uint16_t logid) {
> +    if (logid > g_logid)
> +        g_logid = logid;
> +    return;
> +}
> +
> +inline uint16_t GETLEN(const char *s) {
> +    return (uint16_t) (1 + strlen(s));
> +}
> +
> +static uint16_t create_log_event(event_record_t *rec) {
> +
> +    std::ostringstream buffer;
> +    ofstream myfile;
> +    logheader_t hdr;
> +
> +
> +    buffer << glogname << "/" << int(rec->logid) ;
> +
> +    cout << buffer.str() << endl;
> +
> +    hdr.eyecatcher     = g_eyecatcher;
> +    hdr.version        = g_version;
> +    hdr.logid          = rec->logid;
> +    hdr.timestamp      = time(NULL);
> +    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();
> +
> +    return rec->logid;
> +}
> +
> +static int 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 << glogname << "/" << 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;
> +}
> +
> +
> +
> +int message_load_log(uint16_t logid, event_record_t **rec) {
> +
> +    std::ostringstream buffer;
> +    ifstream f;
> +    logheader_t hdr;
> +
> +    buffer << glogname << "/" << 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 message_free_log(event_record_t *rec) {
> +
> +    delete[] rec->message;
> +    delete[] rec->severity;
> +    delete[] rec->association;
> +    delete[] rec->reportedby;
> +    delete[] rec->p;
> +    delete rec;
> +
> +    return ;
> +}
> +
> +int message_delete_log(uint16_t logid) {
> +
> +    std::stringstream buffer;
> +    string s;
> +
> +    buffer << glogname << "/" << int(logid);
> +
> +    s = buffer.str();
> +    std::remove(s.c_str());
> +
> +    return 0;
> +}
> +
> +
> +int message_get_next_log(uint16_t *logid, event_log_list *log_list) {
> +
> +    std::ostringstream buffer;
> +    struct dirent *ent;
> +
> +    if (*logid==0)
> +        log_list->dirp = opendir(glogname);
> +
> +    if(log_list->dirp)
> +    {
> +        do {
> +            ent = readdir(log_list->dirp);
> +
> +            if (ent == NULL)
> +                break;
> +
> +            string str(ent->d_name);
> +
> +            if (is_file_a_log(str)) {
> +                *logid = (uint16_t) atoi(str.c_str());
> +                update_latest_logid(*logid);
> +                break;
> +            }
> +
> +        } while( 1 );
> +    } 
> +    else
> +    { 
> +        cerr << "Error opening directory" << glogname << endl;
> +        ent    = NULL;
> +        *logid = 0;
> +    }
> +    return  ((ent == NULL) ? 0 : 1);
> +}
> +
> +
> +uint16_t message_create_new_log_event(event_record_t *rec) {
> +
> +    rec->logid = get_new_log_number();
> +    return create_log_event(rec);
> +}
> diff --git a/message.H b/message.H
> new file mode 100644
> index 0000000..26ebe19
> --- /dev/null
> +++ b/message.H
> @@ -0,0 +1,60 @@
> +
> +#include <dirent.h>
> +#include <time.h>
> +
> +#ifdef __cplusplus
> +    #include <cstdint>
> +#else
> +    #include <stdint.h>
> +#endif
> +
> +
> +#ifdef __cplusplus
> +    struct event_log_list {
> +#else
> +    typedef struct _event_log_list {        
> +#endif
> +        DIR *dirp;
> +#ifdef __cplusplus
> +    };
> +#else    
> +    } event_log_list;
> +#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
> +extern "C"  {
> +#endif
> +
> +
> +uint16_t message_create_new_log_event(event_record_t *rec);
> +int      message_load_log(uint16_t logid, event_record_t **rec);
> +void     message_free_log(event_record_t *rec);
> +int      message_get_next_log(uint16_t *logid, event_log_list *log_list);
> +int      message_delete_log(uint16_t logid);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> diff --git a/test.C b/test.C
> new file mode 100644
> index 0000000..afd834e
> --- /dev/null
> +++ b/test.C
> @@ -0,0 +1,92 @@
> +#include <iostream>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +
> +#include "message.H"
> +using namespace std;
> +
> +const char *glogname = "./events";
> +
> +#define ASSERT(a,b)  if(a!=b) {cout << "ASSERT ERROR: line " << __LINE__ << endl; exit(1);}
> +
> +void build_event_record(event_record_t *rec,
> +						uint16_t logid,
> +                        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 load_existing_events(void) {
> +
> +	event_log_list log_list;
> +	uint16_t       logid=0;
> +	event_record_t *rec;
> +
> +	cout << "Loading event log... ";
> +
> +	while (message_get_next_log(&logid, &log_list)) {
> +		cout << " " << int(logid);
> +		message_load_log(logid, &rec);
> +
> +		cout << rec->message << endl;
> +
> +		message_free_log(rec);
> +	}
> +	cout << endl;
> +	
> +	return 0;
> +}
> +
> +
> +int main(int argc, char *argv[]) {
> +
> +	int rc = 0;
> +
> +	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
> +	event_record_t rec, *prec;
> +	event_log_list log_list;
> +	uint16_t logid=0;
> +	int i;
> +
> +	build_event_record(&rec,0, "Testing Message1", "Info", "Association", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),1);
> +	build_event_record(&rec,0, "Testing Message2", "Info", "/dev", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),2);
> +	build_event_record(&rec,0, "Testing Message3", "Info", "Association", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),3);
> +
> +	ASSERT(message_load_log(13, &prec), 0);
> +	ASSERT(message_load_log(1, &prec), 1); message_free_log(prec);
> +
> +	// Test the number of valid logs so far
> +	i = 0;
> +	while (message_get_next_log(&logid, &log_list)) {
> +
> +
> +		cout << int(logid) << endl;
> +		i++;
> +	}
> +	//ASSERT(i,3);
> +
> +	cout << "LOADLOG TEST" << endl;
> +
> +	load_existing_events();
> +
> +	message_delete_log(1);
> +
> +	return rc;
> +}
> \ No newline at end of file
> -- 
> 2.6.4
>
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 859 bytes --]

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

* Re: [PATCH phosphor-event] Event Logs to survive a reboot
  2016-02-02 16:40 ` OpenBMC Patches
  2016-02-03  5:48   ` Daniel Axtens
@ 2016-02-03  6:08   ` Joel Stanley
  2016-02-03  6:22   ` Chris Austen
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Joel Stanley @ 2016-02-03  6:08 UTC (permalink / raw)
  To: OpenBMC Patches; +Cc: OpenBMC Maillist

On Wed, Feb 3, 2016 at 3:40 AM, OpenBMC Patches
<openbmc-patches@stwcx.xyz> wrote:
> 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'.

'make check' is commonly used instead of test. Either way, the make
target should run the test for you.

>
> 1) /var/sys/obmc/events/x

/var/log is generally where logs are stored.

> 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

Should this go into a README?

> ---
>  Makefile               |  29 ++--
>  event_messaged.C       |  44 +++++
>  event_messaged.c       | 341 ---------------------------------------

It looks like you've moved and modified this file in the same commit.
The move should be a separate commit, so we can review the code
changes.

>  event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
>  event_messaged_sdbus.h |  14 ++
>  message.C              | 224 ++++++++++++++++++++++++++
>  message.H              |  60 +++++++
>  test.C                 |  92 +++++++++++
>  8 files changed, 878 insertions(+), 351 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..903ac06 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,27 +1,36 @@
> -TEST      = listfunc
> -OBJS_TEST = $(TEST).o
>
> -EXE     = event_messaged
> +TEST      = test
>
> -OBJS    = $(EXE).o   \
> -          list.o        \
> +EXE       = event_messaged
> +EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
>
> +OBJS_TEST = $(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 $@
> +       $(CXX) $^ $(LDFLAGS) -o $@
>
>  clean:
> -       rm -f $(OBJS) $(EXE) *.o *.d
> +       rm -f $(TEST) *.o *.so $(EXE)
> +
> +
> diff --git a/event_messaged.C b/event_messaged.C
> new file mode 100644
> index 0000000..4376431
> --- /dev/null
> +++ b/event_messaged.C

This file only contains C, so perhaps make it a C file?

> @@ -0,0 +1,44 @@
> +#include <iostream>
> +#include "message.H"
> +#include "event_messaged_sdbus.h"
> +
> +const char *glogname = "/var/lib/obmc/events";
> +
> +using namespace std;
> +
> +

Extra whitespace.

> +// Walk through all the saved logs and reload them in to dbus objects
> +// Needed because on a reboot the existing logs need to be reloaded
> +int load_existing_events(void) {
> +
> +    event_log_list log_list;
> +    uint16_t       logid=0;

Don't initalise this here.

> +
> +    while (message_get_next_log(&logid, &log_list)) {
> +        send_log_to_dbus(logid);
> +    }
> +
> +    return 0;
> +}
> +
> +int main(int argc, char *argv[]) {
> +
> +    int rc = 0;

Don't initalise this here.

> +
> +    if ((rc = build_bus()) < 0) {

This is more readable:

 rc = build_bus();
 if (rc < 0)

> +        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    if ((rc = load_existing_events()) < 0) {
> +        fprintf(stderr, "Event Messager failed add previous logs to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    rc = start_event_monitor();
> +
> +    finish:

This should not be indented.

> +    cleanup_event_monitor();
> +
> +    return rc;
> +}
> \ No newline at end of file


> diff --git a/message.C b/message.C
> new file mode 100644
> index 0000000..31a545a
> --- /dev/null
> +++ b/message.C
> @@ -0,0 +1,224 @@
> +#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>
> +
> +using namespace std;
> +
> +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;
> +};
> +
> +uint16_t g_logid = 0;
> +
> +extern const char *glogname;
> +
> +static uint16_t get_new_log_number(void) {
> +    return ++g_logid;
> +}
> +
> +static void update_latest_logid(uint16_t logid) {
> +    if (logid > g_logid)
> +        g_logid = logid;
> +    return;
> +}
> +
> +inline uint16_t GETLEN(const char *s) {
> +    return (uint16_t) (1 + strlen(s));
> +}

This should be lower case.

> +
> +static uint16_t create_log_event(event_record_t *rec) {
> +
> +    std::ostringstream buffer;
> +    ofstream myfile;
> +    logheader_t hdr;

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

* Re: [PATCH phosphor-event] Event Logs to survive a reboot
  2016-02-02 16:40 ` OpenBMC Patches
  2016-02-03  5:48   ` Daniel Axtens
  2016-02-03  6:08   ` Joel Stanley
@ 2016-02-03  6:22   ` Chris Austen
  2016-02-03  6:31   ` Chris Austen
       [not found]   ` <201602030631.u136VieM002880@d01av03.pok.ibm.com>
  4 siblings, 0 replies; 7+ messages in thread
From: Chris Austen @ 2016-02-03  6:22 UTC (permalink / raw)
  To: Joel Stanley; +Cc: OpenBMC Patches, OpenBMC Maillist

 
Thanks for you insights, I issues this pull request specifically to get feedback.  So here goes...

Chris Austen
POWER Systems Enablement Manager 
(512) 286-5184 (T/L: 363-5184)

-----"openbmc" <openbmc-bounces+austenc=us.ibm.com@lists.ozlabs.org> wrote: -----
To: OpenBMC Patches <openbmc-patches@stwcx.xyz>
From: Joel Stanley 
Sent by: "openbmc" 
Date: 02/03/2016 12:09AM
Cc: OpenBMC Maillist <openbmc@lists.ozlabs.org>
Subject: Re: [PATCH phosphor-event] Event Logs to survive a reboot

On Wed, Feb 3, 2016 at 3:40 AM, OpenBMC Patches
<openbmc-patches@stwcx.xyz> wrote:
> 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'.

'make check' is commonly used instead of test. Either way, the make
target should run the test for you.

CA: Sure I can make that change

>
> 1) /var/sys/obmc/events/x

/var/log is generally where logs are stored.

CA: Typical location for any log from any service? I would imagine a single log file is standard and not a bunch of small ones.

> 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

Should this go into a README?

CA: Yes it will

> ---
>  Makefile               |  29 ++--
>  event_messaged.C       |  44 +++++
>  event_messaged.c       | 341 ---------------------------------------

It looks like you've moved and modified this file in the same commit.
The move should be a separate commit, so we can review the code
changes.

CA: huge refactor best to review that in its entirety.  I could simply rename it in a commit but that is kind of lame
 

>  event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
>  event_messaged_sdbus.h |  14 ++
>  message.C              | 224 ++++++++++++++++++++++++++
>  message.H              |  60 +++++++
>  test.C                 |  92 +++++++++++
>  8 files changed, 878 insertions(+), 351 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..903ac06 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,27 +1,36 @@
> -TEST      = listfunc
> -OBJS_TEST = $(TEST).o
>
> -EXE     = event_messaged
> +TEST      = test
>
> -OBJS    = $(EXE).o   \
> -          list.o        \
> +EXE       = event_messaged
> +EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
>
> +OBJS_TEST = $(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 $@
> +       $(CXX) $^ $(LDFLAGS) -o $@
>
>  clean:
> -       rm -f $(OBJS) $(EXE) *.o *.d
> +       rm -f $(TEST) *.o *.so $(EXE)
> +
> +
> diff --git a/event_messaged.C b/event_messaged.C
> new file mode 100644
> index 0000000..4376431
> --- /dev/null
> +++ b/event_messaged.C

This file only contains C, so perhaps make it a C file?

> @@ -0,0 +1,44 @@
> +#include <iostream>
> +#include "message.H"
> +#include "event_messaged_sdbus.h"
> +
> +const char *glogname = "/var/lib/obmc/events";
> +
> +using namespace std;
> +
> +

Extra whitespace.

> +// Walk through all the saved logs and reload them in to dbus objects
> +// Needed because on a reboot the existing logs need to be reloaded
> +int load_existing_events(void) {
> +
> +    event_log_list log_list;
> +    uint16_t       logid=0;

Don't initalise this here.
CA: ok

> +
> +    while (message_get_next_log(&logid, &log_list)) {
> +        send_log_to_dbus(logid);
> +    }
> +
> +    return 0;
> +}
> +
> +int main(int argc, char *argv[]) {
> +
> +    int rc = 0;

Don't initalise this here.
CA: ok

> +
> +    if ((rc = build_bus()) < 0) {

This is more readable:
CA: ok

 rc = build_bus();
 if (rc < 0)

> +        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    if ((rc = load_existing_events()) < 0) {
> +        fprintf(stderr, "Event Messager failed add previous logs to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    rc = start_event_monitor();
> +
> +    finish:

This should not be indented.
CA: ok

> +    cleanup_event_monitor();
> +
> +    return rc;
> +}
> \ No newline at end of file


> diff --git a/message.C b/message.C
> new file mode 100644
> index 0000000..31a545a
> --- /dev/null
> +++ b/message.C
> @@ -0,0 +1,224 @@
> +#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>
> +
> +using namespace std;
> +
> +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;
> +};
> +
> +uint16_t g_logid = 0;
> +
> +extern const char *glogname;
> +
> +static uint16_t get_new_log_number(void) {
> +    return ++g_logid;
> +}
> +
> +static void update_latest_logid(uint16_t logid) {
> +    if (logid > g_logid)
> +        g_logid = logid;
> +    return;
> +}
> +
> +inline uint16_t GETLEN(const char *s) {
> +    return (uint16_t) (1 + strlen(s));
> +}

This should be lower case.
CA: ok

> +
> +static uint16_t create_log_event(event_record_t *rec) {
> +
> +    std::ostringstream buffer;
> +    ofstream myfile;
> +    logheader_t hdr;
_______________________________________________
openbmc mailing list
openbmc@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/openbmc

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

* Re: [PATCH phosphor-event] Event Logs to survive a reboot
  2016-02-02 16:40 ` OpenBMC Patches
                     ` (2 preceding siblings ...)
  2016-02-03  6:22   ` Chris Austen
@ 2016-02-03  6:31   ` Chris Austen
       [not found]   ` <201602030631.u136VieM002880@d01av03.pok.ibm.com>
  4 siblings, 0 replies; 7+ messages in thread
From: Chris Austen @ 2016-02-03  6:31 UTC (permalink / raw)
  To: Daniel Axtens; +Cc: OpenBMC Patches, openbmc

 


Chris Austen
POWER Systems Enablement Manager 
(512) 286-5184 (T/L: 363-5184)

-----"openbmc" <openbmc-bounces+austenc=us.ibm.com@lists.ozlabs.org> wrote: -----
To: OpenBMC Patches <openbmc-patches@stwcx.xyz>, openbmc@lists.ozlabs.org
From: Daniel Axtens 
Sent by: "openbmc" 
Date: 02/02/2016 11:48PM
Subject: Re: [PATCH phosphor-event] Event Logs to survive a reboot

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
> 2) logs are stored in binary and saved

A couple of broad design questions, and apologies if I've missed some of
the 'backstory' here:

 - Can this log grow unboundedly? Do we need to support logrotate? Do we
   need to enable it now? Will this code deal with the file changing
   underneath it when it's rotated?

 - Is there a compelling reason to store the logs in binary? Can we
   store then in text? Or do we have existing tooling to decode them?

Regards,
Daniel

CA: A log rotate concept seems reasonable.  I can open an issue to ensure that happens.  Any traditional readings on the subject?

CA: The Binary thought process is as follows (and I'm not married to the idea)
  1) The debug developer data is presented as an array of bytes.  So I stored it as an array of bytes.  
  2) Why an array of bytes and not a string?  Well debug data can be up to 2K.  Converting it to ascii makes each log stored as 4K.  
  3) REST is the customer visible interface. no need for anyone outside of the service/support team to be relying on any internals



> 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               |  29 ++--
>  event_messaged.C       |  44 +++++
>  event_messaged.c       | 341 ---------------------------------------
>  event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
>  event_messaged_sdbus.h |  14 ++
>  message.C              | 224 ++++++++++++++++++++++++++
>  message.H              |  60 +++++++
>  test.C                 |  92 +++++++++++
>  8 files changed, 878 insertions(+), 351 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..903ac06 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1,27 +1,36 @@
> -TEST      = listfunc
> -OBJS_TEST = $(TEST).o
>  
> -EXE     = event_messaged
> +TEST      = test
>  
> -OBJS    = $(EXE).o   \
> -          list.o 	 \
> +EXE       = event_messaged
> +EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
>  
> +OBJS_TEST = $(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 $@
> +	$(CXX) $^ $(LDFLAGS) -o $@
>  
>  clean:
> -	rm -f $(OBJS) $(EXE) *.o *.d
> +	rm -f $(TEST) *.o *.so $(EXE)
> +
> +
> diff --git a/event_messaged.C b/event_messaged.C
> new file mode 100644
> index 0000000..4376431
> --- /dev/null
> +++ b/event_messaged.C
> @@ -0,0 +1,44 @@
> +#include <iostream>
> +#include "message.H"
> +#include "event_messaged_sdbus.h"
> +
> +const char *glogname = "/var/lib/obmc/events";
> +
> +using namespace std;
> +
> +
> +// Walk through all the saved logs and reload them in to dbus objects
> +// Needed because on a reboot the existing logs need to be reloaded
> +int load_existing_events(void) {
> +
> +    event_log_list log_list;
> +    uint16_t       logid=0;
> +
> +    while (message_get_next_log(&logid, &log_list)) {
> +        send_log_to_dbus(logid);
> +    }
> +    
> +    return 0;
> +}
> +
> +int main(int argc, char *argv[]) {
> +
> +    int rc = 0;
> +
> +    if ((rc = build_bus()) < 0) {
> +        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
> +        goto finish;
> +    }
> +
> +    if ((rc = load_existing_events()) < 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..fa83e5c
> --- /dev/null
> +++ b/event_messaged_sdbus.c
> @@ -0,0 +1,425 @@
> +#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"
> +
> +/*****************************************************************************/
> +/* 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;
> +
> +} messageEntry_t;
> +
> +
> +static void message_entry_close(messageEntry_t *m) {
> +	free(m);
> +	return;
> +}
> +
> +static void message_entry_new(messageEntry_t **m, uint16_t logid) {
> +	*m          = malloc(sizeof(messageEntry_t));
> +	(*m)->logid = logid;
> +	return;
> +}
> +
> +// After calling this function the gCachedRec will be set
> +static event_record_t* message_record_open(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(logid, &rec)) {
> +			gCachedRec = rec;
> +			return gCachedRec;
> +		} else 
> +			return NULL;
> +	} 
> +
> +	if (logid == gCachedRec->logid) {
> +		r = 1;
> +
> +	} else {
> +		message_free_log(gCachedRec);
> +		gCachedRec = NULL;
> +
> +		r = message_load_log(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->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->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;
> +	size_t   n = 4;
> +	uint8_t *p;
> +	int r;
> +	uint16_t logid;
> +	event_record_t rec;
> +
> +	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;
> +
> +
> +	logid = message_create_new_log_event(&rec);
> +
> +	if (logid) 
> +		r = send_log_to_dbus(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) {
> +
> +	uint8_t p[] = {0x30, 0x32, 0x34, 0x36};
> +	uint16_t logid;
> +	event_record_t rec;
> +
> +    rec.message     = (char*) "Testing Message";
> +    rec.severity    = (char*) "Info";
> +    rec.association = (char*) "Association";
> +    rec.reportedby  = (char*) "Test";
> +    rec.p           = (uint8_t*) p;
> +    rec.n           = sizeof(*p);
> +
> +	logid = message_create_new_log_event(&rec);
> +	send_log_to_dbus(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->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->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("DevelopmentData", "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(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);
> +
> +	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(void) {
> +
> +	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,
> +	                             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));
> +	}	
> +	
> +	/* 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..a6aac94
> --- /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(void);
> +	int send_log_to_dbus(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..31a545a
> --- /dev/null
> +++ b/message.C
> @@ -0,0 +1,224 @@
> +#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>
> +
> +using namespace std;
> +
> +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;
> +};
> +
> +uint16_t g_logid = 0;
> +
> +extern const char *glogname;
> +
> +static uint16_t get_new_log_number(void) {
> +    return ++g_logid;
> +}
> +
> +static void update_latest_logid(uint16_t logid) {
> +    if (logid > g_logid)
> +        g_logid = logid;
> +    return;
> +}
> +
> +inline uint16_t GETLEN(const char *s) {
> +    return (uint16_t) (1 + strlen(s));
> +}
> +
> +static uint16_t create_log_event(event_record_t *rec) {
> +
> +    std::ostringstream buffer;
> +    ofstream myfile;
> +    logheader_t hdr;
> +
> +
> +    buffer << glogname << "/" << int(rec->logid) ;
> +
> +    cout << buffer.str() << endl;
> +
> +    hdr.eyecatcher     = g_eyecatcher;
> +    hdr.version        = g_version;
> +    hdr.logid          = rec->logid;
> +    hdr.timestamp      = time(NULL);
> +    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();
> +
> +    return rec->logid;
> +}
> +
> +static int 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 << glogname << "/" << 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;
> +}
> +
> +
> +
> +int message_load_log(uint16_t logid, event_record_t **rec) {
> +
> +    std::ostringstream buffer;
> +    ifstream f;
> +    logheader_t hdr;
> +
> +    buffer << glogname << "/" << 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 message_free_log(event_record_t *rec) {
> +
> +    delete[] rec->message;
> +    delete[] rec->severity;
> +    delete[] rec->association;
> +    delete[] rec->reportedby;
> +    delete[] rec->p;
> +    delete rec;
> +
> +    return ;
> +}
> +
> +int message_delete_log(uint16_t logid) {
> +
> +    std::stringstream buffer;
> +    string s;
> +
> +    buffer << glogname << "/" << int(logid);
> +
> +    s = buffer.str();
> +    std::remove(s.c_str());
> +
> +    return 0;
> +}
> +
> +
> +int message_get_next_log(uint16_t *logid, event_log_list *log_list) {
> +
> +    std::ostringstream buffer;
> +    struct dirent *ent;
> +
> +    if (*logid==0)
> +        log_list->dirp = opendir(glogname);
> +
> +    if(log_list->dirp)
> +    {
> +        do {
> +            ent = readdir(log_list->dirp);
> +
> +            if (ent == NULL)
> +                break;
> +
> +            string str(ent->d_name);
> +
> +            if (is_file_a_log(str)) {
> +                *logid = (uint16_t) atoi(str.c_str());
> +                update_latest_logid(*logid);
> +                break;
> +            }
> +
> +        } while( 1 );
> +    } 
> +    else
> +    { 
> +        cerr << "Error opening directory" << glogname << endl;
> +        ent    = NULL;
> +        *logid = 0;
> +    }
> +    return  ((ent == NULL) ? 0 : 1);
> +}
> +
> +
> +uint16_t message_create_new_log_event(event_record_t *rec) {
> +
> +    rec->logid = get_new_log_number();
> +    return create_log_event(rec);
> +}
> diff --git a/message.H b/message.H
> new file mode 100644
> index 0000000..26ebe19
> --- /dev/null
> +++ b/message.H
> @@ -0,0 +1,60 @@
> +
> +#include <dirent.h>
> +#include <time.h>
> +
> +#ifdef __cplusplus
> +    #include <cstdint>
> +#else
> +    #include <stdint.h>
> +#endif
> +
> +
> +#ifdef __cplusplus
> +    struct event_log_list {
> +#else
> +    typedef struct _event_log_list {        
> +#endif
> +        DIR *dirp;
> +#ifdef __cplusplus
> +    };
> +#else    
> +    } event_log_list;
> +#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
> +extern "C"  {
> +#endif
> +
> +
> +uint16_t message_create_new_log_event(event_record_t *rec);
> +int      message_load_log(uint16_t logid, event_record_t **rec);
> +void     message_free_log(event_record_t *rec);
> +int      message_get_next_log(uint16_t *logid, event_log_list *log_list);
> +int      message_delete_log(uint16_t logid);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> diff --git a/test.C b/test.C
> new file mode 100644
> index 0000000..afd834e
> --- /dev/null
> +++ b/test.C
> @@ -0,0 +1,92 @@
> +#include <iostream>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +
> +#include "message.H"
> +using namespace std;
> +
> +const char *glogname = "./events";
> +
> +#define ASSERT(a,b)  if(a!=b) {cout << "ASSERT ERROR: line " << __LINE__ << endl; exit(1);}
> +
> +void build_event_record(event_record_t *rec,
> +						uint16_t logid,
> +                        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 load_existing_events(void) {
> +
> +	event_log_list log_list;
> +	uint16_t       logid=0;
> +	event_record_t *rec;
> +
> +	cout << "Loading event log... ";
> +
> +	while (message_get_next_log(&logid, &log_list)) {
> +		cout << " " << int(logid);
> +		message_load_log(logid, &rec);
> +
> +		cout << rec->message << endl;
> +
> +		message_free_log(rec);
> +	}
> +	cout << endl;
> +	
> +	return 0;
> +}
> +
> +
> +int main(int argc, char *argv[]) {
> +
> +	int rc = 0;
> +
> +	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
> +	event_record_t rec, *prec;
> +	event_log_list log_list;
> +	uint16_t logid=0;
> +	int i;
> +
> +	build_event_record(&rec,0, "Testing Message1", "Info", "Association", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),1);
> +	build_event_record(&rec,0, "Testing Message2", "Info", "/dev", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),2);
> +	build_event_record(&rec,0, "Testing Message3", "Info", "Association", "Test", p, 4);
> +	ASSERT(message_create_new_log_event(&rec),3);
> +
> +	ASSERT(message_load_log(13, &prec), 0);
> +	ASSERT(message_load_log(1, &prec), 1); message_free_log(prec);
> +
> +	// Test the number of valid logs so far
> +	i = 0;
> +	while (message_get_next_log(&logid, &log_list)) {
> +
> +
> +		cout << int(logid) << endl;
> +		i++;
> +	}
> +	//ASSERT(i,3);
> +
> +	cout << "LOADLOG TEST" << endl;
> +
> +	load_existing_events();
> +
> +	message_delete_log(1);
> +
> +	return rc;
> +}
> \ No newline at end of file
> -- 
> 2.6.4
>
>
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc
_______________________________________________
openbmc mailing list
openbmc@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/openbmc


[attachment "signature.asc" removed by Chris Austen/Austin/IBM]

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

* Re: [PATCH phosphor-event] Event Logs to survive a reboot
       [not found]   ` <201602030631.u136VieM002880@d01av03.pok.ibm.com>
@ 2016-02-03 13:21     ` Daniel Axtens
  0 siblings, 0 replies; 7+ messages in thread
From: Daniel Axtens @ 2016-02-03 13:21 UTC (permalink / raw)
  To: Chris Austen; +Cc: OpenBMC Patches, openbmc

[-- Attachment #1: Type: text/plain, Size: 44378 bytes --]

Hi Chris,

>
> CA: A log rotate concept seems reasonable.  I can open an issue to ensure that happens.  Any traditional readings on the subject?

Traditionally in linux-land you'd stick a single log file in /var/log,
and use a program called logrotate to rotate it. Logrotate takes a
configuration snippet in /etc somewhere and then automatically can deal
with moving files, keeping a certain number, archiving old logs, sending
signals to processes so they know they've been rotated and can re-open
the log file, etc, etc. `man logrotate` is a good start: it'll be
running on any desktop or server linux system.

>
> CA: The Binary thought process is as follows (and I'm not married to the idea)
>   1) The debug developer data is presented as an array of bytes.  So I stored it as an array of bytes.  
>   2) Why an array of bytes and not a string?  Well debug data can be up to 2K.  Converting it to ascii makes each log stored as 4K.  
>   3) REST is the customer visible interface. no need for anyone outside of the service/support team to be relying on any internals
>
>
Hmm. These are decent points. My concern is that we then:
 - need to maintain the tool to decode them
 - suffer from increased debug turnaround.

I'm not clear on the disk-space limits in BMC land - 2k to 4k seems small to
me but maybe it's a real issue in the BMC case.

I'm not married to text logs either, but I think we should generally
prefer them to binary logs where there's not a compelling reason
otherwise.

Thanks for your helpful and thoughtful responses!

Regards,
Daniel

>
>> 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               |  29 ++--
>>  event_messaged.C       |  44 +++++
>>  event_messaged.c       | 341 ---------------------------------------
>>  event_messaged_sdbus.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  event_messaged_sdbus.h |  14 ++
>>  message.C              | 224 ++++++++++++++++++++++++++
>>  message.H              |  60 +++++++
>>  test.C                 |  92 +++++++++++
>>  8 files changed, 878 insertions(+), 351 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..903ac06 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -1,27 +1,36 @@
>> -TEST      = listfunc
>> -OBJS_TEST = $(TEST).o
>>  
>> -EXE     = event_messaged
>> +TEST      = test
>>  
>> -OBJS    = $(EXE).o   \
>> -          list.o 	 \
>> +EXE       = event_messaged
>> +EXE_OBJS  = $(EXE).o message.o event_messaged_sdbus.o list.o
>>  
>> +OBJS_TEST = $(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 $@
>> +	$(CXX) $^ $(LDFLAGS) -o $@
>>  
>>  clean:
>> -	rm -f $(OBJS) $(EXE) *.o *.d
>> +	rm -f $(TEST) *.o *.so $(EXE)
>> +
>> +
>> diff --git a/event_messaged.C b/event_messaged.C
>> new file mode 100644
>> index 0000000..4376431
>> --- /dev/null
>> +++ b/event_messaged.C
>> @@ -0,0 +1,44 @@
>> +#include <iostream>
>> +#include "message.H"
>> +#include "event_messaged_sdbus.h"
>> +
>> +const char *glogname = "/var/lib/obmc/events";
>> +
>> +using namespace std;
>> +
>> +
>> +// Walk through all the saved logs and reload them in to dbus objects
>> +// Needed because on a reboot the existing logs need to be reloaded
>> +int load_existing_events(void) {
>> +
>> +    event_log_list log_list;
>> +    uint16_t       logid=0;
>> +
>> +    while (message_get_next_log(&logid, &log_list)) {
>> +        send_log_to_dbus(logid);
>> +    }
>> +    
>> +    return 0;
>> +}
>> +
>> +int main(int argc, char *argv[]) {
>> +
>> +    int rc = 0;
>> +
>> +    if ((rc = build_bus()) < 0) {
>> +        fprintf(stderr, "Event Messager failed to connect to dbus rc=%d", rc);
>> +        goto finish;
>> +    }
>> +
>> +    if ((rc = load_existing_events()) < 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..fa83e5c
>> --- /dev/null
>> +++ b/event_messaged_sdbus.c
>> @@ -0,0 +1,425 @@
>> +#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"
>> +
>> +/*****************************************************************************/
>> +/* 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;
>> +
>> +} messageEntry_t;
>> +
>> +
>> +static void message_entry_close(messageEntry_t *m) {
>> +	free(m);
>> +	return;
>> +}
>> +
>> +static void message_entry_new(messageEntry_t **m, uint16_t logid) {
>> +	*m          = malloc(sizeof(messageEntry_t));
>> +	(*m)->logid = logid;
>> +	return;
>> +}
>> +
>> +// After calling this function the gCachedRec will be set
>> +static event_record_t* message_record_open(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(logid, &rec)) {
>> +			gCachedRec = rec;
>> +			return gCachedRec;
>> +		} else 
>> +			return NULL;
>> +	} 
>> +
>> +	if (logid == gCachedRec->logid) {
>> +		r = 1;
>> +
>> +	} else {
>> +		message_free_log(gCachedRec);
>> +		gCachedRec = NULL;
>> +
>> +		r = message_load_log(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->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->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;
>> +	size_t   n = 4;
>> +	uint8_t *p;
>> +	int r;
>> +	uint16_t logid;
>> +	event_record_t rec;
>> +
>> +	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;
>> +
>> +
>> +	logid = message_create_new_log_event(&rec);
>> +
>> +	if (logid) 
>> +		r = send_log_to_dbus(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) {
>> +
>> +	uint8_t p[] = {0x30, 0x32, 0x34, 0x36};
>> +	uint16_t logid;
>> +	event_record_t rec;
>> +
>> +    rec.message     = (char*) "Testing Message";
>> +    rec.severity    = (char*) "Info";
>> +    rec.association = (char*) "Association";
>> +    rec.reportedby  = (char*) "Test";
>> +    rec.p           = (uint8_t*) p;
>> +    rec.n           = sizeof(*p);
>> +
>> +	logid = message_create_new_log_event(&rec);
>> +	send_log_to_dbus(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->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->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("DevelopmentData", "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(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);
>> +
>> +	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(void) {
>> +
>> +	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,
>> +	                             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));
>> +	}	
>> +	
>> +	/* 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..a6aac94
>> --- /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(void);
>> +	int send_log_to_dbus(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..31a545a
>> --- /dev/null
>> +++ b/message.C
>> @@ -0,0 +1,224 @@
>> +#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>
>> +
>> +using namespace std;
>> +
>> +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;
>> +};
>> +
>> +uint16_t g_logid = 0;
>> +
>> +extern const char *glogname;
>> +
>> +static uint16_t get_new_log_number(void) {
>> +    return ++g_logid;
>> +}
>> +
>> +static void update_latest_logid(uint16_t logid) {
>> +    if (logid > g_logid)
>> +        g_logid = logid;
>> +    return;
>> +}
>> +
>> +inline uint16_t GETLEN(const char *s) {
>> +    return (uint16_t) (1 + strlen(s));
>> +}
>> +
>> +static uint16_t create_log_event(event_record_t *rec) {
>> +
>> +    std::ostringstream buffer;
>> +    ofstream myfile;
>> +    logheader_t hdr;
>> +
>> +
>> +    buffer << glogname << "/" << int(rec->logid) ;
>> +
>> +    cout << buffer.str() << endl;
>> +
>> +    hdr.eyecatcher     = g_eyecatcher;
>> +    hdr.version        = g_version;
>> +    hdr.logid          = rec->logid;
>> +    hdr.timestamp      = time(NULL);
>> +    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();
>> +
>> +    return rec->logid;
>> +}
>> +
>> +static int 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 << glogname << "/" << 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;
>> +}
>> +
>> +
>> +
>> +int message_load_log(uint16_t logid, event_record_t **rec) {
>> +
>> +    std::ostringstream buffer;
>> +    ifstream f;
>> +    logheader_t hdr;
>> +
>> +    buffer << glogname << "/" << 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 message_free_log(event_record_t *rec) {
>> +
>> +    delete[] rec->message;
>> +    delete[] rec->severity;
>> +    delete[] rec->association;
>> +    delete[] rec->reportedby;
>> +    delete[] rec->p;
>> +    delete rec;
>> +
>> +    return ;
>> +}
>> +
>> +int message_delete_log(uint16_t logid) {
>> +
>> +    std::stringstream buffer;
>> +    string s;
>> +
>> +    buffer << glogname << "/" << int(logid);
>> +
>> +    s = buffer.str();
>> +    std::remove(s.c_str());
>> +
>> +    return 0;
>> +}
>> +
>> +
>> +int message_get_next_log(uint16_t *logid, event_log_list *log_list) {
>> +
>> +    std::ostringstream buffer;
>> +    struct dirent *ent;
>> +
>> +    if (*logid==0)
>> +        log_list->dirp = opendir(glogname);
>> +
>> +    if(log_list->dirp)
>> +    {
>> +        do {
>> +            ent = readdir(log_list->dirp);
>> +
>> +            if (ent == NULL)
>> +                break;
>> +
>> +            string str(ent->d_name);
>> +
>> +            if (is_file_a_log(str)) {
>> +                *logid = (uint16_t) atoi(str.c_str());
>> +                update_latest_logid(*logid);
>> +                break;
>> +            }
>> +
>> +        } while( 1 );
>> +    } 
>> +    else
>> +    { 
>> +        cerr << "Error opening directory" << glogname << endl;
>> +        ent    = NULL;
>> +        *logid = 0;
>> +    }
>> +    return  ((ent == NULL) ? 0 : 1);
>> +}
>> +
>> +
>> +uint16_t message_create_new_log_event(event_record_t *rec) {
>> +
>> +    rec->logid = get_new_log_number();
>> +    return create_log_event(rec);
>> +}
>> diff --git a/message.H b/message.H
>> new file mode 100644
>> index 0000000..26ebe19
>> --- /dev/null
>> +++ b/message.H
>> @@ -0,0 +1,60 @@
>> +
>> +#include <dirent.h>
>> +#include <time.h>
>> +
>> +#ifdef __cplusplus
>> +    #include <cstdint>
>> +#else
>> +    #include <stdint.h>
>> +#endif
>> +
>> +
>> +#ifdef __cplusplus
>> +    struct event_log_list {
>> +#else
>> +    typedef struct _event_log_list {        
>> +#endif
>> +        DIR *dirp;
>> +#ifdef __cplusplus
>> +    };
>> +#else    
>> +    } event_log_list;
>> +#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
>> +extern "C"  {
>> +#endif
>> +
>> +
>> +uint16_t message_create_new_log_event(event_record_t *rec);
>> +int      message_load_log(uint16_t logid, event_record_t **rec);
>> +void     message_free_log(event_record_t *rec);
>> +int      message_get_next_log(uint16_t *logid, event_log_list *log_list);
>> +int      message_delete_log(uint16_t logid);
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> diff --git a/test.C b/test.C
>> new file mode 100644
>> index 0000000..afd834e
>> --- /dev/null
>> +++ b/test.C
>> @@ -0,0 +1,92 @@
>> +#include <iostream>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <stdint.h>
>> +
>> +#include "message.H"
>> +using namespace std;
>> +
>> +const char *glogname = "./events";
>> +
>> +#define ASSERT(a,b)  if(a!=b) {cout << "ASSERT ERROR: line " << __LINE__ << endl; exit(1);}
>> +
>> +void build_event_record(event_record_t *rec,
>> +						uint16_t logid,
>> +                        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 load_existing_events(void) {
>> +
>> +	event_log_list log_list;
>> +	uint16_t       logid=0;
>> +	event_record_t *rec;
>> +
>> +	cout << "Loading event log... ";
>> +
>> +	while (message_get_next_log(&logid, &log_list)) {
>> +		cout << " " << int(logid);
>> +		message_load_log(logid, &rec);
>> +
>> +		cout << rec->message << endl;
>> +
>> +		message_free_log(rec);
>> +	}
>> +	cout << endl;
>> +	
>> +	return 0;
>> +}
>> +
>> +
>> +int main(int argc, char *argv[]) {
>> +
>> +	int rc = 0;
>> +
>> +	uint8_t p[] = {0x3, 0x32, 0x34, 0x36};
>> +	event_record_t rec, *prec;
>> +	event_log_list log_list;
>> +	uint16_t logid=0;
>> +	int i;
>> +
>> +	build_event_record(&rec,0, "Testing Message1", "Info", "Association", "Test", p, 4);
>> +	ASSERT(message_create_new_log_event(&rec),1);
>> +	build_event_record(&rec,0, "Testing Message2", "Info", "/dev", "Test", p, 4);
>> +	ASSERT(message_create_new_log_event(&rec),2);
>> +	build_event_record(&rec,0, "Testing Message3", "Info", "Association", "Test", p, 4);
>> +	ASSERT(message_create_new_log_event(&rec),3);
>> +
>> +	ASSERT(message_load_log(13, &prec), 0);
>> +	ASSERT(message_load_log(1, &prec), 1); message_free_log(prec);
>> +
>> +	// Test the number of valid logs so far
>> +	i = 0;
>> +	while (message_get_next_log(&logid, &log_list)) {
>> +
>> +
>> +		cout << int(logid) << endl;
>> +		i++;
>> +	}
>> +	//ASSERT(i,3);
>> +
>> +	cout << "LOADLOG TEST" << endl;
>> +
>> +	load_existing_events();
>> +
>> +	message_delete_log(1);
>> +
>> +	return rc;
>> +}
>> \ No newline at end of file
>> -- 
>> 2.6.4
>>
>>
>> _______________________________________________
>> openbmc mailing list
>> openbmc@lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/openbmc
> _______________________________________________
> openbmc mailing list
> openbmc@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/openbmc
>
>
> [attachment "signature.asc" removed by Chris Austen/Austin/IBM]

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 859 bytes --]

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

end of thread, other threads:[~2016-02-03 13:21 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02 16:40 [PATCH phosphor-event] Event Logs to survive a reboot OpenBMC Patches
2016-02-02 16:40 ` OpenBMC Patches
2016-02-03  5:48   ` Daniel Axtens
2016-02-03  6:08   ` Joel Stanley
2016-02-03  6:22   ` Chris Austen
2016-02-03  6:31   ` Chris Austen
     [not found]   ` <201602030631.u136VieM002880@d01av03.pok.ibm.com>
2016-02-03 13:21     ` Daniel Axtens

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.