From f6b58b1f9bb9c47cb9eaefb1266f890b6e705e82 Mon Sep 17 00:00:00 2001 From: hj kim Date: Mon, 5 Oct 2020 18:08:56 +0900 Subject: [PATCH] Reduce DB locking time foreach functions invoke callback while reading DB. It means that the DB is locked. But sometimes applications do unexpected things in callback and it could cause a long DB lock and prevent other apps from accessing the DB. Therefore, saving items to the internal list and unlock the DB quickly. Change-Id: Ideb57e53a77fa3ace74cec512ca4f3adcf149549 --- include/media_controller_private.h | 5 ++ packaging/capi-media-controller.spec | 2 +- src/media_controller_db.c | 112 +++++++++++++++++++++++++---------- src/media_controller_playlist.c | 5 -- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/include/media_controller_private.h b/include/media_controller_private.h index 63c6261..ac76cc4 100644 --- a/include/media_controller_private.h +++ b/include/media_controller_private.h @@ -419,6 +419,11 @@ typedef struct { GList *item_list; } mc_playlist_s; +typedef struct { + char *index; + media_controller_metadata_s *metadata; +} mc_playlist_item_s; + /* formal callback to receive signal */ typedef void(*mc_signal_received_cb)(const char *interface_name, const char *signal_name, const char *message, const char *request_id, void *user_data); diff --git a/packaging/capi-media-controller.spec b/packaging/capi-media-controller.spec index 46d1060..43fd00b 100644 --- a/packaging/capi-media-controller.spec +++ b/packaging/capi-media-controller.spec @@ -1,6 +1,6 @@ Name: capi-media-controller Summary: A media controller library in Tizen Native API -Version: 0.2.21 +Version: 0.2.22 Release: 1 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_controller_db.c b/src/media_controller_db.c index 8fc20fa..e2d90c6 100644 --- a/src/media_controller_db.c +++ b/src/media_controller_db.c @@ -88,6 +88,21 @@ static int __mc_db_get_bool_value(sqlite3 *handle, const char *server_name, cons return ret; } +static void __mc_db_playlist_destroy(gpointer data) +{ + mc_playlist_destroy((mc_playlist_h)data); +} + +static void __mc_db_playlist_item_destroy(gpointer data) +{ + mc_playlist_item_s *item = (mc_playlist_item_s *)data; + mc_retm_if_failed(item); + + g_free(item->index); + mc_metadata_destroy((mc_metadata_h)item->metadata); + g_free(item); +} + int _mc_db_update_playback_info(const char *server_name, const media_controller_playback_s playback) { int ret = MEDIA_CONTROLLER_ERROR_NONE; @@ -493,6 +508,8 @@ int _mc_db_get_foreach_playlist(sqlite3 *handle, const char *server_name, mc_pla int ret = MEDIA_CONTROLLER_ERROR_NONE; char *sql_str = NULL; sqlite3_stmt *stmt = NULL; + GList *playlists = NULL; + GList *node = NULL; mc_retvm_if(!handle, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid handle"); mc_retvm_if(!server_name, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name"); @@ -511,15 +528,21 @@ int _mc_db_get_foreach_playlist(sqlite3 *handle, const char *server_name, mc_pla _playlist->server_name = g_strdup(server_name); _playlist->playlist_name = g_strdup((const char *)sqlite3_column_text(stmt, 0)); - if (callback((mc_playlist_h)_playlist, user_data) == false) { - mc_playlist_destroy((mc_playlist_h)_playlist); + playlists = g_list_append(playlists, _playlist); + } + + SQLITE3_FINALIZE(stmt); + + node = playlists; + + while (node) { + if (!callback(node->data, user_data)) break; - } - mc_playlist_destroy((mc_playlist_h)_playlist); + node = g_list_next(node); } - SQLITE3_FINALIZE(stmt); + g_list_free_full(playlists, __mc_db_playlist_destroy); return MEDIA_CONTROLLER_ERROR_NONE; } @@ -597,8 +620,9 @@ int _mc_db_get_playlist_item(sqlite3 *handle, const char *server_name, char *pla int ret = MEDIA_CONTROLLER_ERROR_NONE; char *sql_str = NULL; sqlite3_stmt *stmt = NULL; - char *index = NULL; - mc_metadata_h _metadata = NULL; + mc_playlist_item_s *item = NULL; + GList *item_list = NULL; + unsigned int idx = 0, length = 0; mc_retvm_if(!handle, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid handle"); mc_retvm_if(!server_name, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid server_name"); @@ -613,27 +637,32 @@ int _mc_db_get_playlist_item(sqlite3 *handle, const char *server_name, char *pla mc_retvm_if(SQLITE_OK != ret, MEDIA_CONTROLLER_ERROR_INVALID_OPERATION, "prepare error [%s]", sqlite3_errmsg(handle)); while (sqlite3_step(stmt) == SQLITE_ROW) { - ret = __mc_db_get_metadata(stmt, 1, &_metadata); + item = g_new0(mc_playlist_item_s, 1); + + ret = __mc_db_get_metadata(stmt, 1, (mc_metadata_h *)&item->metadata); if (ret != MEDIA_CONTROLLER_ERROR_NONE) { mc_error("fail to __mc_db_get_metadata"); SQLITE3_FINALIZE(stmt); + g_list_free_full(item_list, __mc_db_playlist_item_destroy); return ret; } - index = g_strdup((char *)sqlite3_column_text(stmt, 0)); - - if (callback(index, (mc_metadata_h)_metadata, user_data) == false) { - g_free(index); - mc_metadata_destroy((mc_metadata_h)_metadata); - break; - } + item->index = g_strdup((char *)sqlite3_column_text(stmt, 0)); - g_free(index); - mc_metadata_destroy(_metadata); + item_list = g_list_append(item_list, item); } SQLITE3_FINALIZE(stmt); + length = g_list_length(item_list); + for (idx = 0; idx < length; idx++) { + item = g_list_nth_data(item_list, idx); + if (callback(item->index, (mc_metadata_h)item->metadata, user_data) == false) + break; + } + + g_list_free_full(item_list, __mc_db_playlist_item_destroy); + return MEDIA_CONTROLLER_ERROR_NONE; } @@ -749,6 +778,8 @@ int _mc_db_foreach_server_list(sqlite3 *handle, mc_activated_server_cb callback, char *sql_str = NULL; sqlite3_stmt *stmt = NULL; int idx = 0; + GList *list = NULL; + GList *node = NULL; mc_retvm_if(!handle, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid handle"); @@ -773,14 +804,8 @@ int _mc_db_foreach_server_list(sqlite3 *handle, mc_activated_server_cb callback, idx++; mc_info("[%d] %s", idx, server_name); - if (callback != NULL) { - if (callback(server_name, user_data) == false) { - g_free(server_name); - break; - } - } - - g_free(server_name); + if (callback) + list = g_list_append(list, server_name); ret = sqlite3_step(stmt); } @@ -789,6 +814,19 @@ int _mc_db_foreach_server_list(sqlite3 *handle, mc_activated_server_cb callback, SQLITE3_FINALIZE(stmt); + if (callback) { + node = list; + + while (node) { + if (!callback(node->data, user_data)) + break; + + node = g_list_next(node); + } + + g_list_free_full(list, g_free); + } + return MEDIA_CONTROLLER_ERROR_NONE; } @@ -798,6 +836,8 @@ int _mc_db_foreach_client_list(sqlite3 *handle, mc_activated_client_cb callback, char *sql_str = NULL; sqlite3_stmt *stmt = NULL; int idx = 0; + GList *list = NULL; + GList *node = NULL; mc_retvm_if(!handle, MEDIA_CONTROLLER_ERROR_INVALID_PARAMETER, "Invalid handle"); @@ -822,13 +862,8 @@ int _mc_db_foreach_client_list(sqlite3 *handle, mc_activated_client_cb callback, idx++; mc_info("[%d] %s", idx, client_name); - if (callback != NULL) { - if (callback(client_name, user_data) == false) { - g_free(client_name); - break; - } - } - g_free(client_name); + if (callback) + list = g_list_append(list, client_name); ret = sqlite3_step(stmt); } @@ -837,6 +872,19 @@ int _mc_db_foreach_client_list(sqlite3 *handle, mc_activated_client_cb callback, SQLITE3_FINALIZE(stmt); + if (callback) { + node = list; + + while (node) { + if (!callback(node->data, user_data)) + break; + + node = g_list_next(node); + } + + g_list_free_full(list, g_free); + } + return MEDIA_CONTROLLER_ERROR_NONE; } diff --git a/src/media_controller_playlist.c b/src/media_controller_playlist.c index baefe55..7a7c129 100644 --- a/src/media_controller_playlist.c +++ b/src/media_controller_playlist.c @@ -20,11 +20,6 @@ #define MAX_PLAYLIST_LEN 100 -typedef struct { - char *index; - media_controller_metadata_s *metadata; -} mc_playlist_item_s; - static void __release_playlist_item(gpointer data) { mc_playlist_item_s *playlist_item = (mc_playlist_item_s *)data; -- 2.7.4