mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
T#11633: bbfdm: Support transaction commit/abort for microservices
This commit is contained in:
parent
01c0c3769e
commit
f43885b47d
8 changed files with 138 additions and 30 deletions
|
|
@ -562,6 +562,7 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
blob_buf_init(&data.bb, 0);
|
||||
bbf_init(&data.bbf_ctx);
|
||||
|
||||
data.ctx = ctx;
|
||||
data.bbf_ctx.in_param = path;
|
||||
|
||||
fault = fill_pvlist_set(&data, path, tb[DM_SET_VALUE] ? blobmsg_get_string(tb[DM_SET_VALUE]) : NULL, tb[DM_SET_OBJ_PATH], &pv_list);
|
||||
|
|
@ -584,11 +585,13 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
WARNING("Transaction not started yet");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
goto end;
|
||||
} else {
|
||||
data.bbf_ctx.trans_id = data.trans_id;
|
||||
}
|
||||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
trans_id = transaction_start("INT_SET", 0);
|
||||
trans_id = transaction_start(&data, "INT_SET", 0);
|
||||
if (trans_id == 0) {
|
||||
WARNING("Failed to get the lock for the transaction");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
|
|
@ -600,7 +603,7 @@ int bbfdm_set_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
transaction_commit(trans_id, NULL, true);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
@ -687,6 +690,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
snprintf(path, PATH_MAX, "%s", (char *)blobmsg_data(tb[DM_ADD_PATH]));
|
||||
|
||||
data.ctx = ctx;
|
||||
data.bbf_ctx.in_param = path;
|
||||
|
||||
fill_optional_data(&data, tb[DM_ADD_OPTIONAL]);
|
||||
|
|
@ -701,11 +705,13 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
WARNING("Transaction not started yet");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
goto end;
|
||||
} else {
|
||||
data.bbf_ctx.trans_id = data.trans_id;
|
||||
}
|
||||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
trans_id = transaction_start("INT_ADD", 0);
|
||||
trans_id = transaction_start(&data, "INT_ADD", 0);
|
||||
if (trans_id == 0) {
|
||||
ERR("Failed to get the lock for the transaction");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
|
|
@ -719,7 +725,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to abort the changes
|
||||
transaction_abort(trans_id, NULL);
|
||||
transaction_abort(NULL, trans_id);
|
||||
}
|
||||
|
||||
goto end;
|
||||
|
|
@ -737,7 +743,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to abort the changes
|
||||
transaction_abort(trans_id, NULL);
|
||||
transaction_abort(NULL, trans_id);
|
||||
}
|
||||
|
||||
free_pv_list(&pv_list);
|
||||
|
|
@ -753,7 +759,7 @@ int bbfdm_add_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
transaction_commit(trans_id, NULL, true);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
@ -805,6 +811,7 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
}
|
||||
}
|
||||
|
||||
data.ctx = ctx;
|
||||
data.plist = &paths_list;
|
||||
|
||||
fill_optional_data(&data, tb[DM_DEL_OPTIONAL]);
|
||||
|
|
@ -821,11 +828,13 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
WARNING("Transaction not started yet");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
goto end;
|
||||
} else {
|
||||
data.bbf_ctx.trans_id = data.trans_id;
|
||||
}
|
||||
|
||||
if (data.trans_id == 0) {
|
||||
// Transaction-id is not defined so create an internal transaction
|
||||
trans_id = transaction_start("INT_DEL", 0);
|
||||
trans_id = transaction_start(&data, "INT_DEL", 0);
|
||||
if (trans_id == 0) {
|
||||
WARNING("Failed to get the lock for the transaction");
|
||||
fill_err_code_array(&data, USP_FAULT_INTERNAL_ERROR);
|
||||
|
|
@ -837,7 +846,7 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
|
||||
if (data.trans_id == 0) {
|
||||
// Internal transaction: need to commit the changes
|
||||
transaction_commit(trans_id, NULL, true);
|
||||
transaction_commit(NULL, trans_id, true);
|
||||
}
|
||||
|
||||
end:
|
||||
|
|
@ -901,9 +910,11 @@ static int bbfdm_transaction_handler(struct ubus_context *ctx, struct ubus_objec
|
|||
bbf_init(&data.bbf_ctx);
|
||||
blob_buf_init(&data.bb, 0);
|
||||
|
||||
data.ctx = ctx;
|
||||
|
||||
if (is_str_eq(trans_cmd, "start")) {
|
||||
cancel_periodic_timers(ctx);
|
||||
ret = transaction_start("API", max_timeout);
|
||||
ret = transaction_start(&data, "API", max_timeout);
|
||||
if (ret) {
|
||||
blobmsg_add_u8(&data.bb, "status", true);
|
||||
blobmsg_add_u32(&data.bb, "transaction_id", ret);
|
||||
|
|
@ -913,11 +924,11 @@ static int bbfdm_transaction_handler(struct ubus_context *ctx, struct ubus_objec
|
|||
}
|
||||
} else if (is_str_eq(trans_cmd, "commit")) {
|
||||
register_periodic_timers(ctx);
|
||||
ret = transaction_commit(data.trans_id, &data.bb, is_service_restart);
|
||||
ret = transaction_commit(&data, data.trans_id, is_service_restart);
|
||||
blobmsg_add_u8(&data.bb, "status", (ret == 0));
|
||||
} else if (is_str_eq(trans_cmd, "abort")) {
|
||||
register_periodic_timers(ctx);
|
||||
ret = transaction_abort(data.trans_id, &data.bb);
|
||||
ret = transaction_abort(&data, data.trans_id);
|
||||
blobmsg_add_u8(&data.bb, "status", (ret == 0));
|
||||
} else if (is_str_eq(trans_cmd, "status")) {
|
||||
transaction_status(&data.bb);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
#include "common.h"
|
||||
#include "pretty_print.h"
|
||||
|
||||
extern struct list_head head_registered_service;
|
||||
|
||||
DMOBJ *DEAMON_DM_ROOT_OBJ = NULL;
|
||||
DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2] = {0};
|
||||
DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE = NULL;
|
||||
|
|
@ -187,7 +189,7 @@ void fill_err_code_array(bbfdm_data_t *data, int fault)
|
|||
static void transaction_timeout_handler(struct uloop_timeout *t __attribute__((unused)))
|
||||
{
|
||||
INFO("Transaction timeout called, aborting tid %d", g_current_trans.trans_id);
|
||||
transaction_abort(g_current_trans.trans_id, NULL);
|
||||
transaction_abort(NULL, g_current_trans.trans_id);
|
||||
}
|
||||
|
||||
static int get_random_id(void)
|
||||
|
|
@ -269,7 +271,7 @@ static int compare_path(const void *arg1, const void *arg2)
|
|||
}
|
||||
|
||||
// Returns transaction id if successful, otherwise 0
|
||||
int transaction_start(char *app, uint32_t max_timeout)
|
||||
int transaction_start(bbfdm_data_t *data, char *app, uint32_t max_timeout)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t timeout;
|
||||
|
|
@ -280,12 +282,12 @@ int transaction_start(char *app, uint32_t max_timeout)
|
|||
}
|
||||
|
||||
if (max_timeout > 0) {
|
||||
timeout = max_timeout;
|
||||
timeout = max_timeout * 1000;
|
||||
} else {
|
||||
timeout = g_current_trans.timeout_ms;
|
||||
}
|
||||
|
||||
ret = get_random_id();
|
||||
ret = data->trans_id ? data->trans_id : get_random_id();
|
||||
strncpyt(g_current_trans.app, app, 32);
|
||||
|
||||
g_current_trans.trans_id = ret;
|
||||
|
|
@ -293,6 +295,11 @@ int transaction_start(char *app, uint32_t max_timeout)
|
|||
uloop_timeout_set(&g_current_trans.trans_timeout, timeout);
|
||||
INFO("Transaction created by [%s] id %d, timeout %zd", g_current_trans.app, g_current_trans.trans_id, timeout);
|
||||
|
||||
if (data->trans_id) {
|
||||
// Call transaction for registered services only if transaction id is defined
|
||||
handle_transaction_of_registered_service(data->ctx, NULL, &head_registered_service, "start", ret, timeout/1000, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -323,17 +330,26 @@ bool is_transaction_valid(int trans_id)
|
|||
return (trans_id == g_current_trans.trans_id);
|
||||
}
|
||||
|
||||
int transaction_commit(int trans_id, struct blob_buf *bb, bool is_service_restart)
|
||||
int transaction_commit(bbfdm_data_t *data, int trans_id, bool is_service_restart)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (is_transaction_valid(trans_id)) {
|
||||
struct blob_buf *bb = data ? &data->bb : NULL;
|
||||
void *arr = NULL;
|
||||
|
||||
INFO("Commit on-going transaction by %s", g_current_trans.app);
|
||||
uloop_timeout_cancel(&g_current_trans.trans_timeout);
|
||||
g_current_trans.trans_id = 0;
|
||||
g_current_trans.app[0] = '\0';
|
||||
|
||||
if (bb) arr = blobmsg_open_array(bb, "updated_services");
|
||||
bbf_entry_restart_services(bb, is_service_restart);
|
||||
if (data && data->trans_id) {
|
||||
// Call transaction for registered services only if transaction id is defined
|
||||
handle_transaction_of_registered_service(data->ctx, bb, &head_registered_service, "commit", data->trans_id, 0, is_service_restart);
|
||||
}
|
||||
if (bb) blobmsg_close_array(bb, arr);
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
|
|
@ -343,17 +359,26 @@ int transaction_commit(int trans_id, struct blob_buf *bb, bool is_service_restar
|
|||
return ret;
|
||||
}
|
||||
|
||||
int transaction_abort(int trans_id, struct blob_buf *bb)
|
||||
int transaction_abort(bbfdm_data_t *data, int trans_id)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (is_transaction_valid(trans_id)) {
|
||||
struct blob_buf *bb = data ? &data->bb : NULL;
|
||||
void *arr = NULL;
|
||||
|
||||
INFO("Abort on-going transaction by %s", g_current_trans.app);
|
||||
uloop_timeout_cancel(&g_current_trans.trans_timeout);
|
||||
g_current_trans.trans_id = 0;
|
||||
g_current_trans.app[0] = '\0';
|
||||
|
||||
if (bb) arr = blobmsg_open_array(bb, "reverted_configs");
|
||||
bbf_entry_revert_changes(bb);
|
||||
if (data && data->trans_id) {
|
||||
// Call transaction for registered services only if transaction id is defined
|
||||
handle_transaction_of_registered_service(data->ctx, bb, &head_registered_service, "abort", data->trans_id, 0, 0);
|
||||
}
|
||||
if (bb) blobmsg_close_array(bb, arr);
|
||||
|
||||
ret = 0;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ void fill_err_code_array(bbfdm_data_t *data, int fault);
|
|||
|
||||
void bb_add_string(struct blob_buf *bb, const char *name, const char *value);
|
||||
|
||||
int transaction_start(char *app, uint32_t max_timeout);
|
||||
int transaction_commit(int trans_id, struct blob_buf *bb, bool is_service_restart);
|
||||
int transaction_abort(int trans_id, struct blob_buf *bb);
|
||||
int transaction_start(bbfdm_data_t *data, char *app, uint32_t max_timeout);
|
||||
int transaction_commit(bbfdm_data_t *data, int trans_id, bool is_service_restart);
|
||||
int transaction_abort(bbfdm_data_t *data, int trans_id);
|
||||
int transaction_status(struct blob_buf *bb);
|
||||
bool is_transaction_running(void);
|
||||
bool is_transaction_valid(int trans_id);
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ struct dmctx {
|
|||
bool isevent;
|
||||
bool isinfo;
|
||||
bool disable_mservice_browse;
|
||||
int trans_id;
|
||||
};
|
||||
|
||||
typedef struct dmnode {
|
||||
|
|
|
|||
|
|
@ -1291,6 +1291,7 @@ static int add_ubus_object(struct dmctx *dmctx, struct dmnode *node)
|
|||
json_object_object_add(in_args, "proto", json_object_new_string((dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp"));
|
||||
json_object_object_add(in_args, "instance_mode", json_object_new_string(dmctx->instance_mode ? "1" : "0"));
|
||||
json_object_object_add(in_args, "format", json_object_new_string("raw"));
|
||||
json_object_object_add(in_args, "transaction_id", json_object_new_int(dmctx->trans_id));
|
||||
|
||||
dmubus_call(ubus_name, "add",
|
||||
UBUS_ARGS{
|
||||
|
|
@ -1337,6 +1338,7 @@ static int del_ubus_object(struct dmctx *dmctx, struct dmnode *node)
|
|||
json_object_object_add(in_args, "proto", json_object_new_string((dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp"));
|
||||
json_object_object_add(in_args, "instance_mode", json_object_new_string(dmctx->instance_mode ? "1" : "0"));
|
||||
json_object_object_add(in_args, "format", json_object_new_string("raw"));
|
||||
json_object_object_add(in_args, "transaction_id", json_object_new_int(dmctx->trans_id));
|
||||
|
||||
dmubus_call(ubus_name, "del",
|
||||
UBUS_ARGS{
|
||||
|
|
@ -1408,6 +1410,7 @@ static int set_ubus_value(struct dmctx *dmctx, struct dmnode *node)
|
|||
json_object_object_add(in_args, "proto", json_object_new_string((dmctx->dm_type == BBFDM_BOTH) ? "both" : (dmctx->dm_type == BBFDM_CWMP) ? "cwmp" : "usp"));
|
||||
json_object_object_add(in_args, "instance_mode", json_object_new_string(dmctx->instance_mode ? "1" : "0"));
|
||||
json_object_object_add(in_args, "format", json_object_new_string("raw"));
|
||||
json_object_object_add(in_args, "transaction_id", json_object_new_int(dmctx->trans_id));
|
||||
|
||||
if (is_reference_parameter(ubus_name, dmctx->in_param, in_args)) {
|
||||
get_reference_paramater_value(dmctx, dmctx->in_value, param_value, sizeof(param_value));
|
||||
|
|
|
|||
|
|
@ -439,9 +439,6 @@ bool adm_entry_object_exists(struct dmctx *ctx, char *param)
|
|||
void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services)
|
||||
{
|
||||
struct package_change *pc = NULL;
|
||||
void *arr = NULL;
|
||||
|
||||
if (bb) arr = blobmsg_open_array(bb, "updated_services");
|
||||
|
||||
list_for_each_entry(pc, &head_package_change, list) {
|
||||
|
||||
|
|
@ -454,8 +451,6 @@ void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services)
|
|||
}
|
||||
}
|
||||
|
||||
if (bb) blobmsg_close_array(bb, arr);
|
||||
|
||||
dmuci_commit_bbfdm();
|
||||
|
||||
free_all_list_package_change(&head_package_change);
|
||||
|
|
@ -464,9 +459,6 @@ void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services)
|
|||
void bbf_entry_revert_changes(struct blob_buf *bb)
|
||||
{
|
||||
struct package_change *pc = NULL;
|
||||
void *arr = NULL;
|
||||
|
||||
if (bb) arr = blobmsg_open_array(bb, "reverted_configs");
|
||||
|
||||
list_for_each_entry(pc, &head_package_change, list) {
|
||||
|
||||
|
|
@ -475,8 +467,6 @@ void bbf_entry_revert_changes(struct blob_buf *bb)
|
|||
dmubus_call_set("uci", "revert", UBUS_ARGS{{"config", pc->package, String}}, 1);
|
||||
}
|
||||
|
||||
if (bb) blobmsg_close_array(bb, arr);
|
||||
|
||||
dmuci_revert_bbfdm();
|
||||
|
||||
free_all_list_package_change(&head_package_change);
|
||||
|
|
|
|||
|
|
@ -48,4 +48,7 @@ void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *
|
|||
bool load_service(DMOBJ *main_dm, struct list_head *srv_list, char *srv_name, char *srv_parent_dm, char *srv_obj);
|
||||
void free_services_from_list(struct list_head *clist);
|
||||
|
||||
int handle_transaction_of_registered_service(struct ubus_context *ctx, struct blob_buf *trans_bb, struct list_head *srvlist,
|
||||
const char *trans_cmd, int trans_id, uint32_t max_timeout, bool service_restart);
|
||||
|
||||
#endif //__DMENTRY_H__
|
||||
|
|
|
|||
|
|
@ -134,6 +134,81 @@ bool load_service(DMOBJ *main_dm, struct list_head *srv_list, char *srv_name, ch
|
|||
return true;
|
||||
}
|
||||
|
||||
static void ubus_transaction_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
||||
{
|
||||
struct blob_attr *tb[2] = {0};
|
||||
const struct blobmsg_policy p[2] = {
|
||||
{ "updated_services", BLOBMSG_TYPE_ARRAY },
|
||||
{ "reverted_configs", BLOBMSG_TYPE_ARRAY }
|
||||
};
|
||||
|
||||
if (msg == NULL || req == NULL)
|
||||
return;
|
||||
|
||||
struct blob_buf *bb = (struct blob_buf *)req->priv;
|
||||
if (bb == NULL)
|
||||
return;
|
||||
|
||||
blobmsg_parse(p, 2, tb, blobmsg_data(msg), blobmsg_len(msg));
|
||||
|
||||
if (tb[0]) {
|
||||
struct blob_attr *service = NULL;
|
||||
size_t rem;
|
||||
|
||||
blobmsg_for_each_attr(service, tb[0], rem) {
|
||||
blobmsg_add_string(bb, NULL, blobmsg_get_string(service));
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[1]) {
|
||||
struct blob_attr *config = NULL;
|
||||
size_t rem;
|
||||
|
||||
blobmsg_for_each_attr(config, tb[1], rem) {
|
||||
blobmsg_add_string(bb, NULL, blobmsg_get_string(config));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int handle_transaction_of_registered_service(struct ubus_context *ctx, struct blob_buf *trans_bb, struct list_head *srvlist,
|
||||
const char *trans_cmd, int trans_id, uint32_t max_timeout, bool service_restart)
|
||||
{
|
||||
struct service *srv = NULL;
|
||||
|
||||
if (is_micro_service == true) // This should be called only from main daemon
|
||||
return -1;
|
||||
|
||||
if (ctx == NULL || trans_id == 0)
|
||||
return -1;
|
||||
|
||||
list_for_each_entry(srv, srvlist, list) {
|
||||
struct blob_buf bb = {0};
|
||||
void *table = NULL;
|
||||
uint32_t ubus_id;
|
||||
|
||||
// check if object already present
|
||||
int ret = ubus_lookup_id(ctx, srv->name, &ubus_id);
|
||||
if (ret != 0)
|
||||
continue;
|
||||
|
||||
memset(&bb, 0, sizeof(struct blob_buf));
|
||||
blob_buf_init(&bb, 0);
|
||||
|
||||
blobmsg_add_string(&bb, "cmd", trans_cmd);
|
||||
blobmsg_add_u8(&bb, "restart_services", service_restart);
|
||||
blobmsg_add_u32(&bb, "timeout", max_timeout);
|
||||
|
||||
table = blobmsg_open_table(&bb, "optional");
|
||||
blobmsg_add_u32(&bb, "transaction_id", trans_id);
|
||||
blobmsg_close_table(&bb, table);
|
||||
|
||||
ubus_invoke(ctx, ubus_id, "transaction", bb.head, ubus_transaction_callback, (void *)trans_bb, 5000);
|
||||
blob_buf_free(&bb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb)
|
||||
{
|
||||
struct service *srv = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue