Add new apis for multiple response callback 47/135747/45
authorInkyun Kil <inkyun.kil@samsung.com>
Mon, 26 Jun 2017 08:09:40 +0000 (17:09 +0900)
committerjusung son <jusung07.son@samsung.com>
Thu, 3 Aug 2017 00:06:35 +0000 (09:06 +0900)
- 'data_control_map_register_response_cb',
  'data_control_sql_register_response_cb',
  'data_control_map_register_add_bulk_data_response_cb'
  'data_control_sql_register_insert_bulk_data_response_cb'
  couldn't register multiple callback for same provider id.
  This patch is for registering multiple callback for same provider id.

Change-Id: I24190ef238d955e9a07ade38e0f6ecd4be7d271e
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
Signed-off-by: jusung son <jusung07.son@samsung.com>
include/data_control_map.h
include/data_control_sql.h
src/data_control_internal.c
src/data_control_internal.h
src/data_control_map.c
src/data_control_noti.c
src/data_control_provider.c
src/data_control_sql.c

index 4cf96e9..3bf4f28 100755 (executable)
@@ -269,6 +269,7 @@ int data_control_map_get_data_id(data_control_h provider, char **data_id);
  * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
  * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
  * @see data_control_map_unregister_response_cb()
+ * @see data_control_map_bind_response_cb()
  */
 int data_control_map_register_response_cb(data_control_h provider, data_control_map_response_cb *callback, void *user_data);
 
@@ -644,8 +645,13 @@ int data_control_map_add_bulk_data(data_control_h provider, data_control_bulk_da
 
 /**
  * @brief Registers an add bulk data callback for the MAP data control response.
+ *        The application is notified when a data control response is received
+ *        from the @a provider.
  * @since_tizen 3.0
- * @remarks The application is notified when a data control response is received from the @a provider.
+ *
+ * @remarks Only one callback can be registered for each provider id with this
+ *          function. If you call this function multiple times for the same
+ *          provider id, any previously set callback will be overwritten.
  * @param[in] provider The provider handle
  * @param[in] callback The callback function to be called when a response is received
  * @param[in] user_data The user data to be passed to the callback function
@@ -656,6 +662,7 @@ int data_control_map_add_bulk_data(data_control_h provider, data_control_bulk_da
  * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
  * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
  * @see data_control_map_unregister_add_bulk_data_response_cb()
+ * @see data_control_map_bind_add_bulk_data_response_cb()
  */
 int data_control_map_register_add_bulk_data_response_cb(data_control_h provider, data_control_bulk_cb callback, void *user_data);
 
@@ -673,6 +680,120 @@ int data_control_map_register_add_bulk_data_response_cb(data_control_h provider,
  */
 int data_control_map_unregister_add_bulk_data_response_cb(data_control_h provider);
 
+/**
+ * @brief Binds a response callback function to a data control provider handle.
+ *        The application is notified when a data control response is received
+ *        from the @a provider.
+ * @details This function is very similar to
+ *          data_control_map_register_response_cb(), which can register a
+ *          callback for a given provider id. Calling
+ *          data_control_map_register_response_cb() again overwrites the
+ *          callback previously set for the provider id, which means that only
+ *          one callback can be set for a given id.
+ *          data_control_map_bind_response_cb() binds a callback to the handle
+ *          of a provider, which allows registering multiple callbacks for a
+ *          given provider id. To do that, you can create new #data_control_h
+ *          for the same provider id and register callback for the
+ *          #data_control_h.
+ *
+ * @since_tizen 4.0
+ *
+ * @remarks If you call this function multiple times for the same handle, any
+ *          previously set callback will be overwritten.
+ *
+ * @param[in] provider  The provider handle
+ * @param[in] callback  The callback function to be called
+ *                      when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see data_control_map_register_response_cb()
+ * @see data_control_map_unbind_response_cb()
+ */
+int data_control_map_bind_response_cb(data_control_h provider,
+               data_control_map_response_cb *callback, void *user_data);
+
+/**
+ * @brief Unbinds the callback function in the @a provider.
+ * @since_tizen 4.0
+ *
+ * @param[in] provider The provider handle
+ * @return  @c 0 on success,
+ *          otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see data_control_bind_map_response_cb()
+ */
+int data_control_map_unbind_response_cb(data_control_h provider);
+
+/**
+ * @brief Binds the add bulk data callback to the map data control response.
+ * @details This function is very similar to
+ *          data_control_map_register_add_bulk_data_response_cb(), which can
+ *          register a callback for a given provider id. Calling
+ *          data_control_map_register_add_bulk_data_response_cb() again
+ *          overwrites the callback previously set for the provider id, which
+ *          means that only one callback can be set for a given id.
+ *          data_control_map_bind_add_bulk_data_response_cb() binds a
+ *          callback to the handle of a provider, which allows registering
+ *          multiple callbacks for a given provider id. To do that, you can
+ *          create new #data_control_h for the same provider id and register
+ *          callback for the #data_control_h.
+ *
+ * @since_tizen 4.0
+ * @remarks If you call this function multiple times for the same handle,
+ *          any previously set callback will be overwritten.
+ *
+ * @param[in] provider  The provider handle
+ * @param[in] callback  The callback function to be called
+ *                      when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ * @return @c 0 on success,
+ *          otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see data_control_map_register_add_bulk_data_response_cb()
+ * @see data_control_map_unbind_add_bulk_data_response_cb()
+ */
+int data_control_map_bind_add_bulk_data_response_cb(data_control_h provider,
+               data_control_bulk_cb callback, void *user_data);
+
+/**
+ * @brief Unbinds the add bulk data callback in the @a provider.
+ * @since_tizen 4.0
+ *
+ * @param[in] provider The provider handle
+ * @return  @c 0 on success,
+ *          otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see data_control_map_bind_add_bulk_data_response_cb()
+ */
+int data_control_map_unbind_add_bulk_data_response_cb(data_control_h provider);
+
+/**
+ * @brief Gets the handle ID for @a provider.
+ * @since_tizen 4.0
+ *
+ * @remarks @a handle_id is generated internally and it is unique for each
+ *          handle. This function can be used in callbacks to know for which
+ *          handle the callback was called.
+ *
+ * @param[in]  provider  The provider handle
+ * @param[out] handle_id The handle ID for @a provider
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_map_get_handle_id(data_control_h provider, int *handle_id);
+
 
 /**
 * @}
index cc41718..36e1429 100755 (executable)
@@ -323,6 +323,7 @@ int data_control_sql_get_data_id(data_control_h provider, char **data_id);
  * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
  *
  * @see data_control_sql_unregister_response_cb()
+ * @see data_control_sql_bind_response_cb()
  */
 int data_control_sql_register_response_cb(data_control_h provider, data_control_sql_response_cb *callback, void *user_data);
 
@@ -741,9 +742,13 @@ int data_control_sql_insert_bulk_data(data_control_h provider, data_control_bulk
 
 /**
  * @brief Registers an insert bulk data callback for the SQL data control response.
+ *        The application is notified when a data control response is
+ *        received from the @a provider.
  * @since_tizen 3.0
  *
- * remarks The application is notified when a data control response is received from the @a provider.
+ * @remarks Only one callback can be registered for each provider id with this
+ *          function. If you call this function multiple times for the same
+ *          provider id, any previously set callback will be overwritten.
  *
  * @param[in] provider The provider handle
  * @param[in] callback The callback function to be called when a response is received
@@ -758,6 +763,7 @@ int data_control_sql_insert_bulk_data(data_control_h provider, data_control_bulk
  * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
  *
  * @see  data_control_sql_unregister_insert_bulk_data_response_cb()
+ * @see  data_control_sql_bind_insert_bulk_data_response_cb()
  */
 int data_control_sql_register_insert_bulk_data_response_cb(data_control_h provider, data_control_bulk_cb callback, void *user_data);
 
@@ -779,6 +785,128 @@ int data_control_sql_unregister_insert_bulk_data_response_cb(data_control_h prov
 
 
 /**
+ * @brief Binds a callback function to the SQL data control response.
+ * @details This function is very similar to
+ *          data_control_sql_register_response_cb(), which can register a
+ *          callback for a given provider id. Calling
+ *          data_control_sql_register_response_cb() again overwrites the
+ *          callback previously set for the provider id, which means that only
+ *          one callback can be set for a given id.
+ *          data_control_sql_bind_response_cb() binds a callback to the handle
+ *          of a provider, which allows registering multiple callbacks for a
+ *          given provider id. To do that, you can create new #data_control_h
+ *          for the same provider id and register callback for the
+ *          #data_control_h.
+ *
+ * @since_tizen 4.0
+ * @remarks You can bind a callback function to @a provider. If you call this
+ *          function multiple times for the same handle, any previously set
+ *          callback will be overwritten.
+ *
+ * @param[in] provider  The provider handle
+ * @param[in] callback  The callback function to be called
+ *                      when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @see data_control_sql_register_response_cb()
+ * @see data_control_sql_unbind_response_cb()
+ */
+int data_control_sql_bind_response_cb(data_control_h provider,
+               data_control_sql_response_cb *callback, void *user_data);
+
+/**
+ * @brief Unbinds the callback function in the @a provider.
+ * @since_tizen 4.0
+*
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see data_control_sql_bind_response_cb()
+ */
+int data_control_sql_unbind_response_cb(data_control_h provider);
+
+/**
+ * @brief Binds the insert bulk data callback to the SQL data control response.
+ * @details This function is very similar to
+ *          data_control_sql_register_insert_bulk_data_response_cb(), which can
+ *          register a callback for a given provider id. Calling
+ *          data_control_sql_register_insert_bulk_data_response_cb() again
+ *          overwrites the callback previously set for the provider id, which
+ *          means that only one callback can be set for a given id.
+ *          data_control_sql_bind_insert_bulk_data_response_cb() binds a
+ *          callback to the handle of a provider, which allows registering
+ *          multiple callbacks for a given provider id. To do that, you can
+ *          create new #data_control_h for the same provider id and register
+ *          callback for the #data_control_h.
+ *
+ * @since_tizen 4.0
+ * @remarks You can bind a callback function to @a provider. If you call this
+ *          function multiple times for the same handle, any previously set
+ *          callback will be overwritten.
+ *
+ * @param[in] provider  The provider handle
+ * @param[in] callback  The callback function to be called
+ *                      when a response is received
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ *
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_IO_ERROR I/O error
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ *
+ * @see  data_control_sql_register_insert_bulk_data_response_cb()
+ * @see  data_control_sql_unbind_insert_bulk_data_response_cb()
+ */
+int data_control_sql_bind_insert_bulk_data_response_cb(data_control_h provider,
+               data_control_bulk_cb callback, void *user_data);
+
+/**
+ * @brief Unbinds the insert bulk data callback in the @a provider.
+ * @since_tizen 4.0
+ *
+ * @param[in] provider The provider handle
+ *
+ * @return @c 0 on success,
+ *          otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see  data_control_sql_unbind_insert_bulk_data_response_cb()
+ */
+int data_control_sql_unbind_insert_bulk_data_response_cb(
+               data_control_h provider);
+
+/**
+ * @brief Gets the handle ID for @a provider.
+ * @since_tizen 4.0
+ *
+ * @remarks @a handle_id is generated internally and it is unique for each
+ *          handle. This function can be used in callbacks to know for which
+ *          handle the callback was called.
+ *
+ * @param[in]  provider  The provider handle
+ * @param[out] handle_id The handle ID for @a provider
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #DATA_CONTROL_ERROR_NONE Successful
+ * @retval #DATA_CONTROL_ERROR_INVALID_PARAMETER Invalid parameter
+ */
+int data_control_sql_get_handle_id(data_control_h provider, int *handle_id);
+
+
+/**
 * @}
 */
 
index 2c78d78..8d0d31f 100755 (executable)
@@ -69,12 +69,8 @@ struct datacontrol_cert_info {
 };
 
 typedef struct {
-       char *provider_id;
-       char *app_id;
-       char *data_id;
-       int map_access_info;
-       int sql_access_info;
-       GList *request_info_list;
+       struct __response_cb_s *parent_info;
+       unsigned int id;
        data_control_map_response_cb *map_response_cb;
        data_control_sql_response_cb *sql_response_cb;
        data_control_bulk_cb map_bulk_add_cb;
@@ -83,11 +79,21 @@ typedef struct {
        void *map_bulk_user_data;
        void *sql_user_data;
        void *sql_bulk_user_data;
+} __cb_info_s;
+
+typedef struct {
+       char *provider_id;
+       char *app_id;
+       char *data_id;
+       int map_access_info;
+       int sql_access_info;
+       GList *request_info_list;
+       __cb_info_s *registered_cb;
 } __response_cb_s;
 
 static GHashTable *__response_table = NULL;
 static GHashTable *__socket_pair_hash = NULL;
-
+static GHashTable *__bound_cb_hash = NULL;
 
 static GHashTable *__checked_provider_hash;
 static GHashTable *__checked_consumer_hash;
@@ -97,7 +103,7 @@ static GDBusConnection *_gdbus_conn = NULL;
 /* 100 milliseconds */
 const struct timespec TRY_SLEEP_TIME = { 0, 100 * 1000 * 1000 };
 
-int __datacontrol_get_provider_id(void)
+int __get_unique_handle_id(void)
 {
        static int id = 0;
        g_atomic_int_inc(&id);
@@ -155,11 +161,22 @@ static void __insert_hash(GHashTable *hash, const char *key,
        g_hash_table_insert(hash, strdup(key), cert_info);
 }
 
-static void __free_data(gpointer data)
+static void __free_cb_info(gpointer data)
 {
-       if (data) {
-               g_free(data);
-               data = NULL;
+       __cb_info_s *cb_info = (__cb_info_s *)data;
+       data_control_map_response_cb *mc;
+       data_control_sql_response_cb *sc;
+
+       if (cb_info) {
+               mc = (data_control_map_response_cb *)cb_info->map_response_cb;
+               sc = (data_control_sql_response_cb *)cb_info->sql_response_cb;
+
+               if (mc)
+                       free(mc);
+               if (sc)
+                       free(sc);
+
+               free(cb_info);
        }
 }
 
@@ -173,12 +190,10 @@ static void __free_response_cb(gpointer data)
                        free(dc->data_id);
                if (dc->app_id)
                        free(dc->app_id);
-               if (dc->map_response_cb)
-                       free(dc->map_response_cb);
-               if (dc->sql_response_cb)
-                       free(dc->sql_response_cb);
                if (dc->request_info_list)
                        g_list_free_full(dc->request_info_list, free);
+               if (dc->registered_cb)
+                       __free_cb_info(dc->registered_cb);
 
                free(dc);
        }
@@ -187,7 +202,9 @@ static void __free_response_cb(gpointer data)
 static void __initialize(void)
 {
        __response_table = g_hash_table_new_full(g_str_hash, g_str_equal,
-                       __free_data, __free_response_cb);
+                       NULL, __free_response_cb);
+       __bound_cb_hash = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, NULL, __free_cb_info);
 }
 
 int __consumer_request_compare_cb(gconstpointer a, gconstpointer b)
@@ -219,6 +236,20 @@ static void __remove_request_info(int request_id, __response_cb_s *dc)
        }
 }
 
+static gboolean __find_bound_cb_func(gpointer key, gpointer value,
+               gpointer user_data)
+{
+       __cb_info_s *temp_value = (__cb_info_s *)value;
+       __response_cb_s *parent_info = (__response_cb_s *)temp_value->parent_info;
+
+       if (user_data == parent_info) {
+               _LOGI("Has response_cb for %s", parent_info->provider_id);
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 static char **__map_get_value_list(int fd, int *value_count)
 {
        char **value_list = NULL;
@@ -638,34 +669,25 @@ out:
        return retval;
 }
 
-static void __sql_call_cb(const char *provider_id, int request_id,
-               datacontrol_request_type type, const char *data_id,
-               bool provider_result, const char *error, long long insert_rowid,
-               resultset_cursor *cursor, data_control_bulk_result_data_h bulk_results,
-               void *data)
+static void __sql_call_user_cb(data_control_h provider, int request_id,
+               datacontrol_request_type type, bool provider_result, const char *error,
+               long long insert_rowid, resultset_cursor *cursor,
+               data_control_bulk_result_data_h bulk_results, __cb_info_s *cb_info)
 {
-       _LOGI("__sql_call_cb, dataID !!!: %s", data_id);
-
-       __response_cb_s *_dc = NULL;
+       _LOGI("request ID: %d", request_id);
        data_control_sql_response_cb *sql_callback = NULL;
        data_control_bulk_cb bulk_callback = NULL;
 
-       _dc = (__response_cb_s *)data;
-       sql_callback = (data_control_sql_response_cb *)_dc->sql_response_cb;
-       bulk_callback = (data_control_bulk_cb)_dc->sql_bulk_insert_cb;
-
-       data_control_h provider = NULL;
-       _create_data_control_h(&provider);
-
-       _set_provider_id(provider, provider_id);
-       _set_data_id(provider, data_id);
+       sql_callback = (data_control_sql_response_cb *)cb_info->sql_response_cb;
+       bulk_callback = (data_control_bulk_cb)cb_info->sql_bulk_insert_cb;
 
        switch (type) {
        case DATACONTROL_TYPE_SQL_BULK_INSERT:
                _LOGI("BULK INSERT");
                if (bulk_callback != NULL)
-                       bulk_callback(request_id, provider, bulk_results, provider_result,
-                                       error, _dc->sql_bulk_user_data);
+                       bulk_callback(request_id, provider, bulk_results,
+                                       provider_result, error,
+                                       cb_info->sql_bulk_user_data);
                else
                        _LOGI("No registered sql_callback function");
 
@@ -675,7 +697,7 @@ static void __sql_call_cb(const char *provider_id, int request_id,
                if (sql_callback != NULL && sql_callback->select_cb != NULL)
                        sql_callback->select_cb(request_id, provider,
                                        (result_set_cursor) cursor, provider_result,
-                                       error, _dc->sql_user_data);
+                                       error, cb_info->sql_user_data);
                else
                        _LOGI("No registered sql_callback function");
 
@@ -684,7 +706,7 @@ static void __sql_call_cb(const char *provider_id, int request_id,
                _LOGI("INSERT row_id: %lld", insert_rowid);
                if (sql_callback != NULL && sql_callback->insert_cb != NULL)
                        sql_callback->insert_cb(request_id, provider, insert_rowid,
-                                       provider_result, error, _dc->sql_user_data);
+                                       provider_result, error, cb_info->sql_user_data);
                else
                        _LOGI("No registered sql_callback function");
 
@@ -693,7 +715,7 @@ static void __sql_call_cb(const char *provider_id, int request_id,
                _LOGI("UPDATE");
                if (sql_callback != NULL && sql_callback->update_cb != NULL)
                        sql_callback->update_cb(request_id, provider, provider_result,
-                                       error, _dc->sql_user_data);
+                                       error, cb_info->sql_user_data);
                else
                        _LOGI("No registered sql_callback function");
                break;
@@ -701,7 +723,7 @@ static void __sql_call_cb(const char *provider_id, int request_id,
                _LOGI("DELETE");
                if (sql_callback != NULL && sql_callback->delete_cb != NULL)
                        sql_callback->delete_cb(request_id, provider, provider_result,
-                                       error, _dc->sql_user_data);
+                                       error, cb_info->sql_user_data);
                else
                        _LOGI("No registered sql_callback function");
                break;
@@ -709,24 +731,20 @@ static void __sql_call_cb(const char *provider_id, int request_id,
                break;
        }
 
-       _destroy_data_control_h(provider);
 }
 
-static void __map_call_cb(const char *provider_id, int request_id,
-       datacontrol_request_type type, const char *data_id, bool provider_result,
-       const char *error, char **result_value_list, int result_value_count,
-       data_control_bulk_result_data_h bulk_results,
-       void *data)
+static void __sql_call_cb(const char *provider_id, int request_id,
+               datacontrol_request_type type, const char *data_id,
+               int handle_id, bool provider_result, const char *error,
+               long long insert_rowid, resultset_cursor *cursor,
+               data_control_bulk_result_data_h bulk_results, void *data)
 {
-       _LOGI("__map_call_cb, dataID: %s", data_id);
+       _LOGI("handle ID: %d, data_id : %s", handle_id, data_id);
 
        __response_cb_s *_dc = NULL;
-       data_control_map_response_cb *map_callback = NULL;
-       data_control_bulk_cb bulk_callback = NULL;
+       __cb_info_s *cb_info = NULL;
 
        _dc = (__response_cb_s *)data;
-       map_callback = (data_control_map_response_cb *)_dc->map_response_cb;
-       bulk_callback = (data_control_bulk_cb)_dc->map_bulk_add_cb;
 
        data_control_h provider = NULL;
        _create_data_control_h(&provider);
@@ -734,12 +752,45 @@ static void __map_call_cb(const char *provider_id, int request_id,
        _set_provider_id(provider, provider_id);
        _set_data_id(provider, data_id);
 
+       provider->handle_id = handle_id;
+
+       cb_info = _dc->registered_cb;
+       if (cb_info)
+               __sql_call_user_cb(provider, request_id, type, provider_result, error,
+                               insert_rowid, cursor,  bulk_results, cb_info);
+
+       cb_info = g_hash_table_lookup(__bound_cb_hash,
+                       GINT_TO_POINTER(handle_id));
+       if (cb_info) {
+               __sql_call_user_cb(provider, request_id, type, provider_result, error,
+                               insert_rowid, cursor,  bulk_results, cb_info);
+
+               _LOGI("call response callback function for handle_id : %d",
+                               handle_id);
+       }
+
+       _destroy_data_control_h(provider, false);
+}
+
+static void __map_call_user_cb(data_control_h provider, int request_id,
+       datacontrol_request_type type, bool provider_result, const char *error,
+       char **result_value_list, int result_value_count,
+       data_control_bulk_result_data_h bulk_results, __cb_info_s *cb_info)
+{
+       _LOGI("request ID: %d", request_id);
+       data_control_map_response_cb *map_callback = NULL;
+       data_control_bulk_cb bulk_callback = NULL;
+
+       map_callback = (data_control_map_response_cb *)cb_info->map_response_cb;
+       bulk_callback = (data_control_bulk_cb)cb_info->map_bulk_add_cb;
+
        switch (type) {
        case DATACONTROL_TYPE_MAP_BULK_ADD:
                _LOGI("ADD VALUE");
                if (bulk_callback != NULL)
-                       bulk_callback(request_id, provider, bulk_results, provider_result,
-                                       error, _dc->map_bulk_user_data);
+                       bulk_callback(request_id, provider, bulk_results,
+                                       provider_result, error,
+                                       cb_info->map_bulk_user_data);
                else
                        _LOGI("No registered map_callback function");
 
@@ -747,9 +798,9 @@ static void __map_call_cb(const char *provider_id, int request_id,
        case DATACONTROL_TYPE_MAP_GET:
                _LOGI("GET VALUE");
                if (map_callback != NULL && map_callback->get_cb != NULL)
-                       map_callback->get_cb(request_id, provider, result_value_list,
-                                       result_value_count, provider_result, error,
-                                       _dc->map_user_data);
+                       map_callback->get_cb(request_id, provider,
+                                       result_value_list, result_value_count,
+                                       provider_result, error, cb_info->map_user_data);
                else
                        _LOGI("No registered map_callback function");
 
@@ -758,7 +809,7 @@ static void __map_call_cb(const char *provider_id, int request_id,
                _LOGI("SET VALUE");
                if (map_callback != NULL && map_callback->set_cb != NULL)
                        map_callback->set_cb(request_id, provider, provider_result,
-                                       error, _dc->map_user_data);
+                                       error, cb_info->map_user_data);
                else
                        _LOGI("No registered map_callback function");
 
@@ -766,8 +817,8 @@ static void __map_call_cb(const char *provider_id, int request_id,
        case DATACONTROL_TYPE_MAP_ADD:
                _LOGI("ADD VALUE");
                if (map_callback != NULL && map_callback->add_cb != NULL)
-                       map_callback->add_cb(request_id, provider, provider_result, error,
-                                       _dc->map_user_data);
+                       map_callback->add_cb(request_id, provider, provider_result,
+                                       error, cb_info->map_user_data);
                else
                        _LOGI("No registered map_callback function");
 
@@ -775,8 +826,8 @@ static void __map_call_cb(const char *provider_id, int request_id,
        case DATACONTROL_TYPE_MAP_REMOVE:
                _LOGI("REMOVE VALUE");
                if (map_callback != NULL && map_callback->remove_cb != NULL)
-                       map_callback->remove_cb(request_id, provider, provider_result,
-                                       error, _dc->map_user_data);
+                       map_callback->remove_cb(request_id, provider,
+                                       provider_result, error, cb_info->map_user_data);
                else
                        _LOGI("No registered map_callback function");
 
@@ -784,8 +835,45 @@ static void __map_call_cb(const char *provider_id, int request_id,
        default:
                break;
        }
+}
+
+static void __map_call_cb(const char *provider_id, int request_id,
+       datacontrol_request_type type, const char *data_id, int handle_id,
+       bool provider_result, const char *error, char **result_value_list,
+       int result_value_count, data_control_bulk_result_data_h bulk_results,
+       void *data)
+{
+       _LOGI("handle ID: %d, data_id : %s", handle_id, data_id);
+
+       __response_cb_s *_dc = NULL;
+       __cb_info_s *cb_info = NULL;
+
+       _dc = (__response_cb_s *)data;
+
+       data_control_h provider = NULL;
+       _create_data_control_h(&provider);
+
+       _set_provider_id(provider, provider_id);
+       _set_data_id(provider, data_id);
+
+       provider->handle_id = handle_id;
+
+       cb_info = _dc->registered_cb;
+       if (cb_info)
+               __map_call_user_cb(provider, request_id, type, provider_result, error,
+                               result_value_list, result_value_count, bulk_results, cb_info);
+
+       cb_info = g_hash_table_lookup(__bound_cb_hash,
+                       GINT_TO_POINTER(handle_id));
+       if (cb_info) {
+               __map_call_user_cb(provider, request_id, type, provider_result, error,
+                               result_value_list, result_value_count, bulk_results, cb_info);
+
+               _LOGI("call response callback function for handle_id : %d",
+                               handle_id);
+       }
 
-       _destroy_data_control_h(provider);
+       _destroy_data_control_h(provider, false);
 }
 
 static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
@@ -795,6 +883,7 @@ static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
        const char **result_list = NULL;
        const char *provider_id = NULL;
        const char *data_id = NULL;
+       const char *handle_id_char = NULL;
        const char *error_message = NULL;
        int result_list_len = 0;
        int provider_result = 0;
@@ -804,11 +893,12 @@ static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
        const char *request_code = NULL;
        int request_type = 0;
        int request_id = -1;
+       int handle_id = -1;
        long long insert_rowid = -1;
        data_control_bulk_result_data_h bulk_results = NULL;
        resultset_cursor *cursor = NULL;
 
-       _LOGI("__handle_cb, request_type: %d", request_type);
+       _LOGI("request_type: %d", request_type);
 
        if (!b) {
                _LOGE("the bundle returned from datacontrol-provider-service is null");
@@ -861,6 +951,15 @@ static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
        }
 
+       handle_id_char = bundle_get_val(b, OSP_K_DATACONTROL_HANDLE_ID);
+       if (!handle_id_char) {
+               _LOGE("Invalid Bundle: handle_id is null");
+               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+       } else {
+               handle_id = atoi(handle_id_char);
+               _LOGI("handle ID: %d", handle_id);
+       }
+
        request_code = bundle_get_val(b, OSP_K_DATACONTROL_REQUEST_TYPE);
        if (!request_code) {
                _LOGE("Invalid Bundle: data-control request type is null");
@@ -948,6 +1047,7 @@ static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
                                request_id,
                                request_type,
                                data_id,
+                               handle_id,
                                provider_result,
                                error_message,
                                value_list,
@@ -968,6 +1068,7 @@ static int __handle_cb(int fd, bundle *b, __response_cb_s *data)
                                request_id,
                                request_type,
                                data_id,
+                               handle_id,
                                provider_result,
                                error_message,
                                insert_rowid,
@@ -1001,7 +1102,7 @@ static gboolean __recv_message(GIOChannel *channel,
        GList *itr;
        datacontrol_consumer_request_info *request_info;
 
-       _LOGI("__recv_message: ...from %d:%s%s%s%s\n", fd,
+       _LOGI("from %d:%s%s%s%s\n", fd,
                        (cond & G_IO_ERR) ? " ERR" : "",
                        (cond & G_IO_HUP) ? " HUP" : "",
                        (cond & G_IO_IN)  ? " IN"  : "",
@@ -1022,7 +1123,7 @@ static gboolean __recv_message(GIOChannel *channel,
                        goto error;
                }
 
-               _LOGI("__recv_message: ...from %d: %d bytes\n", fd, nbytes);
+               _LOGI("from %d: %d bytes\n", fd, nbytes);
                if (nbytes > 0 && nbytes < MAX_REQUEST_ARGUMENT_SIZE) {
                        buf = (char *) calloc(nbytes + 1, sizeof(char));
                        if (buf == NULL) {
@@ -1053,12 +1154,8 @@ static gboolean __recv_message(GIOChannel *channel,
                                request_id = atoi(p);
                        }
 
-                       _LOGI("Request ID: %d", request_id);
-
-
-                       _LOGI("__recv_message: ...from %d: OK\n", fd);
-                       _LOGI("__recv_message: ...caller appid %s: OK\n",
-                                       bundle_get_val(kb, AUL_K_CALLER_APPID));
+                       _LOGI("Request ID: %d, fd %d, caller appid %s",
+                               request_id, fd, bundle_get_val(kb, AUL_K_CALLER_APPID));
 
                        if (data) {
                                if (__handle_cb(fd, kb, data) != DATA_CONTROL_ERROR_NONE)
@@ -1095,15 +1192,14 @@ error:
                        if (request_info->type >= DATACONTROL_TYPE_MAP_GET &&
                                        request_info->type <= DATACONTROL_TYPE_MAP_BULK_ADD) {
                                __map_call_cb(_dc->provider_id, request_info->request_id,
-                                               request_info->type, _dc->data_id, false,
+                                               request_info->type, _dc->data_id, -1, false,
                                                "provider IO Error", NULL, 0, NULL, data);
-
                        }
 
                        if (request_info->type >= DATACONTROL_TYPE_SQL_SELECT &&
                                        request_info->type <= DATACONTROL_TYPE_SQL_BULK_INSERT) {
                                __sql_call_cb(_dc->provider_id, request_info->request_id,
-                                               request_info->type, _dc->data_id, false,
+                                               request_info->type, _dc->data_id, -1, false,
                                                "provider IO Error", -1, NULL, NULL, data);
                        }
 
@@ -1137,7 +1233,7 @@ static int __datacontrol_send_async(int sockfd, bundle *kb, void *extra_data,
        bundle_raw *encode_data = NULL;
        int encode_datalen = 0;
 
-       LOGD("send async ~~~");
+       LOGD("send async");
 
        bundle_encode_raw(kb, &kb_data, &datalen);
        if (kb_data == NULL) {
@@ -1371,7 +1467,7 @@ void _socket_info_free(gpointer socket)
 
        if (socket_info != NULL) {
                if (socket_info->gio_read != NULL) {
-                       _LOGE("shutdown socketpair !!!! %d ", socket_info->socket_fd);
+                       _LOGE("shutdown socketpair %d ", socket_info->socket_fd);
                        g_io_channel_shutdown(socket_info->gio_read, TRUE, &error);
                        if (error) {
                                _LOGE("g_io_channel_shutdown error : %s", error->message);
@@ -1514,8 +1610,8 @@ int _request_provider(data_control_h provider, datacontrol_request_type type,
 
        app_id = _dc_returned->app_id;
        datacontrol_consumer_request_info *request_info =
-               (datacontrol_consumer_request_info *)calloc(
-                               sizeof(datacontrol_consumer_request_info), 1);
+               (datacontrol_consumer_request_info *)calloc(1,
+                               sizeof(datacontrol_consumer_request_info));
        if (request_info == NULL) {
                _LOGE("out of memory.");
                return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
@@ -1575,7 +1671,7 @@ int _request_provider(data_control_h provider, datacontrol_request_type type,
                                        strdup(provider->provider_id), socket_info);
                }
 
-               _LOGI("send data from consumer !!!");
+               _LOGI("send data from consumer");
                ret = __datacontrol_send_async(socket_info->socket_fd, send_data,
                                extra_data, type, NULL);
                if (ret != DATA_CONTROL_ERROR_NONE)
@@ -1590,15 +1686,83 @@ int _request_provider(data_control_h provider, datacontrol_request_type type,
        return ret;
 }
 
+int __create_response_s(data_control_h provider, char *app_id,
+               __response_cb_s **response_cb_s)
+{
+       int ret = DATA_CONTROL_ERROR_NONE;
+       __response_cb_s *_dc_temp;
+
+       _dc_temp = (__response_cb_s *)calloc(1, sizeof(__response_cb_s));
+       if (!_dc_temp) {
+               _LOGE("unable to create a temporary data control");
+               ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+               goto EXCEPTION;
+       }
+
+       _dc_temp->provider_id = strdup(provider->provider_id);
+       if (!_dc_temp->provider_id) {
+               _LOGE("unable to assign provider_id to data control: %d", errno);
+               ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+               goto EXCEPTION;
+       }
+
+       _dc_temp->data_id = strdup(provider->data_id);
+       if (!_dc_temp->data_id) {
+               _LOGE("unable to assign data_id to data control: %d", errno);
+               ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+               goto EXCEPTION;
+       }
+
+       _dc_temp->app_id = strdup(app_id);
+       if (!_dc_temp->app_id) {
+               _LOGE("unable to assign app_id to data control: %d", errno);
+               ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+               goto EXCEPTION;
+       }
+
+       *response_cb_s = _dc_temp;
+       return DATA_CONTROL_ERROR_NONE;
+
+EXCEPTION:
+       __free_response_cb((gpointer)_dc_temp);
+       return ret;
+}
+
+int __create_cb_info_s(data_control_h provider, datacontrol_request_type type,
+               __cb_info_s **cb_info_s)
+{
+       int ret = DATA_CONTROL_ERROR_NONE;
+       __cb_info_s *cb_info;
+
+       cb_info = (__cb_info_s *)calloc(1, sizeof(__cb_info_s));
+       if (cb_info == NULL) {
+               _LOGE("unable to create a cb_info");
+               ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
+               goto EXCEPTION;
+       }
+
+       cb_info->id = provider->handle_id;
+
+       *cb_info_s = cb_info;
+       return DATA_CONTROL_ERROR_NONE;
+
+EXCEPTION:
+       __free_cb_info((gpointer)cb_info);
+       return ret;
+}
+
 int _register_response_cb(data_control_h provider, void *response_cb,
-               datacontrol_request_type type,  void *user_data)
+               bool is_bind, datacontrol_request_type type,  void *user_data)
 {
-       int ret;
+       int ret = DATA_CONTROL_ERROR_NONE;
        char *app_id = NULL;
        char *access = NULL;
        int access_info = ACCESS_INFO_NONE;
        char *data_type;
-       __response_cb_s *_dc_temp;
+       __response_cb_s *response_cb_s = NULL;
+       __response_cb_s *reserved_response_cb_s = NULL;
+       __cb_info_s *cb_info = NULL;
+       __cb_info_s *reserved_cb_info = NULL;
 
        if (!response_cb || !provider || !provider->provider_id || !provider->data_id)
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
@@ -1630,151 +1794,179 @@ int _register_response_cb(data_control_h provider, void *response_cb,
        else if (strcasecmp(access, "readwrite") == 0)
                access_info = ACCESS_INFO_READ_WRITE;
 
-       _LOGI("data control provider appid = %s", app_id);
+       if (access)
+               free(access);
 
-       _dc_temp = g_hash_table_lookup(__response_table, provider->provider_id);
+       _LOGI("data control provider appid = %s, handle_id = %d, is_bind = %d\n",
+                       app_id, provider->handle_id, is_bind);
 
-       if (_dc_temp == NULL) {
-               _dc_temp = (__response_cb_s *)calloc(1, sizeof(__response_cb_s));
-               if (!_dc_temp) {
-                       _LOGE("unable to create a temporary data control");
-                       ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                       goto EXCEPTION;
-               }
+       response_cb_s = (__response_cb_s *)g_hash_table_lookup(__response_table,
+                       provider->provider_id);
+       if (response_cb_s == NULL) {
+               ret = __create_response_s(provider, app_id, &reserved_response_cb_s);
+               if (ret != DATA_CONTROL_ERROR_NONE)
+                       goto out;
 
-               _dc_temp->provider_id = strdup(provider->provider_id);
-               if (!_dc_temp->provider_id) {
-                       _LOGE("unable to assign provider_id to data control: %d", errno);
-                       ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                       goto EXCEPTION;
-               }
+               g_hash_table_insert(__response_table,
+                               reserved_response_cb_s->provider_id, (gpointer)reserved_response_cb_s);
+               response_cb_s = reserved_response_cb_s;
+       }
 
-               _dc_temp->data_id = strdup(provider->data_id);
-               if (!_dc_temp->data_id) {
-                       _LOGE("unable to assign data_id to data control: %d", errno);
-                       ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                       goto EXCEPTION;
+       if (is_bind) {
+               cb_info = g_hash_table_lookup(__bound_cb_hash,
+                               GINT_TO_POINTER(provider->handle_id));
+               if (cb_info == NULL) {
+                       ret = __create_cb_info_s(provider, type, &reserved_cb_info);
+                       if (ret != DATA_CONTROL_ERROR_NONE) {
+                               goto out;
+                       }
+                       g_hash_table_insert(__bound_cb_hash,
+                                       GINT_TO_POINTER(reserved_cb_info->id), (gpointer)reserved_cb_info);
+                       cb_info = reserved_cb_info;
                }
+               cb_info->parent_info = (struct __response_cb_s *)response_cb_s;
 
-               _dc_temp->app_id = strdup(app_id);
-               if (!_dc_temp->app_id) {
-                       _LOGE("unable to assign app_id to data control: %d", errno);
-                       ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                       goto EXCEPTION;
+       } else {
+               if (response_cb_s->registered_cb == NULL) {
+                       ret = __create_cb_info_s(provider, type, &reserved_cb_info);
+                       if (ret != DATA_CONTROL_ERROR_NONE) {
+                               goto out;
+                       }
+                       response_cb_s->registered_cb = reserved_cb_info;
                }
-
-               g_hash_table_insert(__response_table,
-                               strdup(provider->provider_id), _dc_temp);
+               cb_info = response_cb_s->registered_cb;
        }
 
-       if (type >= DATACONTROL_TYPE_MAP_GET &&
-                       type < DATACONTROL_TYPE_MAP_BULK_ADD) {
-               if (_dc_temp->map_response_cb == NULL) {
-                       _dc_temp->map_response_cb =
-                               (data_control_map_response_cb *)calloc(
-                                               1, sizeof(data_control_map_response_cb));
-                       if (!_dc_temp->map_response_cb) {
-                               _LOGE("unable to create a response_cb of temporary");
+       if (type == DATACONTROL_TYPE_MAP_GET) {
+               if (cb_info->map_response_cb == NULL) {
+                       cb_info->map_response_cb = (data_control_map_response_cb *)
+                               calloc(1, sizeof(data_control_map_response_cb));
+                       if (cb_info->map_response_cb == NULL) {
                                ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                               goto EXCEPTION;
+                               goto out;
                        }
                }
-
-               memcpy(_dc_temp->map_response_cb, response_cb,
+               memcpy(cb_info->map_response_cb, response_cb,
                                sizeof(data_control_map_response_cb));
-               _dc_temp->map_access_info = access_info;
-               _dc_temp->map_user_data = user_data;
+               cb_info->map_user_data = user_data;
+               response_cb_s->map_access_info = access_info;
+
        } else if (type == DATACONTROL_TYPE_MAP_BULK_ADD) {
-               _dc_temp->map_bulk_add_cb = (data_control_bulk_cb)response_cb;
-               _dc_temp->map_access_info = access_info;
-               _dc_temp->map_bulk_user_data = user_data;
-       } else if (type >= DATACONTROL_TYPE_SQL_SELECT &&
-                       type < DATACONTROL_TYPE_SQL_BULK_INSERT) {
-               if (_dc_temp->sql_response_cb == NULL) {
-                       _dc_temp->sql_response_cb =
-                               (data_control_sql_response_cb *)calloc(
-                                               1, sizeof(data_control_sql_response_cb));
-                       if (!_dc_temp->sql_response_cb) {
-                               _LOGE("unable to create a response_cb of temporary");
+               cb_info->map_bulk_add_cb = (data_control_bulk_cb)response_cb;
+               cb_info->map_bulk_user_data = user_data;
+               response_cb_s->map_access_info = access_info;
+
+       } else if (type == DATACONTROL_TYPE_SQL_SELECT) {
+               if (cb_info->sql_response_cb == NULL) {
+                       cb_info->sql_response_cb = (data_control_sql_response_cb *)
+                               calloc(1, sizeof(data_control_sql_response_cb));
+                       if (cb_info->sql_response_cb == NULL) {
                                ret = DATA_CONTROL_ERROR_OUT_OF_MEMORY;
-                               goto EXCEPTION;
+                               goto out;
                        }
                }
-
-               memcpy(_dc_temp->sql_response_cb, response_cb,
+               memcpy(cb_info->sql_response_cb, response_cb,
                                sizeof(data_control_sql_response_cb));
+               cb_info->sql_user_data = user_data;
+               response_cb_s->sql_access_info = access_info;
 
-               _dc_temp->sql_access_info = access_info;
-               _dc_temp->sql_user_data = user_data;
        } else if (type == DATACONTROL_TYPE_SQL_BULK_INSERT) {
-               _dc_temp->sql_bulk_insert_cb =  (data_control_bulk_cb)response_cb;
-               _dc_temp->sql_access_info = access_info;
-               _dc_temp->sql_bulk_user_data = user_data;
+               cb_info->sql_bulk_insert_cb =  (data_control_bulk_cb)response_cb;
+               cb_info->sql_bulk_user_data = user_data;
+               response_cb_s->sql_access_info = access_info;
        }
 
-       ret = DATA_CONTROL_ERROR_NONE;
+out:
+       if (ret != DATA_CONTROL_ERROR_NONE)
+               _unregister_response_cb(provider, is_bind, type);
 
-       /* LCOV_EXCL_START */
-EXCEPTION:
-       if (access)
-               free(access);
        if (app_id)
                free(app_id);
-       if (ret != DATA_CONTROL_ERROR_NONE && _dc_temp) {
-               __free_response_cb((gpointer)_dc_temp);
-       }
-
        return ret;
-       /* LCOV_EXCL_STOP */
 }
 
-int _unregister_response_cb(data_control_h provider,
+int _unregister_response_cb(data_control_h provider, bool is_bind,
                datacontrol_request_type type)
 {
+       __cb_info_s *cb_info;
+       gpointer has_bound_cb;
+
        if (provider == NULL)
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
 
+       _LOGI("provider handle_id : %d[TYPE:%d][is_bind:%d",
+                       provider->handle_id, type, is_bind);
+
        __response_cb_s *_dc_temp = g_hash_table_lookup(__response_table,
                        provider->provider_id);
-       if (_dc_temp == NULL)
+       if (_dc_temp == NULL) {
+               _LOGE("Not found for provider id : %s", provider->provider_id);
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (is_bind) {
+               cb_info = g_hash_table_lookup(__bound_cb_hash,
+                               GINT_TO_POINTER(provider->handle_id));
+       } else {
+               cb_info = _dc_temp->registered_cb;
+       }
+
+       if (cb_info == NULL) {
+               _LOGI("Not registered callback for handle id : %d",
+                               provider->handle_id);
+               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+       }
 
        switch (type) {
        case DATACONTROL_TYPE_MAP_GET:
        case DATACONTROL_TYPE_MAP_ADD:
        case DATACONTROL_TYPE_MAP_SET:
        case DATACONTROL_TYPE_MAP_REMOVE:
-               if (_dc_temp->map_response_cb) {
-                       free(_dc_temp->map_response_cb);
-                       _dc_temp->map_response_cb = NULL;
+               if (cb_info->map_response_cb) {
+                       free(cb_info->map_response_cb);
+                       cb_info->map_response_cb = NULL;
                }
                break;
        case DATACONTROL_TYPE_MAP_BULK_ADD:
-               _dc_temp->map_bulk_add_cb = NULL;
+               cb_info->map_bulk_add_cb = NULL;
                break;
        case DATACONTROL_TYPE_SQL_SELECT:
        case DATACONTROL_TYPE_SQL_INSERT:
        case DATACONTROL_TYPE_SQL_UPDATE:
        case DATACONTROL_TYPE_SQL_DELETE:
-               if (_dc_temp->sql_response_cb) {
-                       free(_dc_temp->sql_response_cb);
-                       _dc_temp->sql_response_cb = NULL;
+               if (cb_info->sql_response_cb) {
+                       free(cb_info->sql_response_cb);
+                       cb_info->sql_response_cb = NULL;
                }
                break;
        case DATACONTROL_TYPE_SQL_BULK_INSERT:
-               _dc_temp->sql_bulk_insert_cb = NULL;;
+               cb_info->sql_bulk_insert_cb = NULL;
                break;
        default:
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
        }
 
-       if (!_dc_temp->map_response_cb &&
-                       !_dc_temp->sql_response_cb &&
-                       !_dc_temp->map_bulk_add_cb &&
-                       !_dc_temp->sql_bulk_insert_cb) {
+       if (!cb_info->map_response_cb &&
+                       !cb_info->sql_response_cb &&
+                       !cb_info->map_bulk_add_cb &&
+                       !cb_info->sql_bulk_insert_cb) {
+
+               if (is_bind) {
+                       g_hash_table_remove(__bound_cb_hash,
+                                       GINT_TO_POINTER(provider->handle_id));
+               } else {
+                       __free_cb_info((gpointer)_dc_temp->registered_cb);
+                       _dc_temp->registered_cb = NULL;
+               }
+
+               has_bound_cb = g_hash_table_find(__bound_cb_hash,
+                               (GHRFunc)__find_bound_cb_func, (gpointer)_dc_temp);
 
-               g_hash_table_remove(__response_table, provider->provider_id);
-               g_hash_table_remove(__socket_pair_hash, provider->provider_id);
+               if (has_bound_cb == NULL && _dc_temp->registered_cb == NULL) {
+                       g_hash_table_remove(__response_table, provider->provider_id);
+                       g_hash_table_remove(__socket_pair_hash, provider->provider_id);
+                       _LOGI("All of registered callback was removed");
+               }
        }
 
        return DATA_CONTROL_ERROR_NONE;
@@ -1831,12 +2023,12 @@ char *_get_encoded_path(data_control_h provider, char *consumer_appid)
 
        snprintf(full_path, full_path_len, "%s%s",
                        DATA_CONTROL_DBUS_PATH_PREFIX, encoded_path);
+       _LOGI("full path : %s ", full_path);
 out:
        if (path)
                free(path);
        if (encoded_path)
                free(encoded_path);
-       _LOGI("full path : %s ", full_path);
        return full_path;
 }
 
@@ -2066,21 +2258,39 @@ int _create_data_control_h(data_control_h *provider)
        if (request == NULL)
                return DATA_CONTROL_ERROR_OUT_OF_MEMORY;
 
+       request->handle_id = __get_unique_handle_id();
+
        *provider = request;
 
        return DATA_CONTROL_ERROR_NONE;
 }
 
-int _destroy_data_control_h(data_control_h provider)
+int _destroy_data_control_h(data_control_h provider, bool remove_bound_cb)
 {
        if (provider == NULL)
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
 
-       if (provider->provider_id != NULL)
+       if (remove_bound_cb) {
+               __cb_info_s *cb_info = g_hash_table_lookup(__bound_cb_hash,
+                               GINT_TO_POINTER(provider->handle_id));
+               if (cb_info) {
+                       _LOGI("Found for handle id : %d", provider->handle_id);
+                       g_hash_table_remove(__bound_cb_hash,
+                                       GINT_TO_POINTER(provider->handle_id));
+               }
+       }
+
+       provider->handle_id = 0;
+
+       if (provider->provider_id != NULL) {
                free(provider->provider_id);
+               provider->provider_id = NULL;
+       }
 
-       if (provider->data_id != NULL)
+       if (provider->data_id != NULL) {
                free(provider->data_id);
+               provider->data_id = NULL;
+       }
 
        free(provider);
        return DATA_CONTROL_ERROR_NONE;
@@ -2149,3 +2359,13 @@ int _get_data_id(data_control_h provider, char **data_id)
 
        return DATA_CONTROL_ERROR_NONE;
 }
+
+int _get_handle_id(data_control_h provider, int *handle_id)
+{
+       if (provider == NULL || handle_id == NULL)
+               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+
+       *handle_id = provider->handle_id;
+
+       return DATA_CONTROL_ERROR_NONE;
+}
index c77540e..b4a342b 100755 (executable)
@@ -41,6 +41,7 @@
 
 #define MAX_LEN_DATACONTROL_REQ_TYPE  8
 #define MAX_LEN_DATACONTROL_COLUMN_COUNT  8
+#define MAX_LEN_DATACONTROL_HANDLE_ID  32
 
 #define OSP_K_LAUNCH_TYPE   "__OSP_LAUNCH_TYPE__"
 #define OSP_K_ARG           "__OSP_ARGS__"
@@ -52,6 +53,7 @@
 #define OSP_K_CALLER_TYPE   "__OSP_CALLER_TYPE__"
 #define OSP_K_DATACONTROL_UNIQUE_NAME  "__OSP_DATACONTROL_UNIQUE_NAME__"
 #define OSP_K_DATA_CHANGED_CALLBACK_ID    "__OSP_DATA_CHANGED_CALLBACK_ID__"
+#define OSP_K_DATACONTROL_HANDLE_ID            "__OSP_DATACONTROL_HANDLE_ID__"
 
 #define DATACONTROL_SELECT_STATEMENT   "DATACONTROL_SELECT_STATEMENT"
 
@@ -152,6 +154,7 @@ typedef struct datacontrol_socket {
 } datacontrol_socket_info;
 
 struct data_control_s {
+       unsigned int handle_id;
        char *provider_id;
        char *data_id;
 };
@@ -180,16 +183,17 @@ int _check_cert(const char *provider_id, bool is_map,
                const char *consumer_appid);
 
 int _create_data_control_h(data_control_h *provider);
-int _destroy_data_control_h(data_control_h provider);
+int _destroy_data_control_h(data_control_h provider, bool remove_bound_cb);
 int _set_provider_id(data_control_h provider, const char *provider_id);
 int _get_provider_id(data_control_h provider, char **provider_id);
 int _set_data_id(data_control_h provider, const char *data_id);
 int _get_data_id(data_control_h provider, char **data_id);
+int _get_handle_id(data_control_h provider, int *handle_id);
 
 int _datacontrol_create_request_id(void);
 int _register_response_cb(data_control_h provider, void *response_cb,
-               datacontrol_request_type type, void *user_data);
-int _unregister_response_cb(data_control_h provider,
+               bool is_bind, datacontrol_request_type type, void *user_data);
+int _unregister_response_cb(data_control_h provider, bool is_bind,
                datacontrol_request_type);
 int _request_provider(data_control_h provider, datacontrol_request_type type,
                bundle *request_data, void *extra_data, int request_id);
index 9b07959..2d12cf8 100755 (executable)
@@ -33,7 +33,7 @@ EXPORT_API int data_control_map_create(data_control_h *provider)
 
 EXPORT_API int data_control_map_destroy(data_control_h provider)
 {
-       return _destroy_data_control_h(provider);
+       return _destroy_data_control_h(provider, true);
 }
 
 EXPORT_API int data_control_map_set_provider_id(data_control_h provider,
@@ -60,16 +60,22 @@ EXPORT_API int data_control_map_get_data_id(data_control_h provider,
        return _get_data_id(provider, data_id);
 }
 
+EXPORT_API int data_control_map_get_handle_id(data_control_h provider,
+               int *handle_id)
+{
+       return _get_handle_id(provider, handle_id);
+}
+
 EXPORT_API int data_control_map_register_response_cb(data_control_h provider,
                data_control_map_response_cb *callback, void *user_data)
 {
        return _register_response_cb(provider, (void *)callback,
-                       DATACONTROL_TYPE_MAP_GET, user_data);
+                       false, DATACONTROL_TYPE_MAP_GET, user_data);
 }
 
 EXPORT_API int data_control_map_unregister_response_cb(data_control_h provider)
 {
-       return _unregister_response_cb(provider, DATACONTROL_TYPE_MAP_GET);
+       return _unregister_response_cb(provider, false, DATACONTROL_TYPE_MAP_GET);
 }
 
 EXPORT_API int data_control_map_register_add_bulk_data_response_cb(
@@ -78,13 +84,42 @@ EXPORT_API int data_control_map_register_add_bulk_data_response_cb(
                void *user_data)
 {
        return _register_response_cb(provider, (void *)callback,
-                       DATACONTROL_TYPE_MAP_BULK_ADD, user_data);
+                       false, DATACONTROL_TYPE_MAP_BULK_ADD, user_data);
 }
 
 EXPORT_API int data_control_map_unregister_add_bulk_data_response_cb(
                data_control_h provider)
 {
-       return _unregister_response_cb(provider, DATACONTROL_TYPE_MAP_BULK_ADD);
+       return _unregister_response_cb(provider, false,
+                       DATACONTROL_TYPE_MAP_BULK_ADD);
+}
+
+EXPORT_API int data_control_map_bind_response_cb(data_control_h provider,
+               data_control_map_response_cb *callback, void *user_data)
+{
+       return _register_response_cb(provider, (void *)callback,
+                       true, DATACONTROL_TYPE_MAP_GET, user_data);
+}
+
+EXPORT_API int data_control_map_unbind_response_cb(data_control_h provider)
+{
+       return _unregister_response_cb(provider, true, DATACONTROL_TYPE_MAP_GET);
+}
+
+EXPORT_API int data_control_map_bind_add_bulk_data_response_cb(
+               data_control_h provider,
+               data_control_bulk_cb callback,
+               void *user_data)
+{
+       return _register_response_cb(provider, (void *)callback,
+                       true, DATACONTROL_TYPE_MAP_BULK_ADD, user_data);
+}
+
+EXPORT_API int data_control_map_unbind_add_bulk_data_response_cb(
+               data_control_h provider)
+{
+       return _unregister_response_cb(provider, true,
+                       DATACONTROL_TYPE_MAP_BULK_ADD);
 }
 
 EXPORT_API int data_control_map_get(data_control_h provider,
@@ -117,6 +152,7 @@ EXPORT_API int data_control_map_get_with_page(data_control_h provider,
        const char *arg_list[4];
        char page_no_str[32];
        char count_per_page_str[32];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = {0, };
        int reqId;
 
        if (provider == NULL || provider->provider_id == NULL ||
@@ -151,6 +187,9 @@ EXPORT_API int data_control_map_get_with_page(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
        arg_list[1] = key;
@@ -193,6 +232,7 @@ EXPORT_API int data_control_map_set(data_control_h provider, const char *key,
        unsigned int arg_size;
        bundle *b;
        const char *arg_list[4];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = {0, };
        int reqId;
 
        if (provider == NULL || provider->provider_id == NULL ||
@@ -229,6 +269,9 @@ EXPORT_API int data_control_map_set(data_control_h provider, const char *key,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
        arg_list[1] = key;
@@ -255,6 +298,7 @@ EXPORT_API int data_control_map_add(data_control_h provider,
        unsigned int arg_size;
        bundle *b;
        const char *arg_list[3];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = {0, };
        int reqId;
 
        if (provider == NULL || provider->provider_id == NULL ||
@@ -290,6 +334,9 @@ EXPORT_API int data_control_map_add(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
        arg_list[1] = key;
@@ -315,6 +362,7 @@ EXPORT_API int data_control_map_remove(data_control_h provider,
        unsigned int arg_size;
        bundle *b;
        const char *arg_list[3];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = {0, };
        int reqId;
 
        if (provider == NULL || provider->provider_id == NULL ||
@@ -350,6 +398,9 @@ EXPORT_API int data_control_map_remove(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
        arg_list[1] = key;
@@ -376,6 +427,7 @@ EXPORT_API int data_control_map_add_bulk_data(data_control_h provider,
        bundle *b;
        bundle *data;
        const char *arg_list[3];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = {0, };
        int count;
        int i;
 
@@ -418,6 +470,10 @@ EXPORT_API int data_control_map_add_bulk_data(data_control_h provider,
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
 
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
+
        arg_list[0] = provider->data_id;
 
        bundle_add_str_array(b, OSP_K_ARG, arg_list, 1);
index f259f25..a4157da 100755 (executable)
@@ -140,7 +140,7 @@ static void __noti_process(GVariant *parameters)
                                        provider_info->provider_id, provider_info->data_id);
                }
                bundle_free(noti_data);
-               _destroy_data_control_h(provider);
+               _destroy_data_control_h(provider, false);
 
        } else {
                _LOGE("data_control_data_change_cb is null");
@@ -172,7 +172,7 @@ static void __call_result_callback(int callback_id, int callback_result)
                                        callback_id,
                                        result_cb_info->user_data);
 
-                       _destroy_data_control_h(provider);
+                       _destroy_data_control_h(provider, false);
                } else {
                        _LOGE("data_control_add_callback_result_cb is null");
                }
index f2ea2ae..ee86306 100755 (executable)
@@ -634,6 +634,7 @@ static bundle *__set_result(bundle *b, datacontrol_request_type type, void *data
        const char *data_id;
        const char *request_id;
        const char *caller_appid;
+       const char *caller_handle_id;
        const char *list[3];
        const char *page_num = bundle_get_val(b, RESULT_PAGE_NUMBER);
        const char *count_per_page = bundle_get_val(b, MAX_COUNT_PER_PAGE);
@@ -662,6 +663,10 @@ static bundle *__set_result(bundle *b, datacontrol_request_type type, void *data
        request_id = bundle_get_val(b, OSP_K_REQUEST_ID);
        bundle_add_str(res, OSP_K_REQUEST_ID, request_id);
 
+       /* Set the caller data_control handle id */
+       caller_handle_id = bundle_get_val(b, OSP_K_DATACONTROL_HANDLE_ID);
+       bundle_add_str(res, OSP_K_DATACONTROL_HANDLE_ID, caller_handle_id);
+
        caller_appid = bundle_get_val(b, AUL_K_CALLER_APPID);
        bundle_add_str(res, AUL_K_CALLER_APPID, caller_appid);
 
index 956f00b..5c79b14 100755 (executable)
@@ -33,7 +33,7 @@ EXPORT_API int data_control_sql_create(data_control_h *provider)
 
 EXPORT_API int data_control_sql_destroy(data_control_h provider)
 {
-       return _destroy_data_control_h(provider);
+       return _destroy_data_control_h(provider, true);
 }
 
 EXPORT_API int data_control_sql_set_provider_id(data_control_h provider,
@@ -60,16 +60,23 @@ EXPORT_API int data_control_sql_get_data_id(data_control_h provider,
        return _get_data_id(provider, data_id);
 }
 
+EXPORT_API int data_control_sql_get_handle_id(data_control_h provider,
+               int *handle_id)
+{
+       return _get_handle_id(provider, handle_id);
+}
+
 EXPORT_API int data_control_sql_register_response_cb(data_control_h provider,
                data_control_sql_response_cb *callback, void *user_data)
 {
        return _register_response_cb(provider, (void *)callback,
-                       DATACONTROL_TYPE_SQL_SELECT, user_data);
+                       false, DATACONTROL_TYPE_SQL_SELECT, user_data);
 }
 
 EXPORT_API int data_control_sql_unregister_response_cb(data_control_h provider)
 {
-       return _unregister_response_cb(provider, DATACONTROL_TYPE_SQL_SELECT);
+       return _unregister_response_cb(provider, false,
+                       DATACONTROL_TYPE_SQL_SELECT);
 }
 
 EXPORT_API int data_control_sql_register_insert_bulk_data_response_cb(
@@ -77,12 +84,40 @@ EXPORT_API int data_control_sql_register_insert_bulk_data_response_cb(
                data_control_bulk_cb callback, void *user_data)
 {
        return _register_response_cb(provider, (void *)callback,
-                       DATACONTROL_TYPE_SQL_BULK_INSERT, user_data);
+                       false, DATACONTROL_TYPE_SQL_BULK_INSERT, user_data);
 }
 
 EXPORT_API int data_control_sql_unregister_insert_bulk_data_response_cb(data_control_h provider)
 {
-       return _unregister_response_cb(provider, DATACONTROL_TYPE_SQL_BULK_INSERT);
+       return _unregister_response_cb(provider, false,
+                       DATACONTROL_TYPE_SQL_BULK_INSERT);
+}
+
+EXPORT_API int data_control_sql_bind_response_cb(data_control_h provider,
+               data_control_sql_response_cb *callback, void *user_data)
+{
+       return _register_response_cb(provider, (void *)callback,
+                       true, DATACONTROL_TYPE_SQL_SELECT, user_data);
+}
+
+EXPORT_API int data_control_sql_unbind_response_cb(data_control_h provider)
+{
+       return _unregister_response_cb(provider, true,
+                       DATACONTROL_TYPE_SQL_SELECT);
+}
+
+EXPORT_API int data_control_sql_bind_insert_bulk_data_response_cb(
+               data_control_h provider,
+               data_control_bulk_cb callback, void *user_data)
+{
+       return _register_response_cb(provider, (void *)callback,
+                       true, DATACONTROL_TYPE_SQL_BULK_INSERT, user_data);
+}
+
+EXPORT_API int data_control_sql_unbind_insert_bulk_data_response_cb(data_control_h provider)
+{
+       return _unregister_response_cb(provider, true,
+                       DATACONTROL_TYPE_SQL_BULK_INSERT);
 }
 
 EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider,
@@ -93,6 +128,7 @@ EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider,
        const char *arg_list[2];
        bundle *b;
        bundle *data;
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = { 0, };
        int count;
        int i;
 
@@ -136,6 +172,9 @@ EXPORT_API int data_control_sql_insert_bulk_data(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
        bundle_add_str_array(b, OSP_K_ARG, arg_list, 1);
@@ -158,6 +197,7 @@ EXPORT_API int data_control_sql_insert(data_control_h provider,
        const char *arg_list[2];
        bundle *b;
        char insert_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = { 0, };
        int count;
 
        if (provider == NULL || provider->provider_id == NULL ||
@@ -190,6 +230,9 @@ EXPORT_API int data_control_sql_insert(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        count = bundle_get_count((bundle *)insert_data);
        retval = snprintf(insert_column_count, MAX_LEN_DATACONTROL_COLUMN_COUNT, "%d", count);
@@ -220,6 +263,7 @@ EXPORT_API int data_control_sql_delete(data_control_h provider,
 {
        int retval;
        const char *arg_list[2];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = { 0, };
        int reqId;
        bundle *b;
 
@@ -245,6 +289,9 @@ EXPORT_API int data_control_sql_delete(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id;
 
@@ -286,6 +333,7 @@ EXPORT_API int data_control_sql_select_with_page(data_control_h provider,
        const char **arg_list;
        int i;
        char select_column_count[MAX_LEN_DATACONTROL_COLUMN_COUNT] = {0, };
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = { 0, };
        int select_col;
        int reqId;
 
@@ -318,6 +366,9 @@ EXPORT_API int data_control_sql_select_with_page(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        retval = snprintf(page, 32, "%d", page_number);
        if (retval < 0) {
@@ -398,6 +449,7 @@ EXPORT_API int data_control_sql_update(data_control_h provider,
        long long arg_size = 0;
        bundle *b;
        const char *arg_list[4];
+       char handle_id[MAX_LEN_DATACONTROL_HANDLE_ID] = { 0, };
 
        if (provider == NULL || provider->provider_id == NULL ||
                        provider->data_id == NULL ||
@@ -430,6 +482,9 @@ EXPORT_API int data_control_sql_update(data_control_h provider,
 
        bundle_add_str(b, OSP_K_DATACONTROL_PROVIDER, provider->provider_id);
        bundle_add_str(b, OSP_K_DATACONTROL_DATA, provider->data_id);
+       snprintf(handle_id, MAX_LEN_DATACONTROL_HANDLE_ID, "%u",
+                       provider->handle_id);
+       bundle_add_str(b, OSP_K_DATACONTROL_HANDLE_ID, handle_id);
 
        arg_list[0] = provider->data_id; /* list(0): data ID */
        arg_list[1] = where;