Implement deserialisation of service_failed_event 70/132970/10
authorŁukasz Stelmach <l.stelmach@samsung.com>
Fri, 2 Jun 2017 14:45:35 +0000 (16:45 +0200)
committerKonrad Kuchciak <k.kuchciak@samsung.com>
Wed, 19 Jul 2017 07:26:20 +0000 (09:26 +0200)
Allocate service_failed_event and fill it with data loaded from the
database.

Change-Id: Ib3d82e92e6e3c21cc37859aaef443b9b991c06e5
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
[ Remove BSON_BIN_UUID_OLD due to compilation error with new EJDB
version. ]
Signed-off-by: Konrad Kuchciak <k.kuchciak@samsung.com>
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..66305333ea6fbd1147d0054b27884e44bd032379 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,19 +82,41 @@ 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;
-       int ret;
+       bool from_bson;
+       int ret = -EINVAL;
 
        if (!type)
-               return -EINVAL;
+               return ret;
+
+       from_bson = (strcmp(type, BSON_EVENT_ID) == 0);
+       if (from_bson) {
+               bson *d = data;
+               /* get event type name from bson */
+               type = bson_get_string(d, EV_TYPE_NAME);
+               if (type == NULL)
+                       return ret;
+       }
 
+       ret = -ENOENT;
        list_for_each_entry(ev_type, &event_factory.types, node)
                if (strcmp(ev_type->name, type) == 0)
                        break;
        if (&ev_type->node == &event_factory.types)
-               return -ENOENT;
-
-       ret = ev_type->allocate_event(ev_type, data, ev);
+               return ret;
 
+       if (from_bson) {
+               if (ev_type->deserialize_event == NULL) {
+                       ret = -ENOTSUP;
+                       log_error("Event type \"%s\" does not support deserialisation.",
+                                         ev_type->name);
+               } else {
+                       ret = ev_type->deserialize_event(ev_type, data, ev);
+                       /* 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 +159,35 @@ 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_type *ev_type, struct faultd_event *ev)
+{
+       bson_iterator it;
+       bson_type bt;
+       int ret = -EINVAL;
+
+       ev->type = ev_type;
+       ev->ops = ev_type->default_ops;
+
+       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) &&
+                       (strcmp(EV_BOOT_ID, bson_iterator_key(&it)) == 0))
+
+                       memcpy(&ev->boot_id, bson_iterator_bin_data(&it), sizeof(ev->boot_id));
+
+               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 9c00edbb2579e785f6d03f3121bfb1881756cee7..3bf08fcd021405e163c8bc4ba96e7e3f32f9ac7d 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_type *ev_type, struct faultd_event *ev);
+
 #endif /* FAULTD_EVENT_H */
index 7d41cec5603197786d0b632033d3bac8ad4cb2f4..c2e03890f41df0ca81abac4380aa0d82f4bf5699 100644 (file)
@@ -238,3 +238,49 @@ void systemd_service_serialize(struct systemd_service *s, bson* out)
                bson_append_string(out, SYSD_SERVICE_RECOVERY_UNIT, s->recovery_unit);
        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;
+       bool dbus_path = false;
+
+       memset(s, 0, sizeof(*s));
+       BSON_ITERATOR_INIT(&it, in);
+
+       while ((bt = bson_iterator_next(&it)) != BSON_EOO) {
+               if ((bt == BSON_STRING) &&
+                       (strcmp(SYSD_SERVICE_DBUS_PATH, bson_iterator_key(&it)) == 0)) {
+                       s->dbus_path = strdup(bson_iterator_string(&it));
+                       if (s->dbus_path == NULL) {
+                               ret = -errno;
+                               goto cleanup;
+                       }
+                       dbus_path = true;
+               } else if ((bt == BSON_STRING) &&
+                                  (strcmp(SYSD_SERVICE_SERVICE_TYPE, bson_iterator_key(&it)) == 0)) {
+                       s->service_type = strdup(bson_iterator_string(&it));
+                       if (s->service_type == NULL) {
+                               ret = -errno;
+                               goto cleanup;
+                       }
+               } else if ((bt == BSON_STRING) &&
+                                  (strcmp(SYSD_SERVICE_RECOVERY_UNIT, bson_iterator_key(&it)) == 0)) {
+                       s->recovery_unit = strdup(bson_iterator_string(&it));
+                       if (s->recovery_unit == NULL) {
+                               ret = -errno;
+                               goto cleanup;
+                       }
+               }
+       }
+
+       if (dbus_path)
+               ret = 0;
+finish:
+       return ret;
+
+cleanup:
+       systemd_service_cleanup(s);
+       return ret;
+}
index b9282dfce7cfcfc32944f0bb6c82a196b694a721..c5563a8e743e7da5aee1dd304a3f63565c42e97e 100644 (file)
@@ -44,6 +44,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..929337923b349ca377ae20a8fccd5a85815256b3 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,59 @@ 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) {
+               systemd_service_cleanup(&sf_ev_data.service);
+               goto finish;
+       }
+
+       ret = faultd_event_deserialize_internal(data, type, *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 +143,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..161569105223a030d02e51e8dda4c1ffcd3dd8b4 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <ejdb/bson.h>
+#include <errno.h>
+#include <string.h>
 #include <time.h>
 
 #include "common.h"
@@ -26,6 +28,37 @@ GENERATE_BSON_APPEND_STRUCT(timespec,
                                                        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 = false;
+       bool nsec = false;
+
+       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)
 {
        int ret;
index 0fbcb51a801fb0962d6f720c73acc49c343cf193..f182d1bdcef6079a1909000bca7c66a847c92b85 100644 (file)
@@ -77,6 +77,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 */)