Modified to support custom item 71/57571/8
authorSomin Kim <somin926.kim@samsung.com>
Thu, 21 Jan 2016 05:08:15 +0000 (14:08 +0900)
committerSomin Kim <somin926.kim@samsung.com>
Mon, 15 Feb 2016 10:09:51 +0000 (02:09 -0800)
Change-Id: I7bce0422916ae89749a41ea5586cebb5c14d490d
Signed-off-by: Somin Kim <somin926.kim@samsung.com>
16 files changed:
src/access_control/peer_creds.cpp
src/access_control/peer_creds.h
src/client_request.cpp
src/client_request.h
src/context_mgr_impl.cpp
src/context_mgr_impl.h
src/context_trigger/context_monitor.cpp
src/context_trigger/rule.cpp
src/context_trigger/rule_manager.cpp
src/context_trigger/rule_manager.h
src/context_trigger/template_manager.cpp
src/context_trigger/template_manager.h
src/context_trigger/trigger.cpp
src/context_trigger/trigger.h
src/request.cpp
src/request.h

index a4a74dc..c8641bc 100644 (file)
 #include <cynara-creds-gdbus.h>
 #include <cynara-session.h>
 #include <app_manager.h>
+#include <package_manager.h>
 #include <types_internal.h>
 #include "peer_creds.h"
 
-ctx::credentials::credentials(char *_app_id, char *_client, char *_session, char *_user) :
+ctx::credentials::credentials(char *_app_id, char *_package_id, char *_client, char *_session, char *_user) :
        app_id(_app_id),
+       package_id(_package_id),
        client(_client),
        session(_session),
        user(_user)
@@ -31,6 +33,7 @@ ctx::credentials::credentials(char *_app_id, char *_client, char *_session, char
 ctx::credentials::~credentials()
 {
        g_free(app_id);
+       g_free(package_id);
        g_free(client);
        g_free(session);
        g_free(user);
@@ -40,6 +43,7 @@ bool ctx::peer_creds::get(GDBusConnection *connection, const char *unique_name,
 {
        pid_t pid = 0;
        char *app_id = NULL;
+       char *package_id = NULL;
        gchar *client = NULL;
        char *session = NULL;
        gchar *user = NULL;
@@ -49,7 +53,8 @@ bool ctx::peer_creds::get(GDBusConnection *connection, const char *unique_name,
        IF_FAIL_RETURN_TAG(err == CYNARA_API_SUCCESS, false, _E, "Peer credentialing failed");
 
        app_manager_get_app_id(pid, &app_id);
-       _D("AppId: %s", app_id);
+       package_manager_get_package_id_by_app_id(app_id, &package_id);
+       _D("AppId: %s, PackageId: %s", app_id, package_id);
 
        err = cynara_creds_gdbus_get_client(connection, unique_name, CLIENT_METHOD_DEFAULT, &client);
        IF_FAIL_CATCH_TAG(err == CYNARA_API_SUCCESS, _E, "Peer credentialing failed");
@@ -60,13 +65,14 @@ bool ctx::peer_creds::get(GDBusConnection *connection, const char *unique_name,
        err = cynara_creds_gdbus_get_user(connection, unique_name, USER_METHOD_DEFAULT, &user);
        IF_FAIL_CATCH_TAG(err == CYNARA_API_SUCCESS, _E, "Peer credentialing failed");
 
-       *creds = new(std::nothrow) credentials(app_id, client, session, user);
+       *creds = new(std::nothrow) credentials(app_id, package_id, client, session, user);
        IF_FAIL_CATCH_TAG(*creds, _E, "Memory allocation failed");
 
        return true;
 
 CATCH:
        g_free(app_id);
+       g_free(package_id);
        g_free(client);
        g_free(session);
        g_free(user);
index d122ec8..7889987 100644 (file)
@@ -26,10 +26,11 @@ namespace ctx {
        class credentials {
        public:
                char *app_id;
+               char *package_id;
                char *client;   /* default: smack label */
                char *session;
                char *user;             /* default: UID */
-               credentials(char *_app_id, char *_client, char *_session, char *_user);
+               credentials(char *_app_id, char *_package_id, char *_client, char *_session, char *_user);
                ~credentials();
        };
 
index 2dd8a14..e164d6d 100644 (file)
@@ -52,6 +52,14 @@ const char* ctx::client_request::get_app_id()
        return NULL;
 }
 
+const char* ctx::client_request::get_package_id()
+{
+       if (__credentials)
+               return __credentials->package_id;
+
+       return NULL;
+}
+
 const char* ctx::client_request::get_client()
 {
        if (__credentials)
index 1f60690..6df5da7 100644 (file)
@@ -30,6 +30,7 @@ namespace ctx {
 
                const credentials* get_credentials();
                const char* get_app_id();
+               const char* get_package_id();
                const char* get_client();
                bool reply(int error);
                bool reply(int error, ctx::json &request_result);
index d48d837..d6ef171 100644 (file)
@@ -18,6 +18,7 @@
 #include <list>
 
 #include <types_internal.h>
+#include <context_trigger_types_internal.h>
 #include <json.h>
 #include <provider_iface.h>
 #include "server.h"
 #include <internal/device_context_provider.h>
 #include <internal/statistics_context_provider.h>
 #include <internal/place_context_provider.h>
+#include <internal/custom_context_provider.h>
 
 struct trigger_item_format_s {
        std::string subject;
        int operation;
        ctx::json attributes;
        ctx::json options;
-       trigger_item_format_s(std::string subj, int ops, ctx::json attr, ctx::json opt)
-               : subject(subj), operation(ops), attributes(attr), options(opt) {}
+       std::string owner;
+       bool unregister;
+       trigger_item_format_s(std::string subj, int ops, ctx::json attr, ctx::json opt, std::string own)
+               : subject(subj), operation(ops), attributes(attr), options(opt), owner(own)
+       {
+               unregister = false;
+       }
+
+       trigger_item_format_s(std::string subj)
+               : subject(subj) {
+               unregister = true;
+       }
 };
 
 static std::list<trigger_item_format_s> __trigger_item_list;
@@ -64,6 +76,9 @@ bool ctx::context_manager_impl::init()
        ret = init_place_context_provider();
        IF_FAIL_RETURN_TAG(ret, false, _E, "Initialization failed: place-context-provider");
 
+       ret = init_custom_context_provider();
+       IF_FAIL_RETURN_TAG(ret, false, _E, "Initialization failed: custom-context-provider");
+
        return true;
 }
 
@@ -98,14 +113,37 @@ bool ctx::context_manager_impl::register_provider(const char *subject, ctx::cont
        return true;
 }
 
-bool ctx::context_manager_impl::register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options)
+bool ctx::context_manager_impl::unregister_provider(const char *subject)
+{
+       auto it = provider_handle_map.find(subject);
+       if (it == provider_handle_map.end()) {
+               _E("The provider for the subject '%s' is not found.", subject);
+               return false;
+       }
+
+       delete it->second;
+       provider_handle_map.erase(it);
+
+       return true;
+}
+
+bool ctx::context_manager_impl::register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options, const char* owner)
+{
+       IF_FAIL_RETURN_TAG(subject, false, _E, "Invalid parameter");
+       __trigger_item_list.push_back(trigger_item_format_s(subject, operation, attributes, options, (owner)? owner : ""));
+
+       return true;
+}
+
+bool ctx::context_manager_impl::unregister_trigger_item(const char *subject)
 {
        IF_FAIL_RETURN_TAG(subject, false, _E, "Invalid parameter");
-       __trigger_item_list.push_back(trigger_item_format_s(subject, operation, attributes, options));
+       __trigger_item_list.push_back(trigger_item_format_s(subject));
+
        return true;
 }
 
-bool ctx::context_manager_impl::pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options)
+bool ctx::context_manager_impl::pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options, std::string& owner, bool& unregister)
 {
        IF_FAIL_RETURN(!__trigger_item_list.empty(), false);
 
@@ -116,12 +154,19 @@ bool ctx::context_manager_impl::pop_trigger_item(std::string &subject, int &oper
        operation = format.operation;
        attributes = format.attributes;
        options = format.options;
+       owner = format.owner;
+       unregister = format.unregister;
 
        return true;
 }
 
 void ctx::context_manager_impl::assign_request(ctx::request_info* request)
 {
+       if (handle_custom_request(request)) {
+               delete request;
+               return;
+       }
+
        auto it = provider_handle_map.find(request->get_subject());
        if (it == provider_handle_map.end()) {
                _W("Unsupported subject");
@@ -255,3 +300,45 @@ bool ctx::context_manager_impl::reply_to_read(const char* subject, ctx::json& op
 
        return true;
 }
+
+bool ctx::context_manager_impl::handle_custom_request(ctx::request_info* request)
+{
+       std::string subject = request->get_subject();
+       IF_FAIL_RETURN( subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_ADD ||
+                                       subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_REMOVE ||
+                                       subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_PUBLISH, false);
+
+       const char* pkg_id = request->get_package_id();
+       if (pkg_id == NULL) {
+               request->reply(ERR_OPERATION_FAILED);
+               return true;
+       }
+
+       ctx::json desc = request->get_description();
+       std::string name;
+       desc.get(NULL, CT_CUSTOM_NAME, &name);
+       std::string subj = pkg_id + std::string("::") + name;
+
+       int error = ERR_NONE;
+       if (subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_ADD) {
+               ctx::json tmpl;
+               desc.get(NULL, CT_CUSTOM_ATTRIBUTES, &tmpl);
+
+               error = ctx::custom_context_provider::add_item(subj, name, tmpl, pkg_id);
+       } else if (subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_REMOVE) {
+               error = ctx::custom_context_provider::remove_item(subj);
+               if (error == ERR_NONE) {
+                       ctx::json data;
+                       data.set(NULL, CT_CUSTOM_SUBJECT, subj);
+                       request->reply(error, data);
+               }
+       } else if (subject == CONTEXT_TRIGGER_SUBJECT_CUSTOM_PUBLISH) {
+               ctx::json fact;
+               desc.get(NULL, CT_CUSTOM_FACT, &fact);
+
+               error = ctx::custom_context_provider::publish_data(subj, fact);
+       }
+
+       request->reply(error);
+       return true;
+}
index 5281595..a9fbb54 100644 (file)
@@ -41,11 +41,13 @@ namespace ctx {
                void assign_request(ctx::request_info *request);
                bool is_supported(const char *subject);
                bool is_allowed(const credentials *creds, const char *subject);
-               bool pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options);
+               bool pop_trigger_item(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options, std::string &owner, bool& unregister);
 
                /* From the interface class */
                bool register_provider(const char *subject, context_provider_info &provider_info);
-               bool register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options);
+               bool unregister_provider(const char *subject);
+               bool register_trigger_item(const char *subject, int operation, ctx::json attributes, ctx::json options, const char *owner = NULL);
+               bool unregister_trigger_item(const char *subject);
                bool publish(const char *subject, ctx::json &option, int error, ctx::json &data_updated);
                bool reply_to_read(const char *subject, ctx::json &option, int error, ctx::json &data_read);
 
@@ -56,6 +58,8 @@ namespace ctx {
                void _publish(const char *subject, ctx::json &option, int error, ctx::json &data_updated);
                void _reply_to_read(const char *subject, ctx::json &option, int error, ctx::json &data_read);
 
+               /* For custom request */
+               bool handle_custom_request(ctx::request_info* request);
        };      /* class context_manager_impl */
 
 }      /* namespace ctx */
index d70b20f..576ee8c 100644 (file)
@@ -75,7 +75,7 @@ void ctx::context_monitor::destroy()
 int ctx::context_monitor::subscribe(int rule_id, std::string subject, ctx::json option, context_listener_iface* listener)
 {
        int req_id = _subscribe(subject.c_str(), &option, listener);
-       IF_FAIL_RETURN_TAG(req_id > 0, ERR_OPERATION_FAILED, _E, "Subscribe event failed");
+       IF_FAIL_RETURN_TAG(req_id > 0, req_id, _E, "Subscribe event failed");
        _D(YELLOW("Subscribe event(rule%d). req%d"), rule_id, req_id);
 
        return ERR_NONE;
@@ -96,7 +96,7 @@ int ctx::context_monitor::_subscribe(const char* subject, json* option, context_
 
        fact_request *req = new(std::nothrow) fact_request(REQ_SUBSCRIBE,
                        rid, subject, option ? option->str().c_str() : NULL, this);
-       IF_FAIL_RETURN_TAG(req, -1, _E, "Memory allocation failed");
+       IF_FAIL_RETURN_TAG(req, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed");
 
        _context_mgr->assign_request(req);
        add_sub(REQ_SUBSCRIBE, rid, subject, option, listener);
@@ -104,7 +104,7 @@ int ctx::context_monitor::_subscribe(const char* subject, json* option, context_
        if (last_err != ERR_NONE) {
                remove_sub(REQ_SUBSCRIBE, rid);
                _E("Subscription request failed: %#x", last_err);
-               return -1;
+               return last_err;
        }
 
        return rid;
index 5c05f60..5328f42 100644 (file)
@@ -78,6 +78,10 @@ int ctx::trigger_rule::stop(void)
 {
        // Unsubscribe event
        int error = ctx::context_monitor::get_instance()->unsubscribe(id, event->name, event->option, this);
+       if (error == ERR_NOT_SUPPORTED) {
+               _E("Stop rule%d (event not supported)");
+               return ERR_NONE;
+       }
        IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", id);
 
        return error;
@@ -125,7 +129,7 @@ void ctx::trigger_rule::on_event_received(std::string name, ctx::json option, ct
        // Check if creator is uninstalled
        if (ctx::rule_manager::is_uninstalled_package(creator)) {
                _D("Creator(%s) of rule%d is uninstalled.", creator.c_str(), id);
-               g_idle_add(handle_uninstalled_rule, &id);
+               g_idle_add(handle_uninstalled_rule, &creator);
                return;
        }
 
@@ -190,9 +194,8 @@ void ctx::trigger_rule::on_context_data_prepared(void)
 
 gboolean ctx::trigger_rule::handle_uninstalled_rule(gpointer data)
 {
-       int* rule_id = static_cast<int*>(data);
-       rule_mgr->disable_rule(*rule_id);
-       rule_mgr->remove_rule(*rule_id);
+       std::string* app_id = static_cast<std::string*>(data);
+       rule_mgr->handle_rule_of_uninstalled_app(*app_id);
 
        return FALSE;
 }
index f76c03f..cb8f579 100644 (file)
@@ -21,7 +21,6 @@
 #include <app_manager.h>
 #include "rule_manager.h"
 #include "context_monitor.h"
-#include "template_manager.h"
 #include "rule.h"
 #include "timer.h"
 
@@ -46,8 +45,7 @@ static std::string int_to_string(int i)
        return str;
 }
 
-ctx::rule_manager::rule_manager(ctx::template_manager* tmpl_mgr)
-: _tmpl_mgr(tmpl_mgr)
+ctx::rule_manager::rule_manager()
 {
 }
 
@@ -61,21 +59,12 @@ bool ctx::rule_manager::init()
        int error;
 
        // Create tables into db (rule, template)
-       std::string q1 = std::string("enabled INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL,")
+       std::string q1 = std::string("status INTEGER DEFAULT 0 NOT NULL, creator TEXT DEFAULT '' NOT NULL,")
                        + "creator_app_id TEXT DEFAULT '' NOT NULL, description TEXT DEFAULT '',"
                        + "details TEXT DEFAULT '' NOT NULL";
        ret = db_manager::create_table(1, RULE_TABLE, q1.c_str(), NULL, NULL);
        IF_FAIL_RETURN_TAG(ret, false, _E, "Create rule table failed");
 
-       std::string q2 = std::string("CREATE TABLE IF NOT EXISTS context_trigger_template ")
-                       + "(name TEXT DEFAULT '' NOT NULL PRIMARY KEY, operation INTEGER DEFAULT 3 NOT NULL, "
-                       + "attributes TEXT DEFAULT '' NOT NULL, options TEXT DEFAULT '' NOT NULL)";
-       ret = db_manager::execute(2, q2.c_str(), NULL);
-       IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
-
-       // Apply templates
-       _tmpl_mgr->apply_templates();
-
        // Before re-enable rules, handle uninstalled app's rules
        if (get_uninstalled_app() > 0) {
                error = clear_rule_of_uninstalled_app(true);
@@ -86,6 +75,12 @@ bool ctx::rule_manager::init()
        return ret;
 }
 
+void ctx::rule_manager::handle_rule_of_uninstalled_app(std::string app_id)
+{
+       uninstalled_apps.insert(app_id);
+       clear_rule_of_uninstalled_app();
+}
+
 int ctx::rule_manager::get_uninstalled_app(void)
 {
        // Return number of uninstalled apps
@@ -151,7 +146,7 @@ int ctx::rule_manager::clear_rule_of_uninstalled_app(bool is_init)
 
        // After event received, disable all the enabled rules of uninstalled apps      // TODO register uninstalled apps app_id when before trigger
        if (!is_init) {
-               std::string q1 = "SELECT row_id FROM context_trigger_rule WHERE enabled = 1 and (";
+               std::string q1 = "SELECT row_id FROM context_trigger_rule WHERE status = 2 and (";
                q1 += creator_list;
                q1 += ")";
 
@@ -182,15 +177,64 @@ int ctx::rule_manager::clear_rule_of_uninstalled_app(bool is_init)
        return ERR_NONE;
 }
 
+int ctx::rule_manager::pause_rule_with_item(std::string& subject)
+{
+       std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=2) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
+       std::vector<json> record;
+       bool ret = db_manager::execute_sync(q.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Failed to query row_ids to be paused");
+       IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
+
+       _D("Pause rules related to %s", subject.c_str());
+       std::vector<json>::iterator vec_end = record.end();
+       for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
+               ctx::json elem = *vec_pos;
+               int row_id;
+               elem.get(NULL, "row_id", &row_id);
+
+               int error = pause_rule(row_id);
+               IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to disable rules using custom item");
+       }
+
+       return ERR_NONE;
+}
+
+int ctx::rule_manager::resume_rule_with_item(std::string& subject)
+{
+       std::string q = "SELECT row_id FROM context_trigger_rule WHERE (status=1) AND (details LIKE '%\"ITEM_NAME\":\"" + subject + "\"%');";
+       std::vector<json> record;
+       bool ret = db_manager::execute_sync(q.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Query paused rule ids failed");
+       IF_FAIL_RETURN(record.size() > 0, ERR_NONE);
+
+       _D("Resume rules related to %s", subject.c_str());
+       std::string q_rowid;
+       std::vector<json>::iterator vec_end = record.end();
+       for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
+               ctx::json elem = *vec_pos;
+               int row_id;
+               elem.get(NULL, "row_id", &row_id);
+
+               int error = enable_rule(row_id);
+               IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to resume rule");
+       }
+
+       return ERR_NONE;
+}
+
 bool ctx::rule_manager::reenable_rule(void)
 {
        int error;
-       std::string q = "SELECT row_id FROM context_trigger_rule where enabled = 1";
+       std::string q = "SELECT row_id FROM context_trigger_rule WHERE status = 2";
 
        std::vector<json> record;
        bool ret = db_manager::execute_sync(q.c_str(), &record);
        IF_FAIL_RETURN_TAG(ret, false, _E, "Query row_ids of enabled rules failed");
+       IF_FAIL_RETURN_TAG(record.size() > 0, true, _D, "No rule to re-enable");
 
+       _D(YELLOW("Re-enable rule started"));
+
+       std::string q_rowid;
        std::vector<json>::iterator vec_end = record.end();
        for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
                ctx::json elem = *vec_pos;
@@ -198,10 +242,19 @@ bool ctx::rule_manager::reenable_rule(void)
                elem.get(NULL, "row_id", &row_id);
 
                error = enable_rule(row_id);
-               if (error != ERR_NONE) {
+               if (error == ERR_NOT_SUPPORTED) {
+                       q_rowid += "(row_id = " + int_to_string(row_id) + ") OR ";
+               } else if (error != ERR_NONE) {
                        _E("Re-enable rule%d failed(%d)", row_id, error);
                }
        }
+       q_rowid = q_rowid.substr(0, q_rowid.length() - 4);
+
+       // For rules which is failed to re-enable
+       std::string q_update = "UPDATE context_trigger_rule SET status = 1 WHERE " + q_rowid;
+       std::vector<json> record2;
+       ret = db_manager::execute_sync(q_update.c_str(), &record2);
+       IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update rules as paused");
 
        return true;
 }
@@ -262,7 +315,7 @@ bool ctx::rule_manager::rule_item_equals(ctx::json& litem, ctx::json& ritem)
        if (lei.compare(rei))
                return false;
 
-       // Compare option       // TODO test
+       // Compare option
        ctx::json loption, roption;
        litem.get(NULL, CT_RULE_EVENT_OPTION, &loption);
        ritem.get(NULL, CT_RULE_EVENT_OPTION, &roption);
@@ -537,7 +590,7 @@ int ctx::rule_manager::enable_rule(int rule_id)
        IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Failed to start rule%d", rule_id);
 
        // Update db to set 'enabled'
-       query = "UPDATE context_trigger_rule SET enabled = 1 WHERE row_id = ";
+       query = "UPDATE context_trigger_rule SET status = 2 WHERE row_id = ";
        query += id_str;
        error = (db_manager::execute_sync(query.c_str(), &record))? ERR_NONE : ERR_OPERATION_FAILED;
        IF_FAIL_CATCH_TAG(error == ERR_NONE, _E, "Update db failed");
@@ -561,6 +614,37 @@ int ctx::rule_manager::disable_rule(int rule_id)
        int error;
 
        rule_map_t::iterator it = rule_map.find(rule_id);
+       bool is_paused = (it == rule_map.end());
+
+       // For 'enabled' rule, not 'paused'
+       if (!is_paused) {
+               // Stop the rule
+               trigger_rule* rule = static_cast<trigger_rule*>(it->second);
+               error = rule->stop();
+               IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", rule_id);
+
+               // Remove rule instance from rule_map
+               delete rule;
+               rule_map.erase(it);
+       }
+
+       // Update db to set 'disabled'  // TODO skip while clear uninstalled rule
+       std::string query = "UPDATE context_trigger_rule SET status = 0 WHERE row_id = ";
+       query += int_to_string(rule_id);
+       std::vector<json> record;
+       ret = db_manager::execute_sync(query.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, ERR_OPERATION_FAILED, _E, "Update db failed");
+
+       _D(YELLOW("Disable Rule%d succeeded"), rule_id);
+       return ERR_NONE;
+}
+
+int ctx::rule_manager::pause_rule(int rule_id)
+{
+       bool ret;
+       int error;
+
+       rule_map_t::iterator it = rule_map.find(rule_id);
        IF_FAIL_RETURN_TAG(it != rule_map.end(), ERR_OPERATION_FAILED, _E, "Rule instance not found");
 
        // Stop the rule
@@ -568,8 +652,8 @@ int ctx::rule_manager::disable_rule(int rule_id)
        error = rule->stop();
        IF_FAIL_RETURN_TAG(error == ERR_NONE, error, _E, "Failed to stop rule%d", rule_id);
 
-       // Update db to set 'disabled'  // TODO skip while clear uninstalled rule
-       std::string query = "UPDATE context_trigger_rule SET enabled = 0 WHERE row_id = ";
+       // Update db to set 'paused'
+       std::string query = "UPDATE context_trigger_rule SET status = 1 WHERE row_id = ";
 
        query += int_to_string(rule_id);
        std::vector<json> record;
@@ -580,7 +664,7 @@ int ctx::rule_manager::disable_rule(int rule_id)
        delete rule;
        rule_map.erase(it);
 
-       _D(YELLOW("Disable Rule%d succeeded"), rule_id);
+       _D(YELLOW("Pause Rule%d"), rule_id);
        return ERR_NONE;
 }
 
@@ -610,20 +694,17 @@ int ctx::rule_manager::check_rule(std::string creator, int rule_id)
 
 bool ctx::rule_manager::is_rule_enabled(int rule_id)
 {
-       std::string q = "SELECT enabled FROM context_trigger_rule WHERE row_id =";
+       std::string q = "SELECT status FROM context_trigger_rule WHERE row_id =";
        q += int_to_string(rule_id);
 
        std::vector<json> record;
        bool ret = db_manager::execute_sync(q.c_str(), &record);
        IF_FAIL_RETURN_TAG(ret, false, _E, "Query enabled by rule id failed");
 
-       int enabled;
-       record[0].get(NULL, "enabled", &enabled);
+       int status;
+       record[0].get(NULL, "status", &status);
 
-       if (enabled == 1)
-               return true;
-       else
-               return false;
+       return (status != 0);
 }
 
 int ctx::rule_manager::get_rule_by_id(std::string creator, int rule_id, ctx::json* request_result)
@@ -657,7 +738,7 @@ int ctx::rule_manager::get_rule_ids(std::string creator, ctx::json* request_resu
 {
        (*request_result) = "{ \"" CT_RULE_ARRAY_ENABLED "\" : [ ] , \"" CT_RULE_ARRAY_DISABLED "\" : [ ] }";
 
-       std::string q = "SELECT row_id, enabled FROM context_trigger_rule WHERE (creator = '";
+       std::string q = "SELECT row_id, status FROM context_trigger_rule WHERE (creator = '";
        q += creator;
        q += "')";
 
@@ -669,14 +750,14 @@ int ctx::rule_manager::get_rule_ids(std::string creator, ctx::json* request_resu
        for (std::vector<json>::iterator vec_pos = record.begin(); vec_pos != vec_end; ++vec_pos) {
                ctx::json elem = *vec_pos;
                std::string id;
-               int enabled;
+               int status;
 
                elem.get(NULL, "row_id", &id);
-               elem.get(NULL, "enabled", &enabled);
+               elem.get(NULL, "status", &status);
 
-               if (enabled == 1) {
+               if (status >= 1) {
                        (*request_result).array_append(NULL, CT_RULE_ARRAY_ENABLED, string_to_int(id));
-               } else if (enabled == 0) {
+               } else if (status == 0) {
                        (*request_result).array_append(NULL, CT_RULE_ARRAY_DISABLED, string_to_int(id));
                }
        }
index a73a149..62c2e5d 100644 (file)
@@ -24,12 +24,11 @@ namespace ctx {
 
        class json;
        class context_trigger;
-       class template_manager;
        class trigger_rule;
 
        class rule_manager {
                public:
-                       rule_manager(ctx::template_manager* tmpl_mgr);
+                       rule_manager();
                        ~rule_manager();
 
                        bool init();
@@ -41,12 +40,14 @@ namespace ctx {
                        int get_rule_ids(std::string creator, ctx::json* request_result);
                        int check_rule(std::string creator, int rule_id);
                        bool is_rule_enabled(int rule_id);
+                       int pause_rule_with_item(std::string& subject);
+                       int pause_rule(int rule_id);
+                       int resume_rule_with_item(std::string& subject);
+                       void handle_rule_of_uninstalled_app(std::string app_id);
 
                        static bool is_uninstalled_package(std::string app_id);
 
                private:
-                       ctx::template_manager* _tmpl_mgr;
-
                        bool reenable_rule(void);
                        int verify_rule(ctx::json& rule, const char* app_id);
                        int64_t get_duplicated_rule_id(std::string creator, ctx::json& rule);
index e5e6500..f90bccf 100644 (file)
@@ -19,6 +19,7 @@
 #include <context_trigger_types_internal.h>
 #include <db_mgr.h>
 #include "../context_mgr_impl.h"
+#include "rule_manager.h"
 #include "template_manager.h"
 
 static std::string int_to_string(int i)
@@ -29,52 +30,84 @@ static std::string int_to_string(int i)
        return str;
 }
 
-ctx::template_manager::template_manager(ctx::context_manager_impl* ctx_mgr)
-: _context_mgr(ctx_mgr)
+ctx::template_manager::template_manager(ctx::context_manager_impl* ctx_mgr, ctx::rule_manager* rule_mgr)
+: _context_mgr(ctx_mgr), _rule_mgr(rule_mgr)
 {
 }
 
 ctx::template_manager::~template_manager()
 {
+       apply_templates();
 }
 
-bool ctx::template_manager::get_fact_definition(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options)
+bool ctx::template_manager::init()
 {
-       return _context_mgr->pop_trigger_item(subject, operation, attributes, options);
+       std::string q = std::string("CREATE TABLE IF NOT EXISTS context_trigger_template ")
+                       + "(name TEXT DEFAULT '' NOT NULL PRIMARY KEY, operation INTEGER DEFAULT 3 NOT NULL, "
+                       + "attributes TEXT DEFAULT '' NOT NULL, options TEXT DEFAULT '' NOT NULL, owner TEXT DEFAULT '' NOT NULL)";
+
+       std::vector<json> record;
+       bool ret = db_manager::execute_sync(q.c_str(), &record);
+       IF_FAIL_RETURN_TAG(ret, false, _E, "Create template table failed");
+
+       // Apply templates
+       apply_templates();
+
+       return true;
 }
 
-void ctx::template_manager::apply_templates(void)
+void ctx::template_manager::apply_templates()
 {
-       // TODO remove templates if needed
        std::string subject;
        int operation;
        ctx::json attributes;
        ctx::json options;
-       std::string q_update;
-       std::string q_insert = "INSERT OR IGNORE INTO context_trigger_template (name, operation, attributes, options) VALUES";
-       int cnt = 0;
+       std::string owner;
+       bool unregister;
+       std::string query;
+       query.clear();
+
+       while(_context_mgr->pop_trigger_item(subject, operation, attributes, options, owner, unregister)) {
+               if (unregister) {
+                       query += remove_template(subject);
+                       _rule_mgr->pause_rule_with_item(subject);
+               } else {
+                       query += add_template(subject, operation, attributes, options, owner);
+                       if (!owner.empty()) {
+                               _rule_mgr->resume_rule_with_item(subject);
+                       }
+               }
+       }
+       IF_FAIL_VOID(!query.empty());
 
-       while (get_fact_definition(subject, operation, attributes, options)) {
-               _D("Subject: %s, Ops: %d", subject.c_str(), operation);
-               _J("Attr", attributes);
-               _J("Opt", options);
+       std::vector<json> record;
+       bool ret = db_manager::execute_sync(query.c_str(), &record);
+       IF_FAIL_VOID_TAG(ret, _E, "Update template db failed");
+}
 
-               q_update += "UPDATE context_trigger_template SET operation=" + int_to_string(operation)
-                       + ", attributes='" + attributes.str() + "', options='" + options.str() + "' WHERE name='" + subject + "';";
+std::string ctx::template_manager::add_template(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options, std::string &owner)
+{
+       _D("[Add template] Subject: %s, Ops: %d, Owner: %s", subject.c_str(), operation, owner.c_str());
+       _J("Attr", attributes);
+       _J("Opt", options);
 
-               q_insert += " ('" + subject + "', " + int_to_string(operation) + ", '" + attributes.str() + "', '" + options.str() + "'),";
-               cnt++;
-       }
-       IF_FAIL_VOID(cnt > 0);
+       std::string query = "UPDATE context_trigger_template SET operation=" + int_to_string(operation)
+                       + ", attributes='" + attributes.str() + "', options='" + options.str() + "', owner='" + owner
+                       + "' WHERE name='" + subject + "'; ";
 
-       q_insert.erase(q_insert.end() - 1, q_insert.end());
-       q_insert += ";";
+       query += "INSERT OR IGNORE INTO context_trigger_template (name, operation, attributes, options, owner) VALUES ('"
+                       + subject + "', " + int_to_string(operation) + ", '" + attributes.str() + "', '" + options.str() + "', '"
+                       + owner + "'); ";
 
-       bool ret = db_manager::execute(1, q_update.c_str(), NULL);
-       IF_FAIL_VOID_TAG(ret, _E, "Update item definition failed");
+       return query;
+}
+
+std::string ctx::template_manager::remove_template(std::string &subject)
+{
+       _D("[Remove template] Subject: %s", subject.c_str());
+       std::string query = "DELETE FROM context_trigger_template WHERE name = '" + subject + "'; ";
 
-       ret = db_manager::execute(2, q_insert.c_str(), NULL);
-       IF_FAIL_VOID_TAG(ret, _E, "Insert item definition failed");
+       return query;
 }
 
 int ctx::template_manager::get_template(std::string &subject, ctx::json* tmpl)
index fb8addc..245db76 100644 (file)
 namespace ctx {
 
        class context_manager_impl;
-
+       class rule_manager;
        class template_manager {
        public:
-               template_manager(ctx::context_manager_impl* ctx_mgr);
+               template_manager(ctx::context_manager_impl* ctx_mgr, ctx::rule_manager* rule_mgr);
                ~template_manager();
 
-               void apply_templates(void);
-               bool get_fact_definition(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options);
+               bool init();
+               void apply_templates();
                int get_template(std::string &subject, ctx::json* tmpl);
 
        private:
                context_manager_impl *_context_mgr;
+               rule_manager *_rule_mgr;
+
+               std::string add_template(std::string &subject, int &operation, ctx::json &attributes, ctx::json &options, std::string &owner);
+               std::string remove_template(std::string &subject);
 
        };      /* class template_manager */
 
index 7e904a1..994fb55 100644 (file)
@@ -17,9 +17,9 @@
 #include <types_internal.h>
 #include <context_trigger_types_internal.h>
 #include "trigger.h"
-#include "rule_manager.h"
 #include "context_monitor.h"
 #include "template_manager.h"
+#include "rule_manager.h"
 
 ctx::context_trigger::context_trigger()
        : rule_mgr(NULL)
@@ -45,14 +45,14 @@ void ctx::context_trigger::release()
 {
        // Release the occupied resources.
        // This function is called from the main thread during the service termination process.
-       _D("Context Trigger Release");
-       delete rule_mgr;
-       rule_mgr = NULL;
-
        _D("Template Manager Release");
        delete tmpl_mgr;
        tmpl_mgr = NULL;
 
+       _D("Rule Manager Release");
+       delete rule_mgr;
+       rule_mgr = NULL;
+
        ctx::context_monitor::destroy();
 }
 
@@ -98,17 +98,25 @@ void ctx::context_trigger::process_request(ctx::request_info* request)
 
 void ctx::context_trigger::process_initialize(ctx::context_manager_impl* mgr)
 {
+       // Context Monitor
        ctx::context_monitor::set_context_manager(mgr);
 
-       tmpl_mgr = new(std::nothrow) template_manager(mgr);
+       // Rule Manager
+       rule_mgr = new(std::nothrow) rule_manager();
+       IF_FAIL_VOID_TAG(rule_mgr, _E, "Memory allocation failed");
+
+       // Template Manager
+       tmpl_mgr = new(std::nothrow) template_manager(mgr, rule_mgr);
        IF_FAIL_VOID_TAG(tmpl_mgr, _E, "Memory allocation failed");
 
-       rule_mgr = new(std::nothrow) rule_manager(tmpl_mgr);
-       IF_FAIL_VOID_TAG(rule_mgr, _E, "Memory allocation failed");
+       // Initialization
+       if (!tmpl_mgr->init()) {
+               _E("Template manager initialization failed");
+               raise(SIGTERM);
+       }
 
-       bool ret = rule_mgr->init();
-       if (!ret) {
-               _E("Context trigger initialization failed.");
+       if (!rule_mgr->init()) {
+               _E("Context trigger initialization failed");
                raise(SIGTERM);
        }
 }
index 8484b39..9d03a40 100644 (file)
@@ -21,8 +21,8 @@
 
 namespace ctx {
 
-       class rule_manager;
        class template_manager;
+       class rule_manager;
        class client_request;
        class context_manager_impl;
        class context_trigger {
index 4134bbe..6bf9f43 100644 (file)
@@ -50,6 +50,11 @@ const char* ctx::request_info::get_app_id()
        return NULL;
 }
 
+const char* ctx::request_info::get_package_id()
+{
+       return NULL;
+}
+
 const char* ctx::request_info::get_client()
 {
        return NULL;
index cc59223..3faeb78 100644 (file)
@@ -37,6 +37,7 @@ namespace ctx {
 
                virtual const credentials* get_credentials();
                virtual const char* get_app_id();
+               virtual const char* get_package_id();
                /* TODO: remove this get_client() */
                virtual const char* get_client();
                virtual bool reply(int error) = 0;