Skip to content

Commit

Permalink
[Remote-service] Add a path to save the model
Browse files Browse the repository at this point in the history
Add a path to save the received model file to the ml-option.

Signed-off-by: gichan2-jang <gichan2.jang@samsung.com>
  • Loading branch information
gichan-jang committed Nov 17, 2023
1 parent e20f6a6 commit b97fe98
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 34 deletions.
1 change: 1 addition & 0 deletions c/include/nnstreamer-tizen-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ char * ml_api_get_version_string (void);
* @retval #ML_ERROR_OUT_OF_MEMORY Failed to allocate required memory.
* @retval #ML_ERROR_STREAMS_PIPE Failed to launch the pipeline.
* @retval #ML_ERROR_TRY_AGAIN The pipeline is not ready yet.
* @retval #ML_ERROR_PERMISSION_DENIED The application does not have the privilege to access to the storage.
*/
int ml_service_remote_create (ml_option_h option, ml_service_event_cb cb, void *user_data, ml_service_h *handle);

Expand Down
106 changes: 72 additions & 34 deletions c/src/ml-api-service-remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/

#include <glib.h>
#include <glib/gstdio.h>
#include <gst/gst.h>
#include <gst/gstbuffer.h>
#include <gst/app/app.h>
Expand Down Expand Up @@ -62,6 +63,7 @@ typedef struct

ml_service_event_cb event_cb;
void *user_data;
gchar *path; /** A path to save the received model file */
} _ml_remote_service_s;

/**
Expand Down Expand Up @@ -232,15 +234,13 @@ curl_mem_write_cb (void *data, size_t size, size_t nmemb, void *clientp)
*/
static gboolean
_mlrs_model_register (gchar * service_key, nns_edge_data_h data_h,
void *data, nns_size_t data_len)
void *data, nns_size_t data_len, const gchar * dir_path)
{
guint version = -1;
gchar *description = NULL;
gchar *name = NULL;
gchar *current_dir = g_get_current_dir ();
gchar *dir_path = NULL;
gchar *model_path = NULL;
gchar *activate = NULL;
g_autofree gchar *description = NULL;
g_autofree gchar *name = NULL;
g_autofree gchar *activate = NULL;
g_autofree gchar *model_path = NULL;
gboolean active_bool = TRUE;
GError *error = NULL;
gboolean ret = TRUE;
Expand All @@ -251,28 +251,18 @@ _mlrs_model_register (gchar * service_key, nns_edge_data_h data_h,
|| NNS_EDGE_ERROR_NONE != nns_edge_data_get_info (data_h, "activate",
&activate)) {
_ml_loge ("Failed to get info from data handle.");
ret = FALSE;
goto error;
return FALSE;
}

active_bool = _mlrs_parse_activate (activate);

dir_path = g_build_path ("/", current_dir, service_key, NULL);
if (g_mkdir_with_parents (dir_path, 0755) < 0) {
_ml_loge ("Failed to create directory %s., error: %s", dir_path,
g_strerror (errno));
ret = FALSE;
goto error;
}

model_path = g_build_path ("/", dir_path, name, NULL);

if (!g_file_set_contents (model_path, (char *) data, data_len, &error)) {
_ml_loge ("Failed to write data to file: %s",
error ? error->message : "unknown error");
g_clear_error (&error);
ret = FALSE;
goto error;
return FALSE;
}

/**
Expand All @@ -283,17 +273,43 @@ _mlrs_model_register (gchar * service_key, nns_edge_data_h data_h,
_ml_loge ("Failed to register model, service ket:%s", service_key);
ret = FALSE;
}
error:
g_free (current_dir);
g_free (dir_path);
g_free (activate);
g_free (model_path);
g_free (description);
g_free (name);

return ret;
}

/**
* @brief Get path to save the model given from remote sender.
* @note The caller is responsible for freeing the returned data using g_free().
*/
static gchar *
_mlrs_get_model_dir_path (_ml_remote_service_s * remote_s,
const gchar * service_key)
{
g_autofree gchar *dir_path = NULL;

if (remote_s->path) {
dir_path = g_strdup (remote_s->path);
} else {
g_autofree gchar *current_dir = g_get_current_dir ();

dir_path = g_build_path ("/", current_dir, service_key, NULL);
if (g_mkdir_with_parents (dir_path, 0755) < 0) {
_ml_loge ("Failed to create directory %s., error: %s", dir_path,
g_strerror (errno));
return NULL;
}
}

if (!g_file_test (dir_path, G_FILE_TEST_IS_DIR)) {
_ml_loge
("The given param, dir path = \"%s\" is invalid or the dir is not found or accessible.",
dir_path);
return NULL;
}

return g_steal_pointer (&dir_path);
}

/**
* @brief Get data from gievn uri
*/
Expand Down Expand Up @@ -371,13 +387,22 @@ _mlrs_process_remote_service (nns_edge_data_h data_h, void *user_data)
case ML_REMOTE_SERVICE_TYPE_MODEL_URI:
{
GByteArray *array = g_byte_array_new ();
g_autofree gchar *dir_path = NULL;

if (!_mlrs_get_data_from_uri ((gchar *) data, array)) {
g_byte_array_free (array, TRUE);
_ml_error_report_return (NNS_EDGE_ERROR_IO,
"Failed to get data from uri: %s.", (gchar *) data);
}
if (_mlrs_model_register (service_key, data_h, array->data, array->len)) {

dir_path = _mlrs_get_model_dir_path (remote_s, service_key);
if (!dir_path) {
_ml_error_report_return (NNS_EDGE_ERROR_UNKNOWN,
"Failed to get model directory path.");
}

if (_mlrs_model_register (service_key, data_h, array->data, array->len,
dir_path)) {
event_type = ML_SERVICE_EVENT_MODEL_REGISTERED;
} else {
_ml_error_report ("Failed to register model downloaded from: %s.",
Expand All @@ -389,7 +414,14 @@ _mlrs_process_remote_service (nns_edge_data_h data_h, void *user_data)
}
case ML_REMOTE_SERVICE_TYPE_MODEL_RAW:
{
if (_mlrs_model_register (service_key, data_h, data, data_len)) {
g_autofree gchar *dir_path =
_mlrs_get_model_dir_path (remote_s, service_key);
if (!dir_path) {
_ml_error_report_return (NNS_EDGE_ERROR_UNKNOWN,
"Failed to get model directory path.");
}

if (_mlrs_model_register (service_key, data_h, data, data_len, dir_path)) {
event_type = ML_SERVICE_EVENT_MODEL_REGISTERED;
} else {
_ml_error_report ("Failed to register model downloaded from: %s.",
Expand Down Expand Up @@ -529,6 +561,7 @@ ml_service_remote_release_internal (void *priv)
return ML_ERROR_INVALID_PARAMETER;

nns_edge_release_handle (mlrs->edge_h);
g_free (mlrs->path);

/** Wait some time until release the edge handle. */
g_usleep (1000000);
Expand All @@ -545,9 +578,10 @@ ml_service_remote_create (ml_option_h option, ml_service_event_cb cb,
void *user_data, ml_service_h * handle)
{
ml_service_s *mls;
_ml_remote_service_s *remote_s;
edge_info_s *edge_info = NULL;
g_autofree _ml_remote_service_s *remote_s = NULL;
g_autofree edge_info_s *edge_info = NULL;
int ret = ML_ERROR_NONE;
void *value;

check_feature_state (ML_FEATURE_SERVICE);
check_feature_state (ML_FEATURE_INFERENCE);
Expand Down Expand Up @@ -576,22 +610,26 @@ ml_service_remote_create (ml_option_h option, ml_service_event_cb cb,
remote_s->node_type = edge_info->node_type;
remote_s->event_cb = cb;
remote_s->user_data = user_data;
if (ML_ERROR_NONE == ml_option_get (option, "path", &value)) {
if (g_access (value, W_OK) != 0) {
_ml_error_report ("Write permission denied, path: %s", value);
return ML_ERROR_PERMISSION_DENIED;
}
remote_s->path = g_strdup (value);
}

ret = _mlrs_create_edge_handle (remote_s, edge_info);
if (ML_ERROR_NONE != ret) {
g_free (edge_info);
g_free (remote_s);
return ret;
}

mls = g_new0 (ml_service_s, 1);
mls->type = ML_SERVICE_TYPE_REMOTE;
mls->priv = remote_s;
mls->priv = g_steal_pointer (&remote_s);

*handle = mls;

_mlrs_release_edge_info (edge_info);
g_free (edge_info);

return ret;
}
Expand Down
126 changes: 126 additions & 0 deletions tests/capi/unittest_capi_remote_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,132 @@ TEST_F (MLRemoteService, registerModelURI)
EXPECT_EQ (ML_ERROR_NONE, status);
}

/**
* @brief use case of model registration using ml remote service.
*/
TEST_F (MLRemoteService, registerModelPath)
{
int status;

/**============= Prepare client ============= **/
ml_service_h client_h;
ml_option_h client_option_h = NULL;

status = ml_option_create (&client_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *client_node_type = g_strdup ("remote_sender");
status = ml_option_set (client_option_h, "node-type", client_node_type, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *client_host = g_strdup ("127.0.0.1");
status = ml_option_set (client_option_h, "host", client_host, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

guint port = _get_available_port ();
status = ml_option_set (client_option_h, "port", &port, NULL);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *client_connect_type = g_strdup ("TCP");
status = ml_option_set (client_option_h, "connect-type", client_connect_type, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *topic = g_strdup ("remote_service_test_topic");
status = ml_option_set (client_option_h, "topic", topic, NULL);
EXPECT_EQ (ML_ERROR_NONE, status);

status = ml_service_remote_create (client_option_h, NULL, NULL, &client_h);
EXPECT_EQ (ML_ERROR_NONE, status);

/**============= Prepare server ============= **/
ml_service_h server_h;
ml_option_h server_option_h = NULL;
status = ml_option_create (&server_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *server_node_type = g_strdup ("remote_receiver");
status = ml_option_set (server_option_h, "node-type", server_node_type, g_free);

gchar *dest_host = g_strdup ("127.0.0.1");
status = ml_option_set (server_option_h, "dest-host", dest_host, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

status = ml_option_set (server_option_h, "topic", topic, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

status = ml_option_set (server_option_h, "dest-port", &port, NULL);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *server_connect_type = g_strdup ("TCP");
status = ml_option_set (server_option_h, "connect-type", server_connect_type, g_free);
EXPECT_EQ (ML_ERROR_NONE, status);

const gchar *root_path = g_getenv ("MLAPI_SOURCE_ROOT_PATH");
/* ml_service_remote_register () requires absolute path to model, ignore this case. */
if (root_path == NULL)
return;

g_autofree gchar* model_dir
= g_build_filename (root_path, "tests", "test_models", "models", NULL);
EXPECT_TRUE (g_file_test (model_dir, G_FILE_TEST_IS_DIR));

/** A path to save the received model file */
status = ml_option_set (server_option_h, "path", model_dir, NULL);
EXPECT_EQ (ML_ERROR_NONE, status);

g_autofree gchar *test_model
= g_build_filename (model_dir, "mobilenet_v1_1.0_224_quant.tflite", NULL);
EXPECT_TRUE (g_file_test (test_model, G_FILE_TEST_EXISTS));

g_autofree gchar *contents = NULL;
gsize len = 0;
EXPECT_TRUE (g_file_get_contents (test_model, &contents, &len, NULL));

status = ml_service_remote_create (
server_option_h, _ml_service_event_cb, contents, &server_h);
EXPECT_EQ (ML_ERROR_NONE, status);

/** Set service option */
ml_option_h remote_service_option_h = NULL;
status = ml_option_create (&remote_service_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);

gchar *service_key = g_strdup ("model_registration_test_key");
ml_option_set (remote_service_option_h, "service-key", service_key, g_free);

gchar *service_type = g_strdup ("model_raw");
ml_option_set (remote_service_option_h, "service-type", service_type, g_free);

gchar *activate = g_strdup ("true");
ml_option_set (remote_service_option_h, "activate", activate, g_free);

gchar *description = g_strdup ("temp description for remote model registeration test");
ml_option_set (remote_service_option_h, "description", description, g_free);

gchar *name = g_strdup ("received_mobilenet_v1_1.0_224_quant.tflite");
ml_option_set (remote_service_option_h, "name", name, g_free);

status = ml_service_remote_register (client_h, remote_service_option_h, contents, len);
EXPECT_EQ (ML_ERROR_NONE, status);

/** Wait for the server to register and check the result. */
g_usleep (1000000);

status = ml_service_model_delete (service_key, 0U);
EXPECT_TRUE (status == ML_ERROR_NONE);

status = ml_service_destroy (server_h);
EXPECT_EQ (ML_ERROR_NONE, status);
status = ml_service_destroy (client_h);
EXPECT_EQ (ML_ERROR_NONE, status);
status = ml_option_destroy (server_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);
status = ml_option_destroy (remote_service_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);
status = ml_option_destroy (client_option_h);
EXPECT_EQ (ML_ERROR_NONE, status);
}

/**
* @brief Main gtest
*/
Expand Down

0 comments on commit b97fe98

Please sign in to comment.