Add support for shared transaction in libprivilege-control DB.
authorDamian Chromejko <d.chromejko@samsung.com>
Thu, 19 Dec 2013 09:31:30 +0000 (10:31 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 30 Jan 2014 11:47:56 +0000 (12:47 +0100)
[Issue#]       SSDWSSP-722
[Feature]      No redundant rules updating during shared read
               transactions.
[Cause]        Rules in the DB are unnecessarily updated during shared
               read transactions.
[Solution]     Rules in the DB are updated only if the current
               transaction is not a shared read transaction.
[Verification] Although no additional tests were created, all previous tests
               should pass.

Change-Id: I6738add767cf1b666680a956ad19572a99d693e5

include/rules-db-internals.h
src/rules-db-internals.c
src/rules-db.c

index 7d619be..55c4b31 100644 (file)
@@ -119,10 +119,11 @@ int add_modified_apps_path_internal(sqlite3 *p_db, const char *const s_app_label
  *
  * @ingroup RDB internal functions
  *
- * @param  p_db pointer to a SQLite3 database object
- * @return      PC_OPERATION_SUCCESS on success, error code otherwise
+ * @param  p_db                      pointer to a SQLite3 database object
+ * @param  b_create_temporary_tables variable denoting if temporary tables should be created
+ * @return                           PC_OPERATION_SUCCESS on success, error code otherwise
  */
-int open_rdb_connection(sqlite3 **pp_db);
+int open_rdb_connection(sqlite3 **pp_db, bool b_create_temporary_tables);
 
 
 /**
index b4ed4ae..2766857 100644 (file)
@@ -178,7 +178,7 @@ static int database_busy_handler(void *not_used UNUSED,
 }
 
 
-int open_rdb_connection(sqlite3 **p_db)
+int open_rdb_connection(sqlite3 **p_db, bool b_create_temporary_tables)
 {
        RDB_LOG_ENTRY;
 
@@ -222,66 +222,74 @@ int open_rdb_connection(sqlite3 **p_db)
        sqlite3_free(p_err_msg);
 
 
-       // Create the temporary tables:
-       if(sqlite3_exec(*p_db,
-                       "PRAGMA foreign_keys = ON;                                 \
-                                                                                  \
-                       PRAGMA temp_store = MEMORY;                                \
-                                                                                  \
-                       CREATE TEMPORARY TABLE modified_label(                     \
-                               name VARCHAR NOT NULL PRIMARY KEY);                \
-                                                                                  \
-                       CREATE TEMPORARY TABLE all_smack_binary_rules_modified(    \
-                               subject TEXT NOT NULL,                             \
-                               object  TEXT NOT NULL,                             \
-                               access  INTEGER NOT NULL,                          \
-                               is_volatile INTEGER NOT NULL);                     \
-                                                                                  \
-                       CREATE TEMPORARY TABLE current_smack_rule_modified(        \
-                               subject VARCHAR NOT NULL,                          \
-                               object  VARCHAR NOT NULL,                          \
-                               access  INTEGER NOT NULL);                         \
-                                                                                  \
-                       CREATE TEMPORARY TABLE history_smack_rule_modified(        \
-                               subject VARCHAR NOT NULL,                          \
-                               object  VARCHAR NOT NULL,                          \
-                               access  INTEGER NOT NULL);                         \
-                                                                                  \
-                       CREATE TEMPORARY VIEW modified_smack_rules AS              \
-                       SELECT  subject, object,                                   \
-                               access_to_str(access_add) AS access_add,           \
-                               access_to_str(access_del) AS access_del            \
-                       FROM    (                                                  \
-                               SELECT     subject, object,                        \
-                                          s1.access & ~s2.access AS access_add,   \
-                                          s2.access & ~s1.access AS access_del    \
-                               FROM       current_smack_rule_modified AS s1       \
-                               INNER JOIN history_smack_rule_modified AS s2       \
-                                          USING (subject, object)                 \
-                               WHERE      s1.access != s2.access                  \
-                               UNION                                              \
-                               SELECT     subject, object,                        \
-                                          s1.access AS access_add,                \
-                                          0 AS access_del                         \
-                               FROM       current_smack_rule_modified s1          \
-                               LEFT JOIN  history_smack_rule_modified s2          \
-                                          USING (subject, object)                 \
-                               WHERE      s2.subject IS NULL AND                  \
-                                          s2.object  IS NULL                      \
-                               UNION                                              \
-                               SELECT     subject, object,                        \
-                                          0 AS access_add,                        \
-                                          s1.access AS access_del                 \
-                               FROM       history_smack_rule_modified s1          \
-                               LEFT JOIN  current_smack_rule_modified s2          \
-                                          USING (subject, object)                 \
-                               WHERE      s2.subject IS NULL AND                  \
-                                          s2.object  IS NULL                      \
-                               )                                                  \
-                       ORDER BY subject, object ASC;",
-                       0, 0, 0) != SQLITE_OK) {
-               C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
-               return PC_ERR_DB_CONNECTION;
+       if (b_create_temporary_tables) {
+               // Create the temporary tables:
+               if(sqlite3_exec(*p_db,
+                               "PRAGMA foreign_keys = ON;                                 \
+                                                                                          \
+                               PRAGMA temp_store = MEMORY;                                \
+                                                                                          \
+                               CREATE TEMPORARY TABLE modified_label(                     \
+                                       name VARCHAR NOT NULL PRIMARY KEY);                \
+                                                                                          \
+                               CREATE TEMPORARY TABLE all_smack_binary_rules_modified(    \
+                                       subject TEXT NOT NULL,                             \
+                                       object  TEXT NOT NULL,                             \
+                                       access  INTEGER NOT NULL,                          \
+                                       is_volatile INTEGER NOT NULL);                     \
+                                                                                          \
+                               CREATE TEMPORARY TABLE current_smack_rule_modified(        \
+                                       subject VARCHAR NOT NULL,                          \
+                                       object  VARCHAR NOT NULL,                          \
+                                       access  INTEGER NOT NULL);                         \
+                                                                                          \
+                               CREATE TEMPORARY TABLE history_smack_rule_modified(        \
+                                       subject VARCHAR NOT NULL,                          \
+                                       object  VARCHAR NOT NULL,                          \
+                                       access  INTEGER NOT NULL);                         \
+                                                                                          \
+                               CREATE TEMPORARY VIEW modified_smack_rules AS              \
+                               SELECT  subject, object,                                   \
+                                       access_to_str(access_add) AS access_add,           \
+                                       access_to_str(access_del) AS access_del            \
+                               FROM    (                                                  \
+                                       SELECT     subject, object,                        \
+                                                  s1.access & ~s2.access AS access_add,   \
+                                                  s2.access & ~s1.access AS access_del    \
+                                       FROM       current_smack_rule_modified AS s1       \
+                                       INNER JOIN history_smack_rule_modified AS s2       \
+                                                  USING (subject, object)                 \
+                                       WHERE      s1.access != s2.access                  \
+                                       UNION                                              \
+                                       SELECT     subject, object,                        \
+                                                  s1.access AS access_add,                \
+                                                  0 AS access_del                         \
+                                       FROM       current_smack_rule_modified s1          \
+                                       LEFT JOIN  history_smack_rule_modified s2          \
+                                                  USING (subject, object)                 \
+                                       WHERE      s2.subject IS NULL AND                  \
+                                                  s2.object  IS NULL                      \
+                                       UNION                                              \
+                                       SELECT     subject, object,                        \
+                                                  0 AS access_add,                        \
+                                                  s1.access AS access_del                 \
+                                       FROM       history_smack_rule_modified s1          \
+                                       LEFT JOIN  current_smack_rule_modified s2          \
+                                                  USING (subject, object)                 \
+                                       WHERE      s2.subject IS NULL AND                  \
+                                                  s2.object  IS NULL                      \
+                                       )                                                  \
+                               ORDER BY subject, object ASC;",
+                               0, 0, 0) != SQLITE_OK) {
+                       C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
+                       return PC_ERR_DB_CONNECTION;
+               }
+       } else {
+               // Just enable foreign keys:
+               if(sqlite3_exec(*p_db, "PRAGMA foreign_keys = ON", 0, 0, 0) != SQLITE_OK) {
+                       C_LOGE("RDB: Error during preparing script: %s", sqlite3_errmsg(*p_db));
+                       return PC_ERR_DB_CONNECTION;
+               }
        }
 
        return PC_OPERATION_SUCCESS;
index 26e84e5..a60403b 100644 (file)
@@ -33,6 +33,7 @@
 
 static sqlite3 *p_db__          = NULL;
 static int i_session_ret_code__ = PC_OPERATION_SUCCESS;
+static bool b_shared_transaction__ = false;
 
 typedef enum {
        RDB_TRANSACTION_EXCLUSIVE,
@@ -53,18 +54,24 @@ static int rdb_begin(sqlite3 **pp_db, rdb_transaction_type_t transaction_type)
        RDB_LOG_ENTRY;
 
        // If rdb_modification_start was called we use a global connection.
+       // Since global connection is always opened only for exclusive transactions, temporary
+       // tables are already created and b_shared_transaction is set to false.
        if(p_db__) {
                *pp_db = p_db__;
                return PC_OPERATION_SUCCESS;
        }
 
-       int ret = open_rdb_connection(pp_db);
+       // Shared transaction doesn't need temporary tables because SMACK labels won't be modified.
+       bool b_create_temporary_tables = transaction_type != RDB_TRANSACTION_SHARED_READ;
+       int ret = open_rdb_connection(pp_db, b_create_temporary_tables);
        if(ret != PC_OPERATION_SUCCESS) return ret;
 
        if(transaction_type == RDB_TRANSACTION_EXCLUSIVE) {
+               b_shared_transaction__ = false;
                ret = sqlite3_exec(*pp_db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0);
        }
        else if(transaction_type == RDB_TRANSACTION_SHARED_READ) {
+               b_shared_transaction__ = true;
                ret = sqlite3_exec(*pp_db, "BEGIN DEFERRED TRANSACTION", 0, 0, 0);
        }
        else {
@@ -76,6 +83,7 @@ static int rdb_begin(sqlite3 **pp_db, rdb_transaction_type_t transaction_type)
        if(ret != SQLITE_OK) {
                C_LOGE("RDB: Error during transaction begin: %s",
                       sqlite3_errmsg(*pp_db));
+               b_shared_transaction__ = false;
                return PC_ERR_DB_CONNECTION;
        }
 
@@ -101,7 +109,7 @@ static int rdb_end(sqlite3 *p_db, int i_session_ret)
        int ret = PC_OPERATION_SUCCESS;
 
        // No error during the session, make updates
-       if(i_session_ret == PC_OPERATION_SUCCESS) {
+       if(i_session_ret == PC_OPERATION_SUCCESS && !b_shared_transaction__) {
                ret = update_rules_in_db(p_db);
                if(ret != PC_OPERATION_SUCCESS) {
                        C_LOGE("RDB: Error during updating rules in the database: %d", ret);