From: Somin Kim Date: Thu, 21 Jan 2016 05:08:15 +0000 (+0900) Subject: Modified to support custom item X-Git-Tag: submit/tizen/20160314.020719~1^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6b9f73a6401e1414b47f142a2eec30aac94acfbe;p=platform%2Fcore%2Fcontext%2Fcontext-service.git Modified to support custom item Change-Id: I7bce0422916ae89749a41ea5586cebb5c14d490d Signed-off-by: Somin Kim --- diff --git a/src/access_control/peer_creds.cpp b/src/access_control/peer_creds.cpp index a4a74dc..c8641bc 100644 --- a/src/access_control/peer_creds.cpp +++ b/src/access_control/peer_creds.cpp @@ -17,11 +17,13 @@ #include #include #include +#include #include #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); diff --git a/src/access_control/peer_creds.h b/src/access_control/peer_creds.h index d122ec8..7889987 100644 --- a/src/access_control/peer_creds.h +++ b/src/access_control/peer_creds.h @@ -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(); }; diff --git a/src/client_request.cpp b/src/client_request.cpp index 2dd8a14..e164d6d 100644 --- a/src/client_request.cpp +++ b/src/client_request.cpp @@ -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) diff --git a/src/client_request.h b/src/client_request.h index 1f60690..6df5da7 100644 --- a/src/client_request.h +++ b/src/client_request.h @@ -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); diff --git a/src/context_mgr_impl.cpp b/src/context_mgr_impl.cpp index d48d837..d6ef171 100644 --- a/src/context_mgr_impl.cpp +++ b/src/context_mgr_impl.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include "server.h" @@ -30,14 +31,25 @@ #include #include #include +#include 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_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; +} diff --git a/src/context_mgr_impl.h b/src/context_mgr_impl.h index 5281595..a9fbb54 100644 --- a/src/context_mgr_impl.h +++ b/src/context_mgr_impl.h @@ -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 */ diff --git a/src/context_trigger/context_monitor.cpp b/src/context_trigger/context_monitor.cpp index d70b20f..576ee8c 100644 --- a/src/context_trigger/context_monitor.cpp +++ b/src/context_trigger/context_monitor.cpp @@ -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; diff --git a/src/context_trigger/rule.cpp b/src/context_trigger/rule.cpp index 5c05f60..5328f42 100644 --- a/src/context_trigger/rule.cpp +++ b/src/context_trigger/rule.cpp @@ -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(data); - rule_mgr->disable_rule(*rule_id); - rule_mgr->remove_rule(*rule_id); + std::string* app_id = static_cast(data); + rule_mgr->handle_rule_of_uninstalled_app(*app_id); return FALSE; } diff --git a/src/context_trigger/rule_manager.cpp b/src/context_trigger/rule_manager.cpp index f76c03f..cb8f579 100644 --- a/src/context_trigger/rule_manager.cpp +++ b/src/context_trigger/rule_manager.cpp @@ -21,7 +21,6 @@ #include #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 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::iterator vec_end = record.end(); + for (std::vector::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 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::iterator vec_end = record.end(); + for (std::vector::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 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::iterator vec_end = record.end(); for (std::vector::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 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"); @@ -560,6 +613,37 @@ int ctx::rule_manager::disable_rule(int rule_id) bool ret; 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(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 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"); @@ -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 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 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::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)); } } diff --git a/src/context_trigger/rule_manager.h b/src/context_trigger/rule_manager.h index a73a149..62c2e5d 100644 --- a/src/context_trigger/rule_manager.h +++ b/src/context_trigger/rule_manager.h @@ -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); diff --git a/src/context_trigger/template_manager.cpp b/src/context_trigger/template_manager.cpp index e5e6500..f90bccf 100644 --- a/src/context_trigger/template_manager.cpp +++ b/src/context_trigger/template_manager.cpp @@ -19,6 +19,7 @@ #include #include #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 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 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) diff --git a/src/context_trigger/template_manager.h b/src/context_trigger/template_manager.h index fb8addc..245db76 100644 --- a/src/context_trigger/template_manager.h +++ b/src/context_trigger/template_manager.h @@ -22,18 +22,22 @@ 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 */ diff --git a/src/context_trigger/trigger.cpp b/src/context_trigger/trigger.cpp index 7e904a1..994fb55 100644 --- a/src/context_trigger/trigger.cpp +++ b/src/context_trigger/trigger.cpp @@ -17,9 +17,9 @@ #include #include #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); } } diff --git a/src/context_trigger/trigger.h b/src/context_trigger/trigger.h index 8484b39..9d03a40 100644 --- a/src/context_trigger/trigger.h +++ b/src/context_trigger/trigger.h @@ -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 { diff --git a/src/request.cpp b/src/request.cpp index 4134bbe..6bf9f43 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -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; diff --git a/src/request.h b/src/request.h index cc59223..3faeb78 100644 --- a/src/request.h +++ b/src/request.h @@ -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;