Skip to content

Commit

Permalink
[Services] Remote model register
Browse files Browse the repository at this point in the history
 - Impelent registering model relotely
 - Add unit test

Signed-off-by: gichan2-jang <gichan2.jang@samsung.com>
  • Loading branch information
gichan-jang committed Jul 10, 2023
1 parent ba23c36 commit 25dd92f
Show file tree
Hide file tree
Showing 6 changed files with 546 additions and 16 deletions.
1 change: 1 addition & 0 deletions c/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ if get_option('enable-ml-service')
ml_service_deps = [nns_capi_dep, ml_agentd_deps]
if nnstreamer_edge_dep.found()
ml_service_deps += nnstreamer_edge_dep
ml_service_deps += curl_dep
endif

nns_capi_service_shared_lib = shared_library ('capi-ml-service',
Expand Down
167 changes: 155 additions & 12 deletions c/src/ml-api-remote-service.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <gst/gstbuffer.h>
#include <gst/app/app.h>
#include <string.h>
#include <curl/curl.h>

#include "ml-api-internal.h"
#include "ml-api-service.h"
Expand Down Expand Up @@ -151,12 +152,12 @@ _mlrs_get_service_type (gchar * service_str)

if (g_ascii_strcasecmp (service_str, "model_raw") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_MODEL_RAW;
} else if (g_ascii_strcasecmp (service_str, "model_url") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_MODEL_URL;
} else if (g_ascii_strcasecmp (service_str, "model_uri") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_MODEL_URI;
} else if (g_ascii_strcasecmp (service_str, "pipeline_raw") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_PIPELINE_RAW;
} else if (g_ascii_strcasecmp (service_str, "pipeline_url") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_PIPELINE_URL;
} else if (g_ascii_strcasecmp (service_str, "pipeline_uri") == 0) {
service_type = ML_REMOTE_SERVICE_TYPE_PIPELINE_URI;
} else {
_ml_error_report ("Invalid service type: %s, Please check service type.",
service_str);
Expand All @@ -165,6 +166,120 @@ _mlrs_get_service_type (gchar * service_str)
return service_type;
}

/**
* @brief Get ml remote service activation type.
*/
static gboolean
_mlrs_parse_activate (gchar * activate)
{
gboolean ret = TRUE;

if (activate && g_ascii_strcasecmp (activate, "false") == 0) {
ret = FALSE;
}

return ret;
}

/**
* @brief Callback function for receving data using curl.
*/
static size_t
curl_mem_write_cb (void *data, size_t size, size_t nmemb, void *clientp)
{
size_t recv_size = size * nmemb;
GByteArray *array = (GByteArray *) clientp;

if (!array)
return 0;

g_byte_array_append (array, data, recv_size);

return recv_size;
}

/**
* @brief Register model file given by the remote sender.
*/
static gboolean
_mlrs_model_register (gchar * service_key, nns_edge_data_h data_h,
void *data, nns_size_t data_len)
{
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;
gboolean active_bool = TRUE;
GError *error = NULL;
gboolean ret = TRUE;

nns_edge_data_get_info (data_h, "description", &description);
nns_edge_data_get_info (data_h, "name", &name);
nns_edge_data_get_info (data_h, "activate", &activate);
active_bool = _mlrs_parse_activate (activate);

dir_path = g_build_path ("/", current_dir, service_key, NULL);
g_mkdir_with_parents (dir_path, 0755);
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;
}

/**
* @todo Hashing the path. Where is the default path to save the model file?
*/
ml_service_model_register (service_key, model_path,
active_bool, description, &version);
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 data from gievn uri
*/
static gboolean
_mlrs_get_data_from_uri (gchar *uri, GByteArray *array)
{
CURL *curl;
CURLcode res;
gboolean ret = FALSE;

curl = curl_easy_init ();
if (curl) {
curl_easy_setopt (curl, CURLOPT_URL, (gchar *) uri);
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, curl_mem_write_cb);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *) array);

res = curl_easy_perform (curl);

if (res != CURLE_OK) {
_ml_loge ("curl_easy_perform failed: %s\n", curl_easy_strerror (res));
return FALSE;
}

curl_easy_cleanup (curl);
ret = TRUE;
}

return ret;
}

/**
* @brief Process ml remote service
*/
Expand All @@ -175,29 +290,48 @@ _mlrs_process_remote_service (nns_edge_data_h data_h)
nns_size_t data_len;
gchar *service_str = NULL;
gchar *service_key = NULL;
gchar *description = NULL;
ml_remote_service_type_e service_type;

nns_edge_data_get (data_h, 0, &data, &data_len);

nns_edge_data_get_info (data_h, "service-type", &service_str);
service_type = _mlrs_get_service_type (service_str);
nns_edge_data_get_info (data_h, "service-key", &service_key);
nns_edge_data_get_info (data_h, "description", &description);

switch (service_type) {
case ML_REMOTE_SERVICE_TYPE_MODEL_URL:
/** @todo Download the model file from given URL */
case ML_REMOTE_SERVICE_TYPE_MODEL_URI:
{
GByteArray *array = g_byte_array_new ();

_mlrs_get_data_from_uri ((gchar *) data, array);
g_message ("pipeline size: %u", array->len);
_mlrs_model_register (service_key, data_h, array->data, array->len);
g_byte_array_free (array, TRUE);
break;
}
case ML_REMOTE_SERVICE_TYPE_MODEL_RAW:
/** @todo Save model file to given path and register the model */
{
_mlrs_model_register (service_key, data_h, data, data_len);
break;
case ML_REMOTE_SERVICE_TYPE_PIPELINE_URL:
/** @todo Download the pipeline description from given URL */
}
case ML_REMOTE_SERVICE_TYPE_PIPELINE_URI:
{
GByteArray *array = g_byte_array_new ();

_mlrs_get_data_from_uri ((gchar *) data, array);
g_message ("pipeline size: %u", array->len);
ml_service_set_pipeline (service_key, (gchar *) array->data);
g_byte_array_free (array, TRUE);
break;
}
case ML_REMOTE_SERVICE_TYPE_PIPELINE_RAW:
ml_service_set_pipeline (service_key, (gchar *) data);
break;
default:
_ml_error_report
("Unknown service type or not supported yet. Service num: %d",
service_type);
_ml_error_report ("Unknown service type or not supported yet. "
"Service num: %d", service_type);
break;
}
}
Expand Down Expand Up @@ -346,6 +480,9 @@ ml_remote_service_register (ml_service_h handle, ml_option_h option, void *data,
nns_edge_data_h data_h = NULL;
int ret = NNS_EDGE_ERROR_NONE;
gchar *service_str = NULL;
gchar *description = NULL;
gchar *name = NULL;
gchar *activate = NULL;

check_feature_state (ML_FEATURE_SERVICE);
check_feature_state (ML_FEATURE_INFERENCE);
Expand Down Expand Up @@ -382,6 +519,12 @@ ml_remote_service_register (ml_service_h handle, ml_option_h option, void *data,
nns_edge_data_set_info (data_h, "service-type", service_str);
ml_option_get (option, "service-key", (void **) &service_key);
nns_edge_data_set_info (data_h, "service-key", service_key);
ml_option_get (option, "description", (void **) &description);
nns_edge_data_set_info (data_h, "description", description);
ml_option_get (option, "name", (void **) &name);
nns_edge_data_set_info (data_h, "name", name);
ml_option_get (option, "activate", (void **) &activate);
nns_edge_data_set_info (data_h, "activate", activate);

ret = nns_edge_data_add (data_h, data, data_len, NULL);
if (NNS_EDGE_ERROR_NONE != ret) {
Expand Down
4 changes: 2 additions & 2 deletions c/src/ml-api-service-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ typedef enum {
typedef enum {
ML_REMOTE_SERVICE_TYPE_UNKNOWN = 0,
ML_REMOTE_SERVICE_TYPE_MODEL_RAW,
ML_REMOTE_SERVICE_TYPE_MODEL_URL,
ML_REMOTE_SERVICE_TYPE_MODEL_URI,
ML_REMOTE_SERVICE_TYPE_PIPELINE_RAW,
ML_REMOTE_SERVICE_TYPE_PIPELINE_URL,
ML_REMOTE_SERVICE_TYPE_PIPELINE_URI,

ML_REMOTE_SERVICE_TYPE_MAX
} ml_remote_service_type_e;
Expand Down
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ nnstreamer_internal_dep = dependency('nnstreamer-internal')
nnstreamer_single_dep = dependency('nnstreamer-single')
nnstreamer_dep = dependency('nnstreamer')
nnstreamer_edge_dep = dependency('nnstreamer-edge', required: false)
curl_dep = cc.find_library('curl', required: false)

if get_option('enable-ml-service')
libsystemd_dep = dependency('libsystemd')
Expand Down
1 change: 1 addition & 0 deletions packaging/machine-learning-api.spec
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ BuildRequires: pkgconfig(json-glib-1.0)
BuildRequires: dbus
BuildRequires: pkgconfig(capi-appfw-package-manager)
BuildRequires: pkgconfig(capi-appfw-app-common)
BuildRequires: libcurl-devel
%endif

%if 0%{?nnstreamer_edge_support}
Expand Down
Loading

0 comments on commit 25dd92f

Please sign in to comment.