#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;
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;
}
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;
+}
#define EV_TIMESTAMP "ts"
#define EV_TYPE_NAME "tn"
+#define BSON_EVENT_ID "bson_event"
+
struct faultd_event;
struct faultd_event_ops {
/* 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;
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 */
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;
+}
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)
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;
*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 =
.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),
};
*/
#include <ejdb/bson.h>
+#include <errno.h>
+#include <string.h>
#include <time.h>
#include "common.h"
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)
{
}
DECLARE_BSON_APPEND_STRUCT(timespec);
+int faultd_bson_get_timespec(const bson *in, struct timespec *t);
#define BSON_EMPTY_SIZE (4 /* len */ + 1 /* \0 */)