From: jongmyeongko Date: Thu, 18 May 2017 04:17:52 +0000 (+0900) Subject: Refactor package event handling X-Git-Tag: accepted/tizen/unified/20170608.185208~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=01d08462acbf177ca8f6b2938f55cc27f3db99f0;p=platform%2Fcore%2Fapi%2Fpackage-manager.git Refactor package event handling In the previous logic, one-by-one incoming events are assumed. So, when there are mixed events from the different package types, there is a bug of that the event_type is changed unexpectedly. Change-Id: I7bdb93050ca2f324be59b25aebd534fcf9e33bc9 Signed-off-by: jongmyeongko --- diff --git a/src/package_manager.c b/src/package_manager.c index 220d10c..5e9a954 100644 --- a/src/package_manager.c +++ b/src/package_manager.c @@ -30,19 +30,24 @@ static GHashTable *__cb_table = NULL; #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) -typedef struct _event_info { +typedef struct _request_event_info { int req_id; package_manager_event_type_e event_type; package_manager_event_state_e event_state; - struct _event_info *next; -} event_info; + struct _request_event_info *next; +} request_event_info; + +struct package_manager_event_info { + char *pkg_name; + package_manager_event_type_e event_type; +}; struct package_manager_s { int handle_id; pkgmgr_client_type ctype; pkgmgr_client *pc; pkgmgr_mode mode; - event_info *head; + GHashTable *event_info_table; package_manager_event_cb event_cb; void *user_data; }; @@ -53,7 +58,7 @@ struct package_manager_request_s { pkgmgr_client *pc; char *pkg_type; pkgmgr_mode mode; - event_info *head; + request_event_info *head; package_manager_request_event_cb event_cb; GHashTable *request_cb_table; void *user_data; @@ -96,6 +101,51 @@ static int package_manager_new_id() return manager_handle_id++; } +static void __clean_all_event_info(request_event_info *head) +{ + request_event_info *current = head; + request_event_info *prev; + + if (current == NULL) + return; + + while (current) { + prev = current; + current = current->next; + free(prev); + } +} + +static int __insert_event_info(package_manager_h manager, const char *pkg_name, + package_manager_event_type_e event_type) +{ + struct package_manager_event_info *info; + + info = calloc(1, sizeof(struct package_manager_event_info)); + if (info == NULL) + return -1; + info->pkg_name = strdup(pkg_name); + info->event_type = event_type; + g_hash_table_insert(manager->event_info_table, info->pkg_name, info); + + return 0; +} + +static void __free_event_info(gpointer data) +{ + struct package_manager_event_info *info = + (struct package_manager_event_info *)data; + + if (!info) + return; + + if (info->pkg_name) + free(info->pkg_name); + free(info); + + _LOGD("event_info removed"); +} + static void __free_request_cb_info(gpointer data) { int req_id; @@ -135,22 +185,6 @@ static int __insert_request_cb_info(package_manager_request_h request, int req_i return 0; } -static void __clean_all_event_info(event_info *head) -{ - event_info *current = head; - event_info *prev; - - if (current == NULL) - return; - - while (current) { - prev = current; - current = current->next; - free(prev); - prev = NULL; - } -} - API int package_manager_request_create(package_manager_request_h *request) { struct package_manager_request_s *package_manager_request; @@ -330,15 +364,15 @@ static int package_manager_get_event_type(const char *key, return PACKAGE_MANAGER_ERROR_NONE; } -static int __add_event_info(event_info **head, int req_id, +static int __add_event_info(request_event_info **head, int req_id, package_manager_event_type_e event_type, package_manager_event_state_e event_state) { - event_info *evt_info; - event_info *current; - event_info *prev; + request_event_info *evt_info; + request_event_info *current; + request_event_info *prev; - evt_info = (event_info *) calloc(1, sizeof(event_info)); + evt_info = (request_event_info *) calloc(1, sizeof(request_event_info)); if (evt_info == NULL) { _LOGD("calloc failed"); return -1; @@ -362,11 +396,11 @@ static int __add_event_info(event_info **head, int req_id, return 0; } -static int __find_event_info(event_info **head, int req_id, +static int __find_event_info(request_event_info **head, int req_id, package_manager_event_type_e *event_type, package_manager_event_state_e *event_state) { - event_info *tmp; + request_event_info *tmp; tmp = *head; @@ -385,13 +419,13 @@ static int __find_event_info(event_info **head, int req_id, return -1; } -static int __update_event_info(event_info **head, int req_id, +static int __update_event_info(request_event_info **head, int req_id, package_manager_event_type_e event_type, package_manager_event_state_e event_state) { package_manager_event_type_e evt_type; package_manager_event_state_e evt_state; - event_info *tmp; + request_event_info *tmp; if (__find_event_info(head, req_id, &evt_type, &evt_state) != 0) __add_event_info(head, req_id, event_type, event_state); @@ -415,32 +449,6 @@ static int __update_event_info(event_info **head, int req_id, return -1; } -/* -static int __remove_event_info(event_info **head request, int req_id) -{ - event_info *current; - event_info *tmp; - - if (* == NULL) - return -1; - - current = *head; - while (current) { - if (current->next) { - if (current->next->req_id == req_id) { - tmp = current->next; - current->next = current->next->next; - free(tmp); - return 0; - } - } - tmp = tmp->next; - } - - return -1; -} -*/ - static int request_event_handler(uid_t target_uid, int req_id, const char *pkg_type, const char *pkg_name, const char *key, const char *val, const void *pmsg, void *data) @@ -896,78 +904,12 @@ API int package_manager_destroy(package_manager_h manager) } pkgmgr_client_free(manager->pc); - manager->pc = NULL; - __clean_all_event_info(manager->head); + g_hash_table_destroy(manager->event_info_table); free(manager); return PACKAGE_MANAGER_ERROR_NONE; } -static int __add_event(event_info **head, int req_id, - package_manager_event_type_e event_type, - package_manager_event_state_e event_state) -{ - event_info *evt_info; - - evt_info = (event_info *) calloc(1, sizeof(event_info)); - if (evt_info == NULL) { - _LOGD("calloc failed"); - return -1; - } - evt_info->req_id = req_id; - evt_info->event_type = event_type; - evt_info->event_state = event_state; - evt_info->next = NULL; - - *head = evt_info; - - return 0; -} - -static int __find_event(event_info **head, int req_id, - package_manager_event_type_e *event_type, - package_manager_event_state_e *event_state) -{ - event_info *tmp; - - tmp = *head; - - if (tmp == NULL) { - _LOGE("tmp is NULL"); - return -1; - } - - *event_type = tmp->event_type; - *event_state = tmp->event_state; - return 0; -} - -static int __update_event(event_info **head, int req_id, - package_manager_event_type_e event_type, - package_manager_event_state_e event_state) -{ - package_manager_event_type_e evt_type; - package_manager_event_state_e evt_state; - event_info *tmp; - - if (__find_event_info(head, req_id, &evt_type, &evt_state) != 0) - __add_event_info(head, req_id, event_type, event_state); - else { - tmp = *head; - - if (tmp == NULL) { - _LOGE("tmp is NULL"); - return -1; - } - - tmp->event_type = event_type; - tmp->event_state = event_state; - return 0; - } - - return -1; -} - /* App Event Listening Policy: * +----------------+------------+---------------+------------------+ * |Listener \ Type |Global Event|My User's Event|Other user's Event| @@ -993,16 +935,19 @@ static int __validate_event_signal(uid_t target_uid) return -1; } -static int global_event_handler(uid_t target_uid, int req_id, const char *pkg_type, +static int internal_callback(uid_t target_uid, int req_id, const char *pkg_type, const char *pkg_name, const char *key, const char *val, const void *pmsg, void *data) { int ret = -1; package_manager_event_type_e event_type = -1; package_manager_event_state_e event_state = -1; + struct package_manager_event_info *info = NULL; + package_manager_h manager = data; uid_t uid = target_uid; - package_manager_h manager = data; + _LOGD("req_id(%d), pkg_name(%s), type(%s), key(%s), val(%s)", + req_id, pkg_name, pkg_type, key, val); if (target_uid == GLOBAL_USER) uid = getuid(); @@ -1010,78 +955,76 @@ static int global_event_handler(uid_t target_uid, int req_id, const char *pkg_ty if (__validate_event_signal(uid)) return PACKAGE_MANAGER_ERROR_NONE; + if (manager && manager->event_info_table) { + info = g_hash_table_lookup(manager->event_info_table, pkg_name); + } else { + _LOGE("invalid handle"); + return PACKAGE_MANAGER_ERROR_NONE; + } + + if (!info) { + if (strcasecmp(key, "start") != 0) { + _LOGD("unexpected signal or no info(removed)"); + return PACKAGE_MANAGER_ERROR_NONE; + } + } + if (strcasecmp(key, "start") == 0) { ret = package_manager_get_event_type(val, &event_type); if (ret != PACKAGE_MANAGER_ERROR_NONE) return PACKAGE_MANAGER_ERROR_INVALID_PARAMETER; - __add_event(&(manager->head), req_id, event_type, - PACKAGE_MANAGER_EVENT_STATE_STARTED); + if (!info) { + __insert_event_info(manager, pkg_name, event_type); - if (manager->event_cb && getuid() == uid) - manager->event_cb(pkg_type, pkg_name, - event_type, - PACKAGE_MANAGER_EVENT_STATE_STARTED, - 0, PACKAGE_MANAGER_ERROR_NONE, manager->user_data); - } else if (strcasecmp(key, "install_percent") == 0 - || strcasecmp(key, "progress_percent") == 0) { - if (__find_event - (&(manager->head), req_id, &event_type, - &event_state) == 0) { - __update_event(&(manager->head), req_id, - event_type, - PACKAGE_MANAGER_EVENT_STATE_PROCESSING); if (manager->event_cb && getuid() == uid) manager->event_cb(pkg_type, pkg_name, - event_type, - PACKAGE_MANAGER_EVENT_STATE_PROCESSING, - atoi(val), - PACKAGE_MANAGER_ERROR_NONE, - manager->user_data); + event_type, + PACKAGE_MANAGER_EVENT_STATE_STARTED, + 0, + PACKAGE_MANAGER_ERROR_NONE, + manager->user_data); + } else { + _LOGE("unexpected start event"); } - + } else if (strcasecmp(key, "install_percent") == 0 + || strcasecmp(key, "progress_percent") == 0) { + if (manager->event_cb && getuid() == uid) + manager->event_cb(pkg_type, pkg_name, + info->event_type, + PACKAGE_MANAGER_EVENT_STATE_PROCESSING, + atoi(val), + PACKAGE_MANAGER_ERROR_NONE, + manager->user_data); } else if (strcasecmp(key, "error") == 0) { - if (strcasecmp(key, "0") != 0) { - if (__find_event - (&(manager->head), req_id, &event_type, - &event_state) == 0) { - __update_event(&(manager->head), req_id, - event_type, - PACKAGE_MANAGER_EVENT_STATE_FAILED); - } - - if (manager->event_cb && getuid() == uid) - manager->event_cb(pkg_type, - pkg_name, event_type, - PACKAGE_MANAGER_EVENT_STATE_FAILED, - 0, - PACKAGE_MANAGER_ERROR_NONE, - manager->user_data); - } + if (manager->event_cb && getuid() == uid) + manager->event_cb(pkg_type, pkg_name, + info->event_type, + PACKAGE_MANAGER_EVENT_STATE_FAILED, + 0, + PACKAGE_MANAGER_ERROR_NONE, + manager->user_data); } else if (strcasecmp(key, "end") == 0) { - if (__find_event - (&(manager->head), req_id, &event_type, - &event_state) == 0) { - if (event_state != PACKAGE_MANAGER_EVENT_STATE_FAILED) { - if (manager->event_cb && getuid() == uid) - manager->event_cb(pkg_type, - pkg_name, event_type, - PACKAGE_MANAGER_EVENT_STATE_COMPLETED, - 100, - PACKAGE_MANAGER_ERROR_NONE, - manager->user_data); - } - } else { - if (strcasecmp(key, "ok") != 0) { - if (manager->event_cb && getuid() == uid) - manager->event_cb(pkg_type, - pkg_name, event_type, - PACKAGE_MANAGER_EVENT_STATE_FAILED, - 0, - PACKAGE_MANAGER_ERROR_NONE, - manager->user_data); + if (event_state != PACKAGE_MANAGER_EVENT_STATE_FAILED) { + if (manager->event_cb && getuid() == uid) { + if (strcasecmp(val, "ok") == 0) { + manager->event_cb(pkg_type, pkg_name, + info->event_type, + PACKAGE_MANAGER_EVENT_STATE_COMPLETED, + 100, + PACKAGE_MANAGER_ERROR_NONE, + manager->user_data); + } else { + manager->event_cb(pkg_type, pkg_name, + info->event_type, + PACKAGE_MANAGER_EVENT_STATE_FAILED, + 0, + PACKAGE_MANAGER_ERROR_NONE, + manager->user_data); + } } } + g_hash_table_remove(manager->event_info_table, info->pkg_name); } return PACKAGE_MANAGER_ERROR_NONE; @@ -1159,7 +1102,18 @@ API int package_manager_set_event_cb(package_manager_h manager, manager->event_cb = callback; manager->user_data = user_data; - pkgmgr_client_listen_status(manager->pc, global_event_handler, manager); + retval = pkgmgr_client_listen_status(manager->pc, + internal_callback, manager); + if (retval < 0) { + return package_manager_error(PACKAGE_MANAGER_ERROR_IO_ERROR, + __FUNCTION__, NULL); + } + + if (!manager->event_info_table) { + manager->event_info_table = + g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, __free_event_info); + } return PACKAGE_MANAGER_ERROR_NONE; } @@ -1177,6 +1131,8 @@ API int package_manager_unset_event_cb(package_manager_h manager) manager->event_cb = NULL; manager->user_data = NULL; + g_hash_table_remove_all(manager->event_info_table); + retval = pkgmgr_client_remove_listen_status(manager->pc); if (retval == PKGMGR_R_EINVAL) return