Implement deserialisation of service_failed_event
authorŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 2 Jun 2017 14:45:35 +0000 (16:45 +0200)
committerŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 9 Jun 2017 15:41:06 +0000 (17:41 +0200)
Allocate service_failed_event and fill it with data loaded from the
database.

Change-Id: Ib3d82e92e6e3c21cc37859aaef443b9b991c06e5

src/core/event.c
src/core/event.h
src/core/service.c
src/core/service.h
src/event_types/service_failed_event.c
src/util/common.c
src/util/common.h

index 5864eddf242eb2637fa5da3a3ba106ffeb056f2b..f2e828fea7951b0d31a60fb95fa7ca847778300f 100644 (file)
 #include <errno.h>
 #include <systemd/sd-id128.h>
 
+#include "common.h"
 #include "event.h"
+#include "log.h"
 #include "module.h"
-#include "common.h"
 
 struct event_factory {
        struct faultd_module module;
@@ -81,18 +82,42 @@ void faultd_event_type_unregister(struct faultd_event_type *type)
 int faultd_event_create(const char *type, void *data, struct faultd_event **ev)
 {
        struct faultd_event_type *ev_type;
+       bool from_bson = (strcmp(type, BSON_EVENT_ID) == 0);
+       const char *t=type;
        int ret;
 
        if (!type)
                return -EINVAL;
 
+       if (from_bson) {
+               bson *d = data;
+               bson_iterator it;
+               bson_type bt;
+
+               /* get event type name from bson */
+               BSON_ITERATOR_INIT(&it, d);
+               bt = bson_find_fieldpath_value(EV_TYPE_NAME, &it);
+               if (!BSON_IS_STRING_TYPE(bt))
+                       return -EINVAL;
+               type = bson_iterator_value(&it);
+       }
+
        list_for_each_entry(ev_type, &event_factory.types, node)
-               if (strcmp(ev_type->name, type) == 0)
+               if (strcmp(ev_type->name, t) == 0)
                        break;
        if (&ev_type->node == &event_factory.types)
                return -ENOENT;
 
-       ret = ev_type->allocate_event(ev_type, data, ev);
+       if (from_bson) {
+               if (ev_type->deserialize_event != NULL)
+                       ret = ev_type->deserialize_event(ev_type, data, ev);
+               else
+                       log_error("Event type \"%s\" does not support deserialisation.",
+                                         ev_type->name);
+       /* faultd_event_init_internal here? (old boot_id and oid) */
+       } else
+               ret = ev_type->allocate_event(ev_type, data, ev);
+       /* faultd_event_init_internal here? (new boot_id and oid) */
 
        return ret;
 }
@@ -136,3 +161,42 @@ void faultd_event_serialize_internal(struct faultd_event *ev, bson *out)
        bson_append_string(out, EV_TYPE_NAME, ev->type->name);
        faultd_bson_append_timespec(out, EV_TIMESTAMP, &ev->timestamp);
 }
+
+int faultd_event_deserialize_internal(const bson* in, struct faultd_event *ev)
+{
+       bson_iterator it;
+       bson_type bt;
+       int ret = -EINVAL;
+
+       BSON_ITERATOR_INIT(&it, in);
+
+       while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
+               bson b;
+               if ((bt == BSON_BINDATA) &&
+                       ((bson_iterator_bin_type(&it) == BSON_BIN_UUID_OLD) ||
+                        (bson_iterator_bin_type(&it) == BSON_BIN_UUID)) &&
+                       (strcmp(EV_BOOT_ID, bson_iterator_key(&it)) == 0))
+
+                       memcpy(&ev->boot_id, bson_iterator_value(&it), sizeof(ev->boot_id));
+
+               else if (BSON_IS_STRING_TYPE(bt) &&
+                                (strcmp(EV_TYPE_NAME, bson_iterator_key(&it)) == 0)) {
+
+                       ev->type->name = strdup(bson_iterator_value(&it));
+                       if (ev->type->name == NULL) {
+                               ret = -errno;
+                               goto finish;
+                       }
+
+               } else if ((bt == BSON_OBJECT) &&
+                                  (strcmp(EV_TIMESTAMP, bson_iterator_key(&it)) == 0)) {
+
+                       bson_init_finished_data(&b, bson_iterator_value(&it));
+                       faultd_bson_get_timespec(&b, &ev->timestamp);
+
+               }
+       }
+       ret = 0;
+finish:
+       return ret;
+}
index 963bb90ee39b604f344db2064b47e698a59ca33e..b9fb1519f6e2c9661601b3b486eeefa930d8d505 100644 (file)
@@ -33,6 +33,8 @@
 #define EV_TIMESTAMP "ts"
 #define EV_TYPE_NAME "tn"
 
+#define BSON_EVENT_ID "bson_event"
+
 struct faultd_event;
 
 struct faultd_event_ops {
@@ -50,7 +52,10 @@ struct faultd_event_type {
 
        /* Allocate event based on passed data */
        int (*allocate_event)(struct faultd_event_type *type,
-                                                 void *data, struct faultd_event **);
+                                                 void *data, struct faultd_event **ev);
+
+       int (*deserialize_event)(struct faultd_event_type *type,
+                                                        bson *data, struct faultd_event **ev);
 
        /* To be used by event factory */
        struct list_head node;
@@ -134,4 +139,6 @@ static inline void faultd_event_cleanup_internal(struct faultd_event *ev) {}
 
 void faultd_event_serialize_internal(struct faultd_event *ev, bson *out);
 
+int faultd_event_deserialize_internal(const bson* in, struct faultd_event *ev);
+
 #endif /* FAULTD_EVENT_H */
index fe5e318aafb00f2ca63de3d28cf3a538d990f7f3..537df551cea063cc12fda3e74313b2ff9e7edfba 100644 (file)
@@ -234,3 +234,24 @@ void systemd_service_serialize(struct systemd_service *s, bson* out)
        bson_append_string(out, SYSD_SERVICE_DBUS_PATH, s->dbus_path);
        bson_append_finish_object(out);
 }
+
+int systemd_service_deserialize(const bson* in, struct systemd_service *s)
+{
+       bson_iterator it;
+       bson_type bt;
+       int ret = -EINVAL;
+
+       BSON_ITERATOR_INIT(&it, in);
+       bt = bson_iterator_next(&it);
+       if (!BSON_IS_STRING_TYPE(bt))
+               goto finish;
+       if (strcmp(SYSD_SERVICE_DBUS_PATH, bson_iterator_key(&it)) != 0)
+               goto finish;
+       s->dbus_path = strdup(bson_iterator_value(&it));
+       if (s->dbus_path == NULL)
+               ret = -errno;
+       else
+               ret = 0;
+finish:
+       return ret;
+}
index d4415e739b2df1461a485dd81c26e02857ec31cb..01ea608e271e63672f3a6acc2e06c9a8a940cbe4 100644 (file)
@@ -42,6 +42,7 @@ int systemd_service_init(const char *dbus_path, struct systemd_service *s);
 void systemd_service_cleanup(struct systemd_service *s);
 int systemd_get_unit_by_pid(pid_t pid, const char **name);
 void systemd_service_serialize(struct systemd_service *s, bson *out);
+int systemd_service_deserialize(const bson *out, struct systemd_service *s);
 
 static inline int systemd_service_is_of_type(struct systemd_service *s,
                                                                                         char *type)
index b05facce6243215377e81638ab6a134803575323..9de10a4fab51ba514e58ed0076e2f1ee8556a951 100644 (file)
@@ -36,7 +36,7 @@ static int allocate_sf_event(struct faultd_event_type *type,
 
        ret = faultd_event_init_internal(type, &sf_ev->event);
        if (ret)
-               goto free_rv_ev;
+               goto free_sf_ev;
 
        /* TODO */
        sf_ev->service = sf_ev_data->service;
@@ -45,12 +45,62 @@ static int allocate_sf_event(struct faultd_event_type *type,
 
        *ev = &sf_ev->event;
        return 0;
-free_rv_ev:
+free_sf_ev:
        free(sf_ev);
 
        return ret;
 }
 
+static int deserialize_sf_event(struct faultd_event_type *type,
+                                                               bson *data, struct faultd_event **ev)
+{
+       int ret = -EINVAL;
+       struct sf_event_data sf_ev_data;
+       bson_type bt;
+       bson_iterator it;
+
+       memset(&sf_ev_data, 0, sizeof(sf_ev_data));
+       BSON_ITERATOR_INIT(&it, data);
+
+       while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
+
+               if ((bt == BSON_OBJECT) &&
+                       (strcmp(SYSD_SERVICE, bson_iterator_key(&it)) == 0)) {
+                       bson svc;
+
+                       bson_init_finished_data(&svc, bson_iterator_value(&it));
+                       ret = systemd_service_deserialize(&svc, &sf_ev_data.service);
+                       if (ret < 0)
+                               goto finish;
+
+               } else if ((bt == BSON_TIMESTAMP) &&
+                                  (strcmp(SF_EV_DTIME, bson_iterator_key(&it)))) {
+                       sf_ev_data.detection_time = bson_iterator_time_t(&it);
+               }
+
+       }
+
+       ret = allocate_sf_event(type, &sf_ev_data, ev);
+       if (ret < 0) {
+               free(sf_ev_data.service.dbus_path);
+               goto finish;
+       }
+
+       ret = faultd_event_deserialize_internal(data, *ev);
+       if (ret < 0) {
+               struct service_failed_event *sf_ev =
+                       to_service_failed_event(*ev);
+               free(sf_ev_data.service.dbus_path);
+               sf_ev_data.service.dbus_path = NULL;
+               free(sf_ev);
+               goto finish;
+       }
+
+       ret = 0;
+finish:
+       return ret;
+}
+
 static void sf_event_release(struct faultd_event *ev)
 {
        struct service_failed_event *sf_ev =
@@ -96,6 +146,7 @@ static struct faultd_event_type service_failed_event_type = {
                .to_string = sf_event_to_string,
        },
        .allocate_event = allocate_sf_event,
+       .deserialize_event = deserialize_sf_event,
        .node = LIST_HEAD_INIT(service_failed_event_type.node),
 };
 
index 3d3c910a9fe27de94132b4bec388353c9a3ce6a6..bebde090c6963fff4b43af612f6460814bd80d79 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <ejdb/bson.h>
+#include <errno.h>
+#include <string.h>
 #include <time.h>
 
 #include "common.h"
@@ -25,6 +27,34 @@ GENERATE_BSON_APPEND_STRUCT(timespec,
                                                        bson_append_long(out, "sec", data->tv_sec);
                                                        bson_append_long(out, "nsec", data->tv_nsec);
                                                        )
+int faultd_bson_get_timespec(const bson *in, struct timespec *t) {
+       int ret = -EINVAL;
+       bson_iterator it;
+       bson_type bt;
+       bool sec, nsec;
+
+       BSON_ITERATOR_INIT(&it, in);
+       while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
+               if ((bt == BSON_LONG) &&
+                       (strcmp("sec", bson_iterator_key(&it)) == 0)){
+
+                       sec = true;
+                       t->tv_sec = bson_iterator_long(&it);
+
+               } else if ((bt == BSON_LONG) &&
+                                  (strcmp("nsec", bson_iterator_key(&it)) == 0)) {
+
+                       nsec = true;
+                       t->tv_nsec = bson_iterator_long(&it);
+
+               }
+       }
+
+       if (sec && nsec)
+         ret = 0;
+
+       return ret;
+}
 
 int bson_fill_empty(bson *b)
 {
index 6ae1cc222af104a0ad6e74a2532be691e052bf52..a17581e4375957b8904b808318118c9ab5481b2a 100644 (file)
@@ -62,6 +62,7 @@ static inline void freep(void *p)
        }
 
 DECLARE_BSON_APPEND_STRUCT(timespec);
+int faultd_bson_get_timespec(const bson *in, struct timespec *t);
 
 #define BSON_EMPTY_SIZE (4 /* len */ + 1 /* \0 */)