mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Added a mechanism to recover blacklisted ubus methods
This commit is contained in:
parent
ae1c44524d
commit
aa74995f9b
2 changed files with 107 additions and 18 deletions
|
|
@ -142,6 +142,11 @@ static void schedule_blacklisted_service_recovery(struct ubus_context *ubus_ctx)
|
||||||
uloop_timeout_set(&blacklisted_recovery_timer, next_check_time);
|
uloop_timeout_set(&blacklisted_recovery_timer, next_check_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stop_blacklisted_service_recovery(void)
|
||||||
|
{
|
||||||
|
uloop_timeout_cancel(&blacklisted_recovery_timer);
|
||||||
|
}
|
||||||
|
|
||||||
static void bbfdm_ubus_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev __attribute__((unused)),
|
static void bbfdm_ubus_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev __attribute__((unused)),
|
||||||
const char *type, struct blob_attr *msg)
|
const char *type, struct blob_attr *msg)
|
||||||
{
|
{
|
||||||
|
|
@ -481,6 +486,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
end:
|
end:
|
||||||
BBFDM_DEBUG("BBFDMD exits");
|
BBFDM_DEBUG("BBFDMD exits");
|
||||||
|
stop_blacklisted_service_recovery();
|
||||||
ubus_unregister_event_handler(&g_ubus_ctx, &add_event);
|
ubus_unregister_event_handler(&g_ubus_ctx, &add_event);
|
||||||
unregister_services();
|
unregister_services();
|
||||||
uloop_done();
|
uloop_done();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,11 @@ static LIST_HEAD(dm_ubus_cache);
|
||||||
|
|
||||||
struct dm_ubus_cache_entry {
|
struct dm_ubus_cache_entry {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
char *obj;
|
||||||
|
char *method;
|
||||||
|
struct blob_attr *attr;
|
||||||
json_object *data;
|
json_object *data;
|
||||||
|
int timeout;
|
||||||
unsigned hash;
|
unsigned hash;
|
||||||
unsigned int consecutive_timeouts; // Tracks successive timeouts
|
unsigned int consecutive_timeouts; // Tracks successive timeouts
|
||||||
bool is_blacklisted; // Marks if the ubus is blacklisted
|
bool is_blacklisted; // Marks if the ubus is blacklisted
|
||||||
|
|
@ -41,7 +45,7 @@ struct ubus_struct {
|
||||||
bool ubus_method_exists;
|
bool ubus_method_exists;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ubus_context *ubus_ctx = NULL;
|
static struct ubus_context *g_dm_ubus_ctx = NULL;
|
||||||
|
|
||||||
static const char *dm_ubus_str_error[__UBUS_STATUS_LAST] = {
|
static const char *dm_ubus_str_error[__UBUS_STATUS_LAST] = {
|
||||||
[UBUS_STATUS_OK] = "Success",
|
[UBUS_STATUS_OK] = "Success",
|
||||||
|
|
@ -106,7 +110,7 @@ static struct dm_ubus_cache_entry *dm_ubus_cache_lookup(unsigned hash)
|
||||||
return entry_match;
|
return entry_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dm_ubus_cache_entry *dm_ubus_cache_entry_new(unsigned hash)
|
static struct dm_ubus_cache_entry *dm_ubus_cache_entry_new(unsigned hash, const char *obj, const char *method, int timeout, struct blob_attr *attr)
|
||||||
{
|
{
|
||||||
struct dm_ubus_cache_entry *entry = NULL;
|
struct dm_ubus_cache_entry *entry = NULL;
|
||||||
|
|
||||||
|
|
@ -119,9 +123,25 @@ static struct dm_ubus_cache_entry *dm_ubus_cache_entry_new(unsigned hash)
|
||||||
list_add_tail(&entry->list, &dm_ubus_cache);
|
list_add_tail(&entry->list, &dm_ubus_cache);
|
||||||
|
|
||||||
entry->hash = hash;
|
entry->hash = hash;
|
||||||
|
entry->obj = strdup(obj);
|
||||||
|
entry->method = strdup(method);
|
||||||
|
entry->timeout = timeout;
|
||||||
entry->consecutive_timeouts = 0;
|
entry->consecutive_timeouts = 0;
|
||||||
entry->is_blacklisted = false;
|
entry->is_blacklisted = false;
|
||||||
|
|
||||||
|
size_t blob_data_len = attr ? blob_raw_len(attr) : 0;
|
||||||
|
|
||||||
|
if (blob_data_len) {
|
||||||
|
entry->attr = (struct blob_attr *)calloc(1, blob_data_len);
|
||||||
|
if (entry->attr) {
|
||||||
|
memcpy(entry->attr, attr, blob_data_len);
|
||||||
|
} else {
|
||||||
|
BBF_ERR("Failed to allocate memory");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
entry->attr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +179,7 @@ static void dm_ubus_data_handler(struct ubus_request *req, int type, struct blob
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_ubus_call_sync(const char *obj, const char *method, int timeout, struct blob_attr *attr, json_object **req_res)
|
static int dm_ubus_call_sync(struct ubus_context *ubus_ctx, const char *obj, const char *method, int timeout, struct blob_attr *attr, json_object **req_res)
|
||||||
{
|
{
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
|
||||||
|
|
@ -212,7 +232,7 @@ static void dm_ubus_data_handler_entry(struct ubus_request *req, int type, struc
|
||||||
free((char *)str);
|
free((char *)str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __dm_ubus_call_sync_entry(struct dm_ubus_cache_entry *entry, const char *obj, const char *method, int timeout, struct blob_attr *attr)
|
static int __dm_ubus_call_sync_entry(struct ubus_context *ubus_ctx, struct dm_ubus_cache_entry *entry, const char *obj, const char *method, int timeout, struct blob_attr *attr)
|
||||||
{
|
{
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
|
||||||
|
|
@ -260,7 +280,7 @@ static int __dm_ubus_call_sync_entry(struct dm_ubus_cache_entry *entry, const ch
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dm_ubus_call_sync_entry(const char *obj, const char *method, int timeout, struct blob_attr *attr, json_object **req_res)
|
static int dm_ubus_call_sync_entry(struct ubus_context *ubus_ctx, const char *obj, const char *method, int timeout, struct blob_attr *attr, json_object **req_res)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
|
@ -285,18 +305,18 @@ static int dm_ubus_call_sync_entry(const char *obj, const char *method, int time
|
||||||
|
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (entry->is_executed == false) {
|
if (entry->is_executed == false) {
|
||||||
err = __dm_ubus_call_sync_entry(entry, obj, method, timeout, attr);
|
err = __dm_ubus_call_sync_entry(ubus_ctx, entry, obj, method, timeout, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req_res) *req_res = entry->data;
|
if (req_res) *req_res = entry->data;
|
||||||
} else {
|
} else {
|
||||||
struct dm_ubus_cache_entry *new_entry = dm_ubus_cache_entry_new(hash);
|
struct dm_ubus_cache_entry *new_entry = dm_ubus_cache_entry_new(hash, obj, method, timeout, attr);
|
||||||
if (new_entry == NULL) {
|
if (new_entry == NULL) {
|
||||||
if (req_res) *req_res = NULL;
|
if (req_res) *req_res = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = __dm_ubus_call_sync_entry(new_entry, obj, method, timeout, attr);
|
err = __dm_ubus_call_sync_entry(ubus_ctx, new_entry, obj, method, timeout, attr);
|
||||||
if (req_res) *req_res = new_entry->data;
|
if (req_res) *req_res = new_entry->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,9 +349,9 @@ static int __dmubus_call(const char *obj, const char *method, int timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (save_data)
|
if (save_data)
|
||||||
rc = dm_ubus_call_sync_entry(obj, method, timeout, bb.head, req_res);
|
rc = dm_ubus_call_sync_entry(g_dm_ubus_ctx, obj, method, timeout, bb.head, req_res);
|
||||||
else
|
else
|
||||||
rc = dm_ubus_call_sync(obj, method, timeout, bb.head, req_res);
|
rc = dm_ubus_call_sync(g_dm_ubus_ctx, obj, method, timeout, bb.head, req_res);
|
||||||
|
|
||||||
blob_buf_free(&bb);
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
|
@ -377,9 +397,9 @@ static int __dmubus_call_blob(const char *obj, const char *method, int timeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (save_data)
|
if (save_data)
|
||||||
rc = dm_ubus_call_sync_entry(obj, method, timeout, bb.head, resp);
|
rc = dm_ubus_call_sync_entry(g_dm_ubus_ctx, obj, method, timeout, bb.head, resp);
|
||||||
else
|
else
|
||||||
rc = dm_ubus_call_sync(obj, method, timeout, bb.head, resp);
|
rc = dm_ubus_call_sync(g_dm_ubus_ctx, obj, method, timeout, bb.head, resp);
|
||||||
|
|
||||||
blob_buf_free(&bb);
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
|
@ -403,12 +423,12 @@ int dmubus_call_blob_set(const char *obj, const char *method, json_object *value
|
||||||
|
|
||||||
int dmubus_call_blob_msg_timeout(const char *obj, const char *method, struct blob_buf *data, int timeout)
|
int dmubus_call_blob_msg_timeout(const char *obj, const char *method, struct blob_buf *data, int timeout)
|
||||||
{
|
{
|
||||||
return dm_ubus_call_sync(obj, method, timeout, data->head, NULL);
|
return dm_ubus_call_sync(g_dm_ubus_ctx, obj, method, timeout, data->head, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int dmubus_call_blob_msg_set(const char *obj, const char *method, struct blob_buf *data)
|
int dmubus_call_blob_msg_set(const char *obj, const char *method, struct blob_buf *data)
|
||||||
{
|
{
|
||||||
return dm_ubus_call_sync(obj, method, UBUS_TIMEOUT, data->head, NULL);
|
return dm_ubus_call_sync(g_dm_ubus_ctx, obj, method, UBUS_TIMEOUT, data->head, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _bbfdm_task_callback(struct uloop_timeout *t)
|
static void _bbfdm_task_callback(struct uloop_timeout *t)
|
||||||
|
|
@ -611,7 +631,7 @@ bool dmubus_object_method_exists(const char *object)
|
||||||
if (object == NULL)
|
if (object == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ubus_ctx == NULL) {
|
if (g_dm_ubus_ctx == NULL) {
|
||||||
BBF_ERR("UBUS context is null");
|
BBF_ERR("UBUS context is null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -625,7 +645,7 @@ bool dmubus_object_method_exists(const char *object)
|
||||||
*delimiter = '\0';
|
*delimiter = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ubus_lookup(ubus_ctx, ubus_object, receive_list_result, &ubus_s))
|
if (ubus_lookup(g_dm_ubus_ctx, ubus_object, receive_list_result, &ubus_s))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ubus_s.ubus_method_name && !ubus_s.ubus_method_exists)
|
if (ubus_s.ubus_method_name && !ubus_s.ubus_method_exists)
|
||||||
|
|
@ -634,9 +654,65 @@ bool dmubus_object_method_exists(const char *object)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dmubus_schedule_blacklisted_ubus_recovery(void);
|
||||||
|
|
||||||
|
static void blacklisted_ubus_recovery_timer_cb(struct uloop_timeout *timeout __attribute__((unused)))
|
||||||
|
{
|
||||||
|
dmubus_schedule_blacklisted_ubus_recovery();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct uloop_timeout blacklisted_ubus_recovery_timer = {
|
||||||
|
.cb = blacklisted_ubus_recovery_timer_cb
|
||||||
|
};
|
||||||
|
|
||||||
|
static void verify_ubus_method(struct dm_ubus_cache_entry *entry)
|
||||||
|
{
|
||||||
|
struct ubus_context *ubus_ctx = ubus_connect(NULL);
|
||||||
|
|
||||||
|
int err = dm_ubus_call_sync(ubus_ctx, entry->obj, entry->method, entry->timeout, entry->attr, NULL);
|
||||||
|
|
||||||
|
if (err == 0) {
|
||||||
|
BBF_INFO("Recovered ubus obj |%s| method |%s|", entry->obj, entry->method);
|
||||||
|
|
||||||
|
entry->consecutive_timeouts = 0;
|
||||||
|
entry->is_blacklisted = false;
|
||||||
|
} else {
|
||||||
|
BBF_INFO("ubus obj |%s| method |%s| still unreachable", entry->obj, entry->method);
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_free(ubus_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dmubus_schedule_blacklisted_ubus_recovery(void)
|
||||||
|
{
|
||||||
|
int next_check_time = 60000; // 1 min
|
||||||
|
|
||||||
|
if (g_dm_ubus_ctx != NULL) {
|
||||||
|
BBF_INFO("A method is currently running. Rescheduling blacklisted ubus recovery in %d msecs", next_check_time);
|
||||||
|
uloop_timeout_set(&blacklisted_ubus_recovery_timer, next_check_time);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dm_ubus_cache_entry *entry = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(entry, &dm_ubus_cache, list) {
|
||||||
|
if (entry->is_blacklisted) {
|
||||||
|
verify_ubus_method(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BBF_INFO("Next blacklisted ubus recovery scheduled in %d msecs", next_check_time);
|
||||||
|
uloop_timeout_set(&blacklisted_ubus_recovery_timer, next_check_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dmubus_stop_blacklisted_ubus_recovery(void)
|
||||||
|
{
|
||||||
|
uloop_timeout_cancel(&blacklisted_ubus_recovery_timer);
|
||||||
|
}
|
||||||
|
|
||||||
void dm_ubus_init(struct dmctx *bbf_ctx)
|
void dm_ubus_init(struct dmctx *bbf_ctx)
|
||||||
{
|
{
|
||||||
bbf_ctx->ubus_ctx = ubus_ctx = ubus_connect(NULL);
|
bbf_ctx->ubus_ctx = g_dm_ubus_ctx = ubus_connect(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_ubus_free(struct dmctx *bbf_ctx)
|
void dm_ubus_free(struct dmctx *bbf_ctx)
|
||||||
|
|
@ -645,13 +721,15 @@ void dm_ubus_free(struct dmctx *bbf_ctx)
|
||||||
|
|
||||||
if (bbf_ctx->ubus_ctx) {
|
if (bbf_ctx->ubus_ctx) {
|
||||||
ubus_free(bbf_ctx->ubus_ctx);
|
ubus_free(bbf_ctx->ubus_ctx);
|
||||||
bbf_ctx->ubus_ctx = ubus_ctx = NULL;
|
bbf_ctx->ubus_ctx = g_dm_ubus_ctx = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_ubus_cache_init(void)
|
void dm_ubus_cache_init(void)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&dm_ubus_cache);
|
INIT_LIST_HEAD(&dm_ubus_cache);
|
||||||
|
|
||||||
|
dmubus_schedule_blacklisted_ubus_recovery();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dm_ubus_cache_free(void)
|
void dm_ubus_cache_free(void)
|
||||||
|
|
@ -660,6 +738,11 @@ void dm_ubus_cache_free(void)
|
||||||
|
|
||||||
list_for_each_entry_safe(entry, tmp, &dm_ubus_cache, list) {
|
list_for_each_entry_safe(entry, tmp, &dm_ubus_cache, list) {
|
||||||
list_del(&entry->list);
|
list_del(&entry->list);
|
||||||
|
FREE(entry->obj);
|
||||||
|
FREE(entry->method);
|
||||||
|
FREE(entry->attr);
|
||||||
FREE(entry);
|
FREE(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dmubus_stop_blacklisted_ubus_recovery();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue