Define new API set for ml-resource control.
Signed-off-by: Jaeyun Jung <jy1210.jung@samsung.com>
*/
int ml_option_get (ml_option_h option, const char *key, void **value);
+/******************
+ * ML INFORMATION *
+ ******************/
+
+/**
+ * @brief A handle of a ml-information instance.
+ * @since_tizen 8.0
+ */
+typedef void *ml_information_h;
+
+/**
+ * @brief A handle of a list of ml-information instance.
+ * @since_tizen 8.0
+ */
+typedef void *ml_information_list_h;
+
/**
* @}
*/
int ml_service_model_delete (const char *name, const unsigned int version);
/**
+ * @brief Adds new information of machine learning resources those contain images, audio samples, binary files, and so on.
+ * @since_tizen 8.0
+ * @remarks If same name is already registered in machine learning service, this returns no error and the list of resource files will be updated.
+ * @remarks %http://tizen.org/privilege/mediastorage is needed if model file is relevant to media storage.
+ * @remarks %http://tizen.org/privilege/externalstorage is needed if model file is relevant to external storage.
+ * @param[in] name The unique name to indicate the resources.
+ * @param[in] path The path to machine learning resources.
+ * @param[in] description Nullable, description for machine learning resources.
+ * @return 0 on success. Otherwise a negative error value.
+ * @retval #ML_ERROR_NONE Successful.
+ * @retval #ML_ERROR_NOT_SUPPORTED Not supported.
+ * @retval #ML_ERROR_PERMISSION_DENIED The application does not have the privilege to access to the storage.
+ * @retval #ML_ERROR_INVALID_PARAMETER Given parameter is invalid.
+ * @retval #ML_ERROR_IO_ERROR The operation of DB or filesystem has failed.
+ *
+ * Here is an example of the usage:
+ * @code
+ * // The machine-learning resource API provides a method to share the data files those can be used for training or inferencing AI model.
+ * // Users may generate preprocessed data file, and add it into machine-learning service.
+ * // Then an application can fetch the data set for retraining an AI model.
+ *
+ * const char *my_resources[3] = {
+ * "/path/to/resources/my_res1.dat",
+ * "/path/to/resources/my_res2.dat"
+ * "/path/to/resources/my_res3.dat"
+ * };
+ *
+ * int status;
+ * unsigned int i, length;
+ * ml_information_list_h resources;
+ * ml_information_h res;
+ * char *path_to_resource;
+ *
+ * // Add resource files with name "my_resource".
+ * for (i = 0; i < 3; i++) {
+ * status = ml_service_resource_add ("my_resource", my_resources[i], "This is my resource data file.");
+ * if (status != ML_ERROR_NONE) {
+ * // Handle error case.
+ * }
+ * }
+ *
+ * // Get the resources with specific name.
+ * status = ml_service_resource_get ("my_resource", &resources);
+ * if (status != ML_ERROR_NONE) {
+ * // Handle error case.
+ * }
+ *
+ * status = ml_information_list_length (resources, &length);
+ * for (i = 0; i < length; i++) {
+ * status = ml_information_list_get (resources, i, &res);
+ * // Get the path of added resources.
+ * status = ml_information_get (res, "path", (void **) &path_to_resource);
+ * }
+ *
+ * // Release the information handle of resources.
+ * status = ml_information_list_destroy (resources);
+ * @endcode
+ */
+int ml_service_resource_add (const char *name, const char *path, const char *description);
+
+/**
+ * @brief Deletes the information of the resources from machine learning service.
+ * @since_tizen 8.0
+ * @remarks This does not remove the resource files from file system.
+ * @param[in] name The unique name to indicate the resources.
+ * @return 0 on success. Otherwise a negative error value.
+ * @retval #ML_ERROR_NONE Successful.
+ * @retval #ML_ERROR_NOT_SUPPORTED Not supported.
+ * @retval #ML_ERROR_INVALID_PARAMETER Given parameter is invalid.
+ * @retval #ML_ERROR_IO_ERROR The operation of DB or filesystem has failed.
+ */
+int ml_service_resource_delete (const char *name);
+
+/**
+ * @brief Gets the information of the resources from machine learning service.
+ * @since_tizen 8.0
+ * @remarks If the function succeeds, the @a res should be released using ml_information_list_destroy().
+ * @param[in] name The unique name to indicate the resources.
+ * @param[out] res The handle of the machine learning resources.
+ * @return 0 on success. Otherwise a negative error value.
+ * @retval #ML_ERROR_NONE Successful.
+ * @retval #ML_ERROR_NOT_SUPPORTED Not supported.
+ * @retval #ML_ERROR_INVALID_PARAMETER Given parameter is invalid.
+ * @retval #ML_ERROR_IO_ERROR The operation of DB or filesystem has failed.
+ * @retval #ML_ERROR_OUT_OF_MEMORY Failed to allocate required memory.
+ */
+int ml_service_resource_get (const char *name, ml_information_list_h *res);
+
+/**
* @}
*/
#ifdef __cplusplus
return ret;
}
+
+/**
+ * @brief Adds new information of machine learning resources.
+ */
+int
+ml_service_resource_add (const char *name, const char *path,
+ const char *description)
+{
+ int ret = ML_ERROR_NONE;
+ g_autoptr (GError) err = NULL;
+
+ check_feature_state (ML_FEATURE_SERVICE);
+
+ if (!name) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "The parameter, 'name' is NULL. It should be a valid string.");
+ }
+
+ ret = _ml_service_check_path (path);
+ if (ret != ML_ERROR_NONE)
+ return ret;
+
+ /**
+ * @todo Check whether the given path is in the app's resource directory.
+ * Implement common function later, see ml_service_model_register().
+ */
+ ret = ml_agent_dbus_interface_resource_add (name, path,
+ description ? description : "", &err);
+ if (ret < 0) {
+ _ml_error_report ("Failed to invoke the method resource_add (%s).",
+ err ? err->message : "Unknown error");
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Deletes the information of the resources from machine learning service.
+ */
+int
+ml_service_resource_delete (const char *name)
+{
+ int ret = ML_ERROR_NONE;
+ g_autoptr (GError) err = NULL;
+
+ check_feature_state (ML_FEATURE_SERVICE);
+
+ if (!name) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "The parameter, 'name' is NULL. It should be a valid string.");
+ }
+
+ ret = ml_agent_dbus_interface_resource_delete (name, &err);
+ if (ret < 0) {
+ _ml_error_report ("Failed to invoke the method resource_delete (%s).",
+ err ? err->message : "Unknown error");
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Gets the information of the resources from machine learning service.
+ */
+int
+ml_service_resource_get (const char *name, ml_information_list_h * res)
+{
+ int ret = ML_ERROR_NONE;
+ ml_info_list_s *_info_list = NULL;
+ g_autofree gchar *res_info = NULL;
+ g_autoptr (GError) err = NULL;
+ guint i, n;
+
+ check_feature_state (ML_FEATURE_SERVICE);
+
+ if (!name) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "The parameter, 'name' is NULL. It should be a valid string.");
+ }
+
+ if (res == NULL) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "The argument for 'res' should not be NULL.");
+ }
+
+ if (*res != NULL) {
+ _ml_logw (WARN_MSG_DPTR_SET_OVER, "ml_information_list_h res = NULL");
+ }
+ *res = NULL;
+
+ ret = ml_agent_dbus_interface_resource_get (name, &res_info, &err);
+ if (ML_ERROR_NONE != ret || !res_info) {
+ _ml_error_report_return (ret,
+ "Failed to invoke the method resource_get (%s).",
+ err ? err->message : "Unknown error");
+ }
+
+ _info_list = g_try_new0 (ml_info_list_s, 1);
+ if (NULL == _info_list) {
+ _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
+ "Failed to allocate memory for ml_information_list_h. Out of memory?");
+ }
+
+ /* Parse json string (res_info). */
+ {
+ g_autoptr (JsonParser) parser = NULL;
+ JsonNode *rnode = NULL;
+ JsonArray *array = NULL;
+
+ parser = json_parser_new ();
+ if (!parser) {
+ _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
+ "Failed to allocate memory for JsonParser. Out of memory?");
+ }
+
+ if (!json_parser_load_from_data (parser, res_info, -1, &err)) {
+ _ml_error_report ("Failed to parse the json string (%s).",
+ err ? err->message : "Unknown error");
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+
+ rnode = json_parser_get_root (parser);
+ if (!rnode) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "Failed to get the root node of json string.");
+ }
+
+ array =
+ (JSON_NODE_HOLDS_ARRAY (rnode) ? json_node_get_array (rnode) : NULL);
+ if (!array) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "Failed to get array from json string.");
+ }
+
+ n = json_array_get_length (array);
+ if (n == 0U) {
+ _ml_error_report_return (ML_ERROR_INVALID_PARAMETER,
+ "Failed to retrieve the length of the json array.");
+ }
+
+ _info_list->info = g_try_new0 (ml_info_s *, n);
+ if (!_info_list->info) {
+ g_free (_info_list);
+ _ml_error_report_return (ML_ERROR_OUT_OF_MEMORY,
+ "Failed to allocate memory for list of ml_information_list_h. Out of memory?");
+ }
+ _info_list->length = n;
+
+ for (i = 0; i < n; i++) {
+ g_autoptr (GList) members = NULL;
+ JsonObject *jobj = NULL;
+ GList *l;
+
+ ret = ml_option_create ((ml_information_h *) (&_info_list->info[i]));
+ if (ret != ML_ERROR_NONE) {
+ _ml_error_report
+ ("Failed to allocate memory for ml_information_list_h. Out of memory?");
+ n = i;
+ goto error;
+ }
+
+ jobj = json_array_get_object_element (array, i);
+ members = json_object_get_members (jobj);
+ for (l = members; l != NULL; l = l->next) {
+ const gchar *key = l->data;
+ const gchar *val = json_object_get_string_member (jobj, key);
+
+ ml_option_set (_info_list->info[i], key, g_strdup (val), g_free);
+ }
+ /** @todo add app_info and fetch it from service-db */
+ }
+ }
+
+ *res = _info_list;
+ return ML_ERROR_NONE;
+
+error:
+ if (_info_list) {
+ for (i = 0; i < n; i++) {
+ if (_info_list->info[i])
+ ml_option_destroy (_info_list->info[i]);
+ }
+
+ g_free (_info_list->info);
+ g_free (_info_list);
+ }
+
+ return ret;
+}
}
/**
+ * @brief Negative testcase of ml-service-resource - add invalid param.
+ */
+TEST (MLServiceResource, addInvalidParam01_n)
+{
+ const gchar *root_path = g_getenv ("MLAPI_SOURCE_ROOT_PATH");
+ g_autofree gchar *test_model = NULL;
+ int ret;
+
+ /* Adding res file into ml-service-agent requires absolute path, ignore this case. */
+ if (root_path == NULL)
+ return;
+
+ test_model = g_build_filename (root_path, "tests", "test_models", "models",
+ "mobilenet_v1_1.0_224_quant.tflite", NULL);
+ ASSERT_TRUE (g_file_test (test_model, G_FILE_TEST_EXISTS));
+
+ ret = ml_service_resource_add (NULL, test_model, "unittest-add-resource");
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
+ * @brief Negative testcase of ml-service-resource - add invalid param.
+ */
+TEST (MLServiceResource, addInvalidParam02_n)
+{
+ int ret;
+
+ ret = ml_service_resource_add ("unittest-res", NULL, "unittest-add-resource");
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
+ * @brief Negative testcase of ml-service-resource - add invalid param.
+ */
+TEST (MLServiceResource, addInvalidParam03_n)
+{
+ const gchar *root_path = g_getenv ("MLAPI_SOURCE_ROOT_PATH");
+ g_autofree gchar *test_model = NULL;
+ int ret;
+
+ /* Adding res file into ml-service-agent requires absolute path, ignore this case. */
+ if (root_path == NULL)
+ return;
+
+ test_model = g_build_filename (root_path, "tests", "test_models", "models",
+ "restest_invalid.tflite", NULL);
+
+ ret = ml_service_resource_add ("unittest-res", test_model, "unittest-add-resource");
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
+ * @brief Negative testcase of ml-service-resource - delete invalid param.
+ */
+TEST (MLServiceResource, deleteInvalidParam01_n)
+{
+ int ret;
+
+ ret = ml_service_resource_delete (NULL);
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
+ * @brief Negative testcase of ml-service-resource - get invalid param.
+ */
+TEST (MLServiceResource, getInvalidParam01_n)
+{
+ int ret;
+ ml_option_h res = NULL;
+
+ ret = ml_service_resource_get (NULL, &res);
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
+ * @brief Negative testcase of ml-service-resource - get invalid param.
+ */
+TEST (MLServiceResource, getInvalidParam02_n)
+{
+ int ret;
+
+ ret = ml_service_resource_get ("unittest-res", NULL);
+ EXPECT_NE (ret, ML_ERROR_NONE);
+}
+
+/**
* @brief Negative test for pipeline. With DBus unconnected.
*/
TEST (MLServiceAgentTestDbusUnconnected, pipeline_n)