2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <murphy/common/glib-glue.h>
18 #include "lib/mm_resource_manager.h"
19 #include "daemon/mm_resource_manager_daemon_dbus.h"
20 #include "daemon/backend/murphy/mm_resource_manager_mloop.h"
22 static void __mm_resource_manager_mloop_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data);
23 static gboolean __mm_resource_manager_mloop_list_resources(mrp_res_context_t *context);
24 static int __mm_resource_manager_mloop_wait_connection(mm_resource_manager_mloop_s *mrp);
26 #define RM_RESOURCE_TIMEOUT 300
28 static gpointer thread_func(mm_resource_manager_mloop_s *mrp)
30 MM_RM_DEBUG("Worker thread is active");
32 g_mutex_lock(&mrp->lock);
34 GMainContext *m_ctx = g_main_context_new();
36 MM_RM_ERROR("Failed to create main context for resource manager");
37 g_mutex_unlock(&mrp->lock);
41 mrp->m_loop = g_main_loop_new(m_ctx, FALSE);
42 g_main_context_unref(m_ctx);
44 MM_RM_ERROR("Failed to create main loop for resource manager");
45 g_mutex_unlock(&mrp->lock);
49 mrp->mrp_loop = mrp_mainloop_glib_get(mrp->m_loop);
51 MM_RM_ERROR("Failed to create mrp_loop for resource manager");
52 g_mutex_unlock(&mrp->lock);
56 mrp->mrp_ctx = mrp_res_create(mrp->mrp_loop,
57 __mm_resource_manager_mloop_state_callback, mrp);
59 MM_RM_ERROR("Failed to create mrp_ctx for resource manager");
60 mrp_mainloop_destroy(mrp->mrp_loop);
61 g_mutex_unlock(&mrp->lock);
65 g_mutex_unlock(&mrp->lock);
67 g_main_loop_run(mrp->m_loop);
73 int _mm_resource_manager_mloop_create(mm_resource_manager_mloop_s **mrp)
75 mm_resource_manager_mloop_s *handle = NULL;
76 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
78 handle = (mm_resource_manager_mloop_s *) calloc(1, sizeof(mm_resource_manager_mloop_s));
79 MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Error allocating memory for Handle");
81 g_mutex_init(&handle->lock);
82 g_cond_init(&handle->cond);
84 handle->worker = g_thread_try_new("worker thread", (GThreadFunc) thread_func, handle, NULL);
85 if (!handle->worker) {
86 MM_RM_ERROR("Failed to create worker thread");
87 _mm_resource_manager_mloop_destroy(handle);
88 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
91 /* Wait while resource manager connects to Murphy.
92 We assume that this condition is triggered only in case
93 we successfully connected to Murphy. Otherwise an error
94 is returned. And resulting handle is NULL */
95 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
96 __mm_resource_manager_mloop_wait_connection(handle)) {
97 _mm_resource_manager_mloop_destroy(handle);
98 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
103 MM_RM_INFO("Successfully performed mloop create");
108 int _mm_resource_manager_mloop_destroy(mm_resource_manager_mloop_s *mrp)
111 MM_RM_ERROR("mrp is null");
112 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
115 g_mutex_lock(&mrp->lock);
118 mrp_mainloop_quit(mrp->mrp_loop, 0);
121 mrp_res_destroy(mrp->mrp_ctx);
126 mrp_mainloop_destroy(mrp->mrp_loop);
127 mrp->mrp_loop = NULL;
131 g_main_loop_quit(mrp->m_loop);
132 g_main_loop_unref(mrp->m_loop);
136 MM_RM_DEBUG("Joining worker thread...");
137 g_thread_join(mrp->worker);
139 MM_RM_DEBUG("Joined to worker thread");
142 g_mutex_unlock(&mrp->lock);
144 g_mutex_clear(&mrp->lock);
145 g_cond_clear(&mrp->cond);
149 return MM_RESOURCE_MANAGER_ERROR_NONE;
152 int _mm_resource_manager_mloop_is_run(mm_resource_manager_mloop_s *mrp, gboolean *is_run)
154 *is_run = mrp->mrp_ctx->state == MRP_RES_CONNECTED ? TRUE : FALSE;
156 return MM_RESOURCE_MANAGER_ERROR_NONE;
159 int _mm_resource_manager_mloop_set_error_cb(mm_resource_manager_mloop_s *mrp,
160 mm_resource_manager_mloop_error_cb cb, void *user_data)
163 mrp->user_data = user_data;
165 return MM_RESOURCE_MANAGER_ERROR_NONE;
168 static void __mm_resource_manager_mloop_state_callback(mrp_res_context_t *context,
169 mrp_res_error_t err, void *user_data)
171 mm_resource_manager_mloop_s *mrp = NULL;
173 MM_RM_DEBUG("enter");
176 MM_RM_ERROR("user data must be not NULL");
180 mrp = (mm_resource_manager_mloop_s *) user_data;
182 g_mutex_lock(&mrp->lock);
185 case MRP_RES_ERROR_CONNECTION_LOST:
186 case MRP_RES_ERROR_INTERNAL:
187 case MRP_RES_ERROR_MALFORMED:
188 MM_RM_ERROR("error message received from Murphy, err(0x%x)", err);
190 mrp->error_cb(mrp, err, mrp->user_data);
192 g_mutex_unlock(&mrp->lock);
194 case MRP_RES_ERROR_NONE:
199 switch (context->state) {
200 case MRP_RES_CONNECTED:
201 MM_RM_DEBUG("Connected to Murphy");
202 if (__mm_resource_manager_mloop_list_resources(context))
203 g_cond_signal(&mrp->cond);
206 case MRP_RES_DISCONNECTED:
207 MM_RM_DEBUG("Disconnected from Murphy");
213 g_mutex_unlock(&mrp->lock);
216 static gboolean __mm_resource_manager_mloop_list_resources(mrp_res_context_t *context)
218 const mrp_res_resource_set_t *rset;
219 mrp_res_resource_t *resource = NULL;
222 rset = mrp_res_list_resources(context);
224 mrp_res_string_array_t *resource_names = NULL;
226 resource_names = mrp_res_list_resource_names(rset);
227 if (!resource_names) {
228 MM_RM_ERROR("no resources available");
232 for (i = 0; i < resource_names->num_strings; ++i) {
233 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
235 MM_RM_DEBUG("available resource: %s", resource->name);
238 mrp_res_free_string_array(resource_names);
244 static int __mm_resource_manager_mloop_wait_connection(mm_resource_manager_mloop_s *mrp)
246 MM_RM_RETVM_IF(mrp == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "mainloop_s is null");
248 g_mutex_lock(&mrp->lock);
250 if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
251 MM_RM_DEBUG("Already connected to resource server");
253 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_MILLISECOND;
255 MM_RM_DEBUG("Not connected to resource server yet. Waiting...");
257 if (!g_cond_wait_until(&mrp->cond, &mrp->lock, end_time)) {
258 MM_RM_ERROR("Could not connect to resource server");
259 g_mutex_unlock(&mrp->lock);
260 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
262 if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
263 MM_RM_DEBUG("Successfully connected to resource server!");
265 MM_RM_ERROR("Failed to connect to resource server");
266 g_mutex_unlock(&mrp->lock);
267 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
272 g_mutex_unlock(&mrp->lock);
274 return MM_RESOURCE_MANAGER_ERROR_NONE;