X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=parser%2Fsrc%2Fpkgmgr_parser_db.c;h=b6db5238f24d2d3db4ada0e8e187dffe4fe62760;hb=aa88d97f98ae9093f07947ec8397e15e07e1dac3;hp=93d2e1a22a8e36ed112e3a497c864bdeebc752c9;hpb=9a5b648ce367d93407bed4890c27c94eff88f2b4;p=platform%2Fcore%2Fappfw%2Fpkgmgr-info.git diff --git a/parser/src/pkgmgr_parser_db.c b/parser/src/pkgmgr_parser_db.c index 93d2e1a..b6db523 100644 --- a/parser/src/pkgmgr_parser_db.c +++ b/parser/src/pkgmgr_parser_db.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -113,7 +114,7 @@ static const char *__get_bool(char *value, bool is_true) #define __BEGIN_TRANSACTION(db) \ do { \ - if (sqlite3_exec(db, "BEGIN EXCLUSIVE", NULL, NULL, NULL) != \ + if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) != \ SQLITE_OK) { \ _LOGE("begin transaction failed: %s", sqlite3_errmsg(db)); \ sqlite3_close_v2(db); \ @@ -328,6 +329,8 @@ static const char *parser_init_queries[] = { QUERY_CREATE_TABLE_PACKAGE_APP_INFO_FOR_UID, QUERY_CREATE_TRIGGER_UPDATE_PACKAGE_APP_INFO_FOR_UID, QUERY_CREATE_TABLE_PACKAGE_APP_SPLASH_SCREEN, + QUERY_CREATE_TABLE_PACKAGE_DEPENDENCY_INFO, + QUERY_CREATE_TABLE_PACKAGE_PLUGIN_INFO, NULL, }; @@ -341,11 +344,23 @@ static const char *cert_init_queries[] = { NULL }; -static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid) +static int __create_tables(sqlite3 *db, const char **queries) { int ret; - const char **queries; int i; + for (i = 0; queries[i] != NULL; i++) { + ret = sqlite3_exec(db, queries[i], NULL, NULL, NULL); + if (ret != SQLITE_OK) { + _LOGE("exec failed: %s", sqlite3_errmsg(db)); + return -1; + } + } + return 0; +} + +static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid) +{ + const char **queries; if (__set_db_version(db)) return -1; @@ -359,13 +374,9 @@ static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid) return -1; } - for (i = 0; queries[i] != NULL; i++) { - ret = sqlite3_exec(db, queries[i], NULL, NULL, NULL); - if (ret != SQLITE_OK) { - _LOGE("exec failed: %s", sqlite3_errmsg(db)); - return -1; - } - } + __BEGIN_TRANSACTION(db); + __DO_TRANSACTION(db, __create_tables(db, queries)); + __END_TRANSACTION(db); if (__set_db_permission(dbpath, uid)) _LOGE("failed to set db permission"); @@ -373,6 +384,122 @@ static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid) return 0; } +#define RESOURCED_BUS_NAME "org.tizen.resourced" +#define RESOURCED_PROC_PATH "/Org/Tizen/ResourceD/Process" +#define RESOURCED_PROC_INTERFACE "org.tizen.resourced.process" +#define RESOURCED_PROC_METHOD "ProcExclude" +static void __send_wakeup_signal_to_resourced(pid_t pid) +{ + GError *error = NULL; + GDBusConnection *conn; + GDBusProxy *proxy; + GVariant *reply; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (conn == NULL) { + _LOGE("Failed to connect to dbus: %s", error->message); + g_error_free(error); + return; + } + + proxy = g_dbus_proxy_new_sync(conn, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, RESOURCED_BUS_NAME, + RESOURCED_PROC_PATH, RESOURCED_PROC_INTERFACE, + NULL, &error); + if (proxy == NULL) { + _LOGE("failed to get proxy object: %s", error->message); + g_error_free(error); + g_object_unref(conn); + return; + } + + reply = g_dbus_proxy_call_sync(proxy, RESOURCED_PROC_METHOD, + g_variant_new("(si)", "wakeup", pid), + G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); + if (reply == NULL) + _LOGE("failed to get reply from resourced"); + if (error) { + _LOGE("failed to send request: %s", error->message); + g_error_free(error); + } + + g_object_unref(proxy); + g_object_unref(conn); +} + +static void __check_db_lock(const char *dbpath) +{ + FILE *fp; + FILE *fp_cmdline; + struct stat sb; + int pid; + unsigned int maj; + unsigned int min; + ino_t ino; + char cmdline[BUFSIZE]; + char name[BUFSIZE]; + size_t len; + + if (stat(dbpath, &sb) == -1) { + _LOGE("get db file(%s) status failed: %d", dbpath, errno); + return; + } + + fp = fopen("/proc/locks", "r"); + if (fp == NULL) { + _LOGE("Failed to open lock info: %d", errno); + return; + } + + while (fscanf(fp, "%*s %*s %*s %*s %d %x:%x:%lu %*s %*s", + &pid, &maj, &min, &ino) != EOF) { + if (maj != major(sb.st_dev) || min != minor(sb.st_dev) || + ino != sb.st_ino || pid == getpid()) + continue; + + snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); + fp_cmdline = fopen(cmdline, "r"); + name[0] = '\0'; + if (fp_cmdline != NULL) { + len = fread(name, sizeof(char), sizeof(name) - 1, + fp_cmdline); + if (len > 0) { + if (name[len - 1] == '\n') + name[len - 1] = '\0'; + else + name[len] = '\0'; + } + fclose(fp_cmdline); + } + + _LOGE("%s (%d) has lock on pkgmgr db(%s)!", name, pid, dbpath); + __send_wakeup_signal_to_resourced(pid); + } + + fclose(fp); +} + +#define BUSY_WAITING_USEC (1000000 / 10 / 2) /* 0.05 sec */ +#define BUSY_WAITING_MAX 40 /* wait for max 2 sec */ +static int __db_busy_handler(void *data, int count) +{ + if (count < (BUSY_WAITING_MAX / 2)) { + usleep(BUSY_WAITING_USEC); + return 1; + } else if (count == (BUSY_WAITING_MAX / 2)) { + __check_db_lock((const char *)data); + usleep(BUSY_WAITING_USEC); + return 1; + } else if (count < BUSY_WAITING_MAX) { + usleep(BUSY_WAITING_USEC); + return 1; + } else { + /* sqlite3_prepare_v2 will return SQLITE_BUSY */ + return 0; + } +} + API int pkgmgr_parser_initialize_parser_db(uid_t uid) { int ret; @@ -392,6 +519,14 @@ API int pkgmgr_parser_initialize_parser_db(uid_t uid) return PM_PARSER_R_ERROR; } + ret = sqlite3_busy_handler(db, __db_busy_handler, NULL); + if (ret != SQLITE_OK) { + _LOGE("failed to register busy handler: %s", + sqlite3_errmsg(db)); + sqlite3_close_v2(db); + return ret; + } + if (__initialize_db(db, dbpath, uid)) { sqlite3_close_v2(db); return PM_PARSER_R_ERROR; @@ -420,6 +555,14 @@ API int pkgmgr_parser_initialize_cert_db(void) return PM_PARSER_R_ERROR; } + ret = sqlite3_busy_handler(db, __db_busy_handler, NULL); + if (ret != SQLITE_OK) { + _LOGE("failed to register busy handler: %s", + sqlite3_errmsg(db)); + sqlite3_close_v2(db); + return ret; + } + if (__initialize_db(db, dbpath, GLOBAL_USER)) { sqlite3_close_v2(db); return PM_PARSER_R_ERROR; @@ -460,71 +603,6 @@ API int pkgmgr_parser_create_and_initialize_db(uid_t uid) return PM_PARSER_R_OK; } -static void __check_db_lock(const char *dbpath) -{ - FILE *fp; - FILE *fp_cmdline; - struct stat sb; - int pid; - unsigned int maj; - unsigned int min; - ino_t ino; - char cmdline[BUFSIZE]; - char name[BUFSIZE]; - size_t len; - - if (stat(dbpath, &sb) == -1) { - _LOGE("get db file(%s) status failed: %d", dbpath, errno); - return; - } - - fp = fopen("/proc/locks", "r"); - if (fp == NULL) { - _LOGE("Failed to open lock info: %d", errno); - return; - } - - while (fscanf(fp, "%*s %*s %*s %*s %d %x:%x:%lu %*s %*s", - &pid, &maj, &min, &ino) != EOF) { - if (maj != major(sb.st_dev) || min != minor(sb.st_dev) || - ino != sb.st_ino || pid == getpid()) - continue; - - snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid); - fp_cmdline = fopen(cmdline, "r"); - name[0] = '\0'; - if (fp_cmdline != NULL) { - len = fread(name, sizeof(char), sizeof(name) - 1, - fp_cmdline); - if (len > 0) { - if (name[len - 1] == '\n') - name[len - 1] = '\0'; - else - name[len] = '\0'; - } - fclose(fp_cmdline); - } - - _LOGE("%s (%d) has lock on pkgmgr db(%s)!", name, pid, dbpath); - } - - fclose(fp); -} - -#define BUSY_WAITING_USEC (1000000 / 10 / 2) /* 0.05 sec */ -#define BUSY_WAITING_MAX 20 /* wait for max 1 sec */ -static int __db_busy_handler(void *data, int count) -{ - if (count < BUSY_WAITING_MAX) { - usleep(BUSY_WAITING_USEC); - return 1; - } else { - /* sqlite3_prepare_v2 will return SQLITE_BUSY */ - __check_db_lock((const char *)data); - return 0; - } -} - static int __open_db(uid_t uid, const char *path, sqlite3 **db, int flags) { int ret; @@ -680,8 +758,8 @@ static int __insert_appcontrol_info(sqlite3 *db, application_x *app) { static const char query[] = "INSERT INTO package_app_app_control (app_id, app_control," - " visibility) " - "VALUES (?, ?, ?)"; + " visibility, app_control_id) " + "VALUES (?, ?, ?, ?)"; int ret; sqlite3_stmt *stmt; int idx; @@ -713,6 +791,7 @@ static int __insert_appcontrol_info(sqlite3 *db, application_x *app) __BIND_TEXT(db, stmt, idx++, app->appid); __BIND_TEXT(db, stmt, idx++, app_control); __BIND_TEXT(db, stmt, idx++, ac->visibility); + __BIND_TEXT(db, stmt, idx++, ac->id); ret = sqlite3_step(stmt); if (ret != SQLITE_DONE) { @@ -1635,6 +1714,81 @@ static int __insert_package_privilege_info(sqlite3 *db, manifest_x *mfx) return 0; } +static int __insert_package_plugin_execution_info(sqlite3 *db, + manifest_x *mfx) +{ + static const char query[] = + "INSERT INTO package_plugin_info " + "(pkgid, appid, plugin_type, plugin_name) " + "VALUES (?, ?, ?, ?)"; + int ret; + sqlite3_stmt *stmt; + int idx; + GList *tmp; + plugin_x *plugin; + + if (!mfx->plugin) + return 0; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + _LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return -1; + } + + for (tmp = mfx->plugin; tmp; tmp = tmp->next) { + plugin = (plugin_x *)tmp->data; + if (plugin == NULL) + continue; + + idx = 1; + __BIND_TEXT(db, stmt, idx++, plugin->pkgid); + __BIND_TEXT(db, stmt, idx++, plugin->appid); + __BIND_TEXT(db, stmt, idx++, plugin->plugin_type); + __BIND_TEXT(db, stmt, idx++, plugin->plugin_name); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_DONE) { + _LOGE("step failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + return -1; + } + sqlite3_reset(stmt); + } + + sqlite3_finalize(stmt); + + return 0; +} + +static int __delete_package_plugin_execution_info(sqlite3 *db, + const char *pkgid) +{ + static const char query[] = + "DELETE FROM package_plugin_info WHERE pkgid=?"; + int ret; + sqlite3_stmt *stmt; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + _LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return -1; + } + + __BIND_TEXT(db, stmt, 1, pkgid); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_DONE) { + _LOGE("step failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + return -1; + } + + sqlite3_finalize(stmt); + + return 0; +} + static int __insert_package_appdefined_privilege_info(sqlite3 *db, manifest_x *mfx) { @@ -1679,6 +1833,49 @@ static int __insert_package_appdefined_privilege_info(sqlite3 *db, return 0; } +static int __insert_package_dependency_info(sqlite3 *db, manifest_x *mfx) +{ + static const char query[] = + "INSERT INTO package_dependency_info" + " (package, depends_on, type, required_version) " + "VALUES (?, ?, ?, ?)"; + int ret; + sqlite3_stmt *stmt; + int idx; + GList *tmp; + dependency_x *dep; + + ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL); + if (ret != SQLITE_OK) { + _LOGE("prepare failed: %s", sqlite3_errmsg(db)); + return -1; + } + + for (tmp = mfx->dependencies; tmp; tmp = tmp->next) { + dep = (dependency_x *)tmp->data; + if (dep == NULL) + continue; + + idx = 1; + __BIND_TEXT(db, stmt, idx++, mfx->package); + __BIND_TEXT(db, stmt, idx++, dep->depends_on); + __BIND_TEXT(db, stmt, idx++, dep->type); + __BIND_TEXT(db, stmt, idx++, dep->required_version); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_DONE) { + _LOGE("step failed: %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + return -1; + } + sqlite3_reset(stmt); + } + + sqlite3_finalize(stmt); + + return 0; +} + /* _PRODUCT_LAUNCHING_ENHANCED_ * app->indicatordisplay, app->portraitimg, app->landscapeimg, * app->guestmode_appstatus @@ -2022,6 +2219,8 @@ static int __insert_package_info(sqlite3 *db, manifest_x *mfx) return -1; if (__insert_package_appdefined_privilege_info(db, mfx)) return -1; + if (__insert_package_dependency_info(db, mfx)) + return -1; return 0; } @@ -2944,3 +3143,92 @@ API int pkgmgr_parser_unregister_all_pkg_update_info_in_db(void) return pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db( __getuid()); } + +API int pkgmgr_parser_register_pkg_plugin_info_in_usr_db( + manifest_x *mfx, uid_t uid) +{ + int ret; + const char *dbpath; + sqlite3 *db; + + if (!mfx) + return PM_PARSER_R_EINVAL; + dbpath = __get_parser_db_path(uid); + ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE); + if (ret != SQLITE_OK) { + _LOGE("open db failed: %d", ret); + return PM_PARSER_R_ERROR; + } + + __BEGIN_TRANSACTION(db); + __DO_TRANSACTION(db, __insert_package_plugin_execution_info(db, mfx)); + __END_TRANSACTION(db); + + sqlite3_close_v2(db); + + return PM_PARSER_R_OK; +} + +API int pkgmgr_parser_register_pkg_plugin_info_in_db(manifest_x *mfx) +{ + return pkgmgr_parser_register_pkg_plugin_info_in_usr_db(mfx, __getuid()); +} + +API int pkgmgr_parser_update_pkg_plugin_info_in_usr_db( + manifest_x *mfx, uid_t uid) +{ + int ret; + const char *dbpath; + sqlite3 *db; + + if (!mfx) + return PM_PARSER_R_EINVAL; + dbpath = __get_parser_db_path(uid); + ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE); + if (ret != SQLITE_OK) { + _LOGE("open db failed: %d", ret); + return PM_PARSER_R_ERROR; + } + + __BEGIN_TRANSACTION(db); + __DO_TRANSACTION(db, __delete_package_plugin_execution_info(db, mfx->package)); + __DO_TRANSACTION(db, __insert_package_plugin_execution_info(db, mfx)); + __END_TRANSACTION(db); + + sqlite3_close_v2(db); + + return PM_PARSER_R_OK; +} + +API int pkgmgr_parser_update_pkg_plugin_info_in_db(manifest_x *mfx) +{ + return pkgmgr_parser_update_pkg_plugin_info_in_usr_db(mfx, __getuid()); +} + +API int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db( + const char *pkgid, uid_t uid) +{ + int ret; + const char *dbpath; + sqlite3 *db; + + dbpath = __get_parser_db_path(uid); + ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE); + if (ret != SQLITE_OK) { + _LOGE("open db failed: %d", ret); + return PM_PARSER_R_ERROR; + } + + __BEGIN_TRANSACTION(db); + __DO_TRANSACTION(db, __delete_package_plugin_execution_info(db, pkgid)); + __END_TRANSACTION(db); + + sqlite3_close_v2(db); + + return PM_PARSER_R_OK; +} + +API int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid) +{ + return pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(pkgid, __getuid()); +} \ No newline at end of file