return database_adapter->id_key;
}
+
+int database_get_event(faultd_oid_t *oid, struct faultd_event **ev)
+{
+ if (!database_adapter)
+ return -ENOSYS;
+
+ return database_adapter->get_event(oid, ev);
+}
#include "common.h"
#include "module.h"
+#include "event.h"
#define FAULTD_LAST_BOOT_OID "org.tizen.faultd.last_boot_oid"
int (*get_well_known_oid)(const char *name, faultd_oid_t *oid);
bool (*is_oid_valid)(faultd_oid_t *oid);
+
+ int (*get_event)(faultd_oid_t *oid, struct faultd_event **ev);
};
#define to_database_adapter(MOD) \
int database_get_well_known_oid(const char *name, faultd_oid_t *oid);
bool database_is_oid_valid(faultd_oid_t *oid);
const char *database_get_id_key(void);
+int database_get_event(faultd_oid_t *oid, struct faultd_event **ev);
#endif /* _DATABASE_H_ */
#include "log.h"
#include "module.h"
+#include "system_booted_event.h"
+
+static struct system_booted_event *boot_event = NULL;
+
+void set_boot_event(struct system_booted_event *sb_ev)
+{
+ boot_event = sb_ev;
+ faultd_event_ref(&boot_event->event);
+}
+
+struct system_booted_event *get_boot_event(void)
+{
+ if (boot_event)
+ faultd_event_ref(&boot_event->event);
+ return boot_event;
+}
+
struct event_factory {
struct faultd_module module;
struct list_head types;
{
struct event_factory *efactory = to_event_factory(module);
+ if (boot_event != NULL)
+ faultd_event_unref(&boot_event->event);
+
assert(list_empty(&efactory->types));
}
{
struct faultd_event *ev = container_of(uref, struct faultd_event, uref);
+ if (ev->boot_event)
+ faultd_event_unref(&ev->boot_event->event);
+
if (ev->ops.release)
ev->ops.release(ev);
}
if (ret)
return ret;
- ret = sd_id128_get_boot(&ev->boot_id);
- if (ret < 0)
- return ret;
+ ev->boot_event = get_boot_event();
ev->type = ev_type;
ev->ops = ev_type->default_ops;
void faultd_event_serialize_internal(struct faultd_event *ev, struct faultd_object *out)
{
/* FIXME: check return values of faultd_object_append_XXX */
- faultd_object_append_uuid(out, EV_BOOT_ID, &ev->boot_id);
+ if (ev->boot_event != NULL)
+ faultd_object_append_oid(out, EV_BOOT_EVENT, &ev->boot_event->event.oid);
/* FIXME: serialise event_type structure (?) */
faultd_object_append_string(out, EV_TYPE_NAME, ev->type->name);
faultd_object_append_timespec(out, EV_TIMESTAMP, &ev->timestamp);
}
-int faultd_event_deserialize_internal(const struct faultd_object* in, struct faultd_event_type *ev_type, struct faultd_event *ev)
+int faultd_event_deserialize_internal(const struct faultd_object* in,
+ struct faultd_event_type *ev_type,
+ struct faultd_event *ev)
{
struct faultd_object *obj;
+ struct system_booted_event *current_boot_event = get_boot_event();
+ struct faultd_event *other_boot_event = NULL;
+ int ret = 0;
ev->type = ev_type;
ev->ops = ev_type->default_ops;
+ ev->boot_event = NULL;
+
+ list_for_each_entry(obj, &in->val.children, node)
+ if (obj->type == TYPE_OID && strcmp(EV_BOOT_EVENT, obj->key) == 0) {
+ if (current_boot_event &&
+ faultd_oid_equal(&obj->val.oid, ¤t_boot_event->event.oid)) {
+
+ /* event created in the current faultd instance */
+ ev->boot_event = current_boot_event;
+ } else {
+
+ /* retrieve event's boot_event from database */
+ ret = database_get_event(&obj->val.oid, &other_boot_event);
+ if (ret == 0)
+ ev->boot_event = to_system_booted_event(other_boot_event);
+ else
+ goto cleanup;
+ }
+ } else if (obj->type == TYPE_TIMESPEC && strcmp(EV_TIMESTAMP, obj->key) == 0) {
+ memcpy(&ev->timestamp, &obj->val.ts, sizeof(ev->timestamp));
+ }
- list_for_each_entry(obj, &in->val.children, node) {
- if (obj->type == TYPE_UUID && strcmp(EV_BOOT_ID, obj->key) == 0)
- memcpy(&ev->boot_id, &obj->val.uuid, sizeof(ev->boot_id));
- else if (obj->type == TYPE_TIMESPEC && strcmp(EV_TIMESTAMP, obj->key) == 0)
- memcpy(&ev->timestamp, &obj->val.ts, sizeof(ev->timestamp));
- }
+cleanup:
+ if (current_boot_event && ev->boot_event != current_boot_event)
+ faultd_event_unref(¤t_boot_event->event);
- return 0;
+ return ret;
}
#include "notify_queue.h"
#include "module.h"
-#define EV_BOOT_ID "bid"
+#define EV_BOOT_EVENT "bev"
#define EV_TIMESTAMP "ts"
#define EV_TYPE_NAME "tn"
struct faultd_event {
struct timespec timestamp;
- sd_id128_t boot_id;
+ struct system_booted_event *boot_event;
/* TODO: add here some id field */
int faultd_event_deserialize_internal(const struct faultd_object *in, struct faultd_event_type *ev_type, struct faultd_event *ev);
+void set_boot_event(struct system_booted_event *sb_ev);
+struct system_booted_event *get_boot_event(void);
+
#endif /* FAULTD_EVENT_H */
return strncmp(oid->nop, NOP_DEFAULT_OID, OID_NOP_SIZE) == 0;
}
+static int nop_get_event(faultd_oid_t *oid, struct faultd_event **ev)
+{
+ return -ENOENT;
+}
+
static struct nop_adapter nop_adapter = {
.database_adapter = {
.module = {
.new_oid = nop_new_oid,
.get_well_known_oid = nop_get_well_known_oid,
.is_oid_valid = nop_is_oid_valid,
+ .get_event = nop_get_event,
}
};
oid->bson.ints[2] != 0;
}
+static int ejdb_get_event(faultd_oid_t *oid, struct faultd_event **ev)
+{
+ struct faultd_object *obj;
+ int ret;
+
+ ret = faultd_object_new(&obj);
+ if (ret)
+ return ret;
+
+ ret = database_get_by_oid(oid, obj);
+ if (ret)
+ goto cleanup;
+
+ ret = faultd_event_create(BSON_EVENT_ID, obj, ev);
+ if (ret)
+ goto cleanup;
+
+cleanup:
+ faultd_object_unref(obj);
+ return ret;
+}
+
static struct ejdb_adapter ejdb_adapter = {
.database_adapter = {
.module = {
.new_oid = ejdb_new_oid,
.get_well_known_oid = ejdb_get_well_known_oid,
.is_oid_valid = ejdb_is_oid_valid,
+ .get_event = ejdb_get_event,
}
};
#include "service_failed_event.h"
#include "decision_made_event.h"
+#include "system_booted_event.h"
#include "action.h"
#include "event_processor.h"
#include "log.h"
struct faultd_event,
nq_node);
struct service_failed_event *sf_ev = to_service_failed_event(ev);
+ struct system_booted_event *boot_event;
struct faultd_event *new_ev;
struct dm_event_data ev_data = {
.reason = ev,
};
int ret;
struct faultd_object *query, *service_obj;
- sd_id128_t boot_id;
uint32_t nr;
- ret = sd_id128_get_boot(&boot_id);
- if (ret < 0)
- return ret;
+ boot_event = get_boot_event();
+ if (!boot_event)
+ return -ENOTSUP;
ret = faultd_object_new(&query);
- if (ret < 0)
+ if (ret < 0) {
+ faultd_event_unref(&boot_event->event);
return ret;
+ }
- faultd_object_append_uuid(query, EV_BOOT_ID, &boot_id);
+ faultd_object_append_oid(query, EV_BOOT_EVENT, &boot_event->event.oid);
+ faultd_event_unref(&boot_event->event);
faultd_object_append_string(query, EV_TYPE_NAME, ev->type->name);
ret = faultd_object_new(&service_obj);
return -ENOMEM;
memset(sb_ev, 0, sizeof(*sb_ev));
+ sb_ev->boot_id = sb_ev_data->boot_id;
+ sb_ev->prev_boot_event = sb_ev_data->prev_boot_event;
+
ret = faultd_event_init_internal(type, &sb_ev->event);
if (ret)
goto free_sb_ev;
- sb_ev->prev_boot_id = sb_ev_data->prev_boot_id;
*ev = &sb_ev->event;
return 0;
return ret;
}
+static int deserialize_sb_event(struct faultd_event_type *type,
+ struct faultd_object *data, struct faultd_event **ev)
+{
+ int ret = -EINVAL;
+ struct sb_event_data sb_ev_data;
+ struct faultd_object *obj;
+
+ memset(&sb_ev_data, 0, sizeof(sb_ev_data));
+
+ list_for_each_entry(obj, &data->val.children, node) {
+ if ((obj->type == TYPE_UUID) &&
+ (strcmp(SB_EV_BID, obj->key) == 0)) {
+
+ sb_ev_data.boot_id = obj->val.uuid;
+
+ } else if ((obj->type == TYPE_OID) &&
+ (strcmp(SB_EV_PREV_BEV, obj->key) == 0)) {
+
+ sb_ev_data.prev_boot_event = obj->val.oid;
+
+ }
+ }
+
+ ret = allocate_sb_event(type, &sb_ev_data, ev);
+ if (ret < 0)
+ goto finish;
+
+ ret = faultd_event_deserialize_internal(data, type, *ev);
+ if (ret < 0) {
+ struct system_booted_event *sb_ev =
+ to_system_booted_event(*ev);
+ free(sb_ev);
+ goto finish;
+ }
+
+ ret = 0;
+finish:
+ return ret;
+}
+
static void sb_event_release(struct faultd_event *ev)
{
struct system_booted_event *sb_ev=
to_system_booted_event(ev);
char *str;
int ret;
+ char *oidbuf = faultd_oid_to_string_hex(&sb_ev->prev_boot_event);
ret = asprintf(&str, "System booted event:"
" Time: %lld.%.9ld"
- " Previous boot ID: %s"
+ " Previous boot EVENT: %s"
" Current boot ID: %s",
(long long)ev->timestamp.tv_sec,
ev->timestamp.tv_nsec,
- SD_ID128_CONST_STR(sb_ev->prev_boot_id),
- SD_ID128_CONST_STR(ev->boot_id)
+ oidbuf,
+ SD_ID128_CONST_STR(sb_ev->boot_id)
);
+ if (oidbuf)
+ free(oidbuf);
return ret > 0 ? str : NULL;
}
to_system_booted_event(ev);
faultd_event_serialize_internal(ev, out);
- faultd_object_append_uuid(out, "prev_boot_id", &sb_ev->prev_boot_id);
+ faultd_object_append_uuid(out, SB_EV_BID, &sb_ev->boot_id);
+ faultd_object_append_oid(out, SB_EV_PREV_BEV, &sb_ev->prev_boot_event);
}
TEST_ENTRY_POINT(sb_event_serialize);
.to_string = sb_event_to_string,
},
.allocate_event = allocate_sb_event,
+ .deserialize_event = deserialize_sb_event,
.node = LIST_HEAD_INIT(system_booted_event_type.node),
};
#include "event.h"
#include "common.h"
#include "service.h"
+#include "database.h"
#define SYSTEM_BOOTED_EVENT_ID "system_booted"
+#define SB_EV_BID "bid"
+#define SB_EV_PREV_BEV "p_bev"
struct system_booted_event {
struct faultd_event event;
- sd_id128_t prev_boot_id;
+ sd_id128_t boot_id;
+ faultd_oid_t prev_boot_event;
};
struct sb_event_data {
- sd_id128_t prev_boot_id;
+ sd_id128_t boot_id;
+ faultd_oid_t prev_boot_event;
};
#define to_system_booted_event(EVENT) \
struct faultd_module module;
};
-static int retrieve_last_boot_id(sd_id128_t *boot_id)
+static int retrieve_last_boot_event(faultd_oid_t *boot_event)
{
- faultd_oid_t oid;
- int ret;
+ faultd_oid_t root_oid;
struct faultd_object *root;
+ int ret;
- ret = database_get_well_known_oid(FAULTD_LAST_BOOT_OID, &oid);
- if (ret < 0) {
+ faultd_object_new(&root);
+ ret = database_get_well_known_oid(FAULTD_LAST_BOOT_OID, &root_oid);
+ if (ret) {
log_error("Could not get last boot id oid");
- return ret;
+ goto out;
}
- faultd_object_new(&root);
- ret = database_get_by_oid(&oid, root);
- if (ret < 0) {
+ ret = database_get_by_oid(&root_oid, root);
+ if (ret) {
log_debug("No boot event found");
- *boot_id = SD_ID128_NULL;
- ret = 0;
+ ret = -ENOENT;
goto out;
}
- ret = faultd_object_get_uuid(root, "boot_id", boot_id);
- if (ret < 0) {
- log_error("could not get boot_id object");
+ ret = faultd_object_get_oid(root, "boot_event", boot_event);
+ if (ret) {
+ log_error("Could not get last boot event");
goto out;
}
return ret;
}
-static void store_boot_id(sd_id128_t *boot_id)
+static int retrieve_boot_id(faultd_oid_t *boot_event, sd_id128_t *boot_id)
+{
+ struct faultd_object *obj;
+ int ret;
+
+ faultd_object_new(&obj);
+ ret = database_get_by_oid(boot_event, obj);
+ if (ret) {
+ log_error("No boot event found");
+ goto out;
+ }
+
+ ret = faultd_object_get_uuid(obj, SB_EV_BID, boot_id);
+ if (ret) {
+ log_error("Could not get boot id");
+ goto out;
+ }
+
+out:
+ faultd_object_unref(obj);
+ return ret;
+}
+
+static int store_boot_event(faultd_oid_t *boot_event)
{
faultd_oid_t oid;
struct faultd_object *obj;
ret = database_get_well_known_oid(FAULTD_LAST_BOOT_OID, &oid);
if (ret < 0) {
log_error_errno(ret, "Could not get oid of %s: %m", FAULTD_LAST_BOOT_OID);
- return;
+ return ret;
}
faultd_object_new(&obj);
faultd_object_append_oid(obj, JDBIDKEYNAME, &oid);
- faultd_object_append_uuid(obj, "boot_id", boot_id);
+ faultd_object_append_oid(obj, "boot_event", boot_event);
ret = database_store(obj, &oid);
- if (ret < 0)
- log_error_errno(ret, "Could not store object in database");
+
faultd_object_unref(obj);
+ return ret;
+}
+
+static int generate_event(const char *type, void *data, struct faultd_event **ev)
+{
+ int ret;
+
+ ret = faultd_event_create(type, data, ev);
+ if (ret) {
+ log_error_errno(ret, "Unable to allocate an event");
+ return ret;
+ }
+
+ faultd_event_ref(*ev);
+
+ ret = event_processor_report_event(*ev);
+ if (ret) {
+ log_error_errno(ret, "Unable to report event");
+ faultd_event_unref(*ev);
+ faultd_event_unref(*ev);
+ }
+
+ return ret;
}
static int startup_listener_init(struct faultd_module *module,
struct faultd_config *cfg, sd_event *event)
{
- int rc;
- struct faultd_event *started_ev, *booted_ev;
+ struct faultd_event *started_ev = NULL;
+ struct faultd_event *booted_ev = NULL;
struct sb_event_data sb_ev_data;
- sd_id128_t boot_id;
+ sd_id128_t boot_id, last_boot_id;
+ faultd_oid_t last_boot_event_oid;
+ int ret;
- rc = faultd_event_create(FAULTD_STARTED_EVENT_ID, NULL, &started_ev);
- if (rc) {
- log_error_errno(rc, "Unable to allocate an event");
- return rc;
+ ret = sd_id128_get_boot(&boot_id);
+ if (ret)
+ goto error;
+
+ ret = retrieve_last_boot_event(&last_boot_event_oid);
+ switch (ret) {
+ case -ENOENT:
+ /* database is empty */
+
+ sb_ev_data.boot_id = boot_id;
+ memset(&sb_ev_data.prev_boot_event, 0, sizeof(sb_ev_data.prev_boot_event));
+ break;
+
+ case 0:
+ ret = retrieve_boot_id(&last_boot_event_oid, &last_boot_id);
+ if (ret)
+ goto error;
+
+ if (!sd_id128_equal(boot_id, last_boot_id)) {
+ /* first start in current boot */
+
+ sb_ev_data.boot_id = boot_id;
+ sb_ev_data.prev_boot_event = last_boot_event_oid;
+ } else {
+ /* next start in current boot */
+
+ ret = database_get_event(&last_boot_event_oid, &booted_ev);
+ if (ret) {
+ log_error_errno(ret, "Unable to create system booted event from database");
+ goto error;
+ }
+
+ booted_ev->oid = last_boot_event_oid;
+ goto finish;
+ }
+ break;
+
+ default:
+ goto error;
+ break;
}
- rc = event_processor_report_event(started_ev);
- if (rc) {
- log_error_errno(rc, "Unable to report event");
- faultd_event_unref(started_ev);
- return rc;
- }
+ ret = generate_event(SYSTEM_BOOTED_EVENT_ID, &sb_ev_data, &booted_ev);
+ if (ret)
+ goto error;
- rc = retrieve_last_boot_id(&boot_id);
- if (rc < 0) {
- log_error_errno(rc, "Could not retrieve boot id");
- return rc;
+ ret = store_boot_event(&booted_ev->oid);
+ if (ret) {
+ log_error_errno(ret, "Could not store object in database");
+ goto booted_ev_unref;
}
- if (sd_id128_equal(started_ev->boot_id, boot_id))
- return 0;
+finish:
+ set_boot_event(to_system_booted_event(booted_ev));
+ faultd_event_unref(booted_ev);
- store_boot_id(&started_ev->boot_id);
- sb_ev_data.prev_boot_id = boot_id;
+ ret = generate_event(FAULTD_STARTED_EVENT_ID, NULL, &started_ev);
+ if (ret)
+ goto booted_ev_unref;
- rc = faultd_event_create(SYSTEM_BOOTED_EVENT_ID, &sb_ev_data, &booted_ev);
- if (rc) {
- log_error_errno(rc, "Unable to allocate an event");
- return rc;
- }
+ faultd_event_unref(started_ev);
+ return ret;
- rc = event_processor_report_event(booted_ev);
- if (rc) {
- log_error_errno(rc, "Unable to report event");
- faultd_event_unref(booted_ev);
- return rc;
- }
+booted_ev_unref:
+ faultd_event_unref(booted_ev);
- return 0;
+error:
+ return ret;
}
static void startup_listener_cleanup(struct faultd_module *module)
{
return sd_id128_from_string(s, &oid->uuid);
}
+
+int faultd_oid_equal(const faultd_oid_t *oid1, const faultd_oid_t *oid2)
+{
+ if (!oid1 || !oid2)
+ return 0;
+
+ return !memcmp(oid1, oid2, sizeof *oid1);
+}
+
+char *faultd_oid_to_string_hex(const faultd_oid_t *oid)
+{
+ unsigned char *bytes = (unsigned char*)oid;
+ unsigned int size = sizeof(*oid);
+ char *buf;
+ int ret;
+
+ buf = calloc(sizeof(*oid) * 2 + 1, sizeof(char));
+ if (!buf)
+ return NULL;
+
+ for (unsigned int i = 0; i < size; i++) {
+ ret = snprintf(&buf[i * 2], 3, "%02x", bytes[i]);
+ if (ret < 0) {
+ free(buf);
+ return NULL;
+ }
+ }
+
+ return buf;
+}
int faultd_oid_from_string(faultd_oid_t *oid, const char *s);
+int faultd_oid_equal(const faultd_oid_t *oid1, const faultd_oid_t *oid2);
+
+char *faultd_oid_to_string_hex(const faultd_oid_t *oid);
+
#endif /* FAULTD_COMMON_H */
#include <systemd/sd-id128.h>
#include <systemd/sd-bus.h>
+#include "system_booted_event.h"
+
#define STR_SIZE 20
#define GET_FAULTD_OBJECT_VAL(TYPE, VAR, OBJ, KEY, TYPE2) \
}
#define S_ELEMENT_EVENT(EV) \
- S_ELEMENT(EV_BOOT_ID, TYPE_UUID, &EV.boot_id), \
+ S_ELEMENT(EV_BOOT_EVENT, TYPE_OID, &EV.boot_event->event.oid), \
S_ELEMENT(EV_TYPE_NAME, TYPE_STRING, &EV.type->name), \
S_ELEMENT(EV_TIMESTAMP, TYPE_TIMESPEC, &EV.timestamp)
generate_attrs_func_t generate_attrs,
serialize_func_t serialize_func);
+static inline void allocate_boot_event()
+{
+ struct system_booted_event *sb_ev;
+
+ sb_ev = malloc(sizeof(struct system_booted_event));
+
+ if (sb_ev) {
+ sb_ev->event.oid = generate_oid();
+ sb_ev->event.uref.refcnt = 1;
+ set_boot_event(sb_ev);
+ } else {
+ printf("Unable to allocate boot event");
+ fail();
+ }
+}
+
+static inline void free_boot_event()
+{
+ struct system_booted_event *sb_ev = get_boot_event();
+ free(sb_ev);
+}
+
static inline void fill_event(struct faultd_event *ev)
{
- ev->boot_id = generate_uuid();
+ allocate_boot_event();
+ ev->boot_event = get_boot_event();
ev->type = calloc(1, sizeof(*(ev->type)));
assert_non_null(ev->type);
ev->type->name = generate_string(STR_SIZE);
static inline void free_event(struct faultd_event *ev)
{
+ free_boot_event();
free(ev->type->name);
free(ev->type);
}
assert_non_null(sb_ev);
fill_event(&sb_ev->event);
- sb_ev->prev_boot_id = generate_uuid();
+ sb_ev->boot_id = generate_uuid();
+ sb_ev->prev_boot_event = generate_oid();
return &sb_ev->event;
}
struct system_booted_event *sb_ev = to_system_booted_event(td->ev);
struct serialized_element serialized_attrs[] = {
S_ELEMENT_EVENT(sb_ev->event),
- S_ELEMENT("prev_boot_id", TYPE_UUID, &sb_ev->prev_boot_id)
+ S_ELEMENT(SB_EV_BID, TYPE_UUID, &sb_ev->boot_id),
+ S_ELEMENT(SB_EV_PREV_BEV, TYPE_OID, &sb_ev->prev_boot_event)
};
td->test_data = serialized_elems_dup(serialized_attrs,