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,
23 mrp_res_error_t err, void *user_data);
24 static gboolean __mm_resource_manager_mloop_list_resources(mrp_res_context_t *context);
25 static int __mm_resource_manager_mloop_wait_connection(mm_resource_manager_mloop_s *mrp);
27 #define RM_RESOURCE_TIMEOUT 5
29 static gpointer thread_func(mm_resource_manager_mloop_s *mrp)
31 MM_RM_DEBUG("Worker thread is active");
33 g_mutex_lock(&mrp->lock);
35 GMainContext *m_ctx = g_main_context_new();
37 MM_RM_ERROR("Failed to create main context for resource manager");
38 g_mutex_unlock(&mrp->lock);
42 mrp->m_loop = g_main_loop_new(m_ctx, FALSE);
43 g_main_context_unref(m_ctx);
45 MM_RM_ERROR("Failed to create main loop for resource manager");
46 g_mutex_unlock(&mrp->lock);
50 mrp->mrp_loop = mrp_mainloop_glib_get(mrp->m_loop);
52 MM_RM_ERROR("Failed to create mrp_loop for resource manager");
53 g_mutex_unlock(&mrp->lock);
57 mrp->mrp_ctx = mrp_res_create(mrp->mrp_loop,
58 __mm_resource_manager_mloop_state_callback, mrp);
60 MM_RM_ERROR("Failed to create mrp_ctx for resource manager");
61 mrp_mainloop_destroy(mrp->mrp_loop);
62 g_mutex_unlock(&mrp->lock);
66 g_mutex_unlock(&mrp->lock);
68 g_main_loop_run(mrp->m_loop);
74 int _mm_resource_manager_mloop_create(mm_resource_manager_mloop_s **mrp)
76 mm_resource_manager_mloop_s *handle = NULL;
77 int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
79 handle = (mm_resource_manager_mloop_s *) calloc(1,
80 sizeof(mm_resource_manager_mloop_s));
81 MM_RM_RETVM_IF(NULL == handle, MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION,
82 "Error allocating memory for Handle");
84 g_mutex_init(&handle->lock);
85 g_cond_init(&handle->cond);
87 handle->worker = g_thread_try_new(NULL, (GThreadFunc) thread_func, handle, NULL);
88 if (!handle->worker) {
89 MM_RM_ERROR("Failed to create worker thread");
90 _mm_resource_manager_mloop_destroy(handle);
91 return MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION;
94 /* Wait while resource manager connects to Murphy.
95 We assume that this condition is triggered only in case
96 we successfully connected to Murphy. Otherwise an error
97 is returned. And resulting handle is NULL */
98 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
99 __mm_resource_manager_mloop_wait_connection(handle)) {
100 _mm_resource_manager_mloop_destroy(handle);
101 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
106 MM_RM_INFO("Successfully performed mloop create");
111 int _mm_resource_manager_mloop_destroy(mm_resource_manager_mloop_s *mrp)
114 MM_RM_ERROR("mrp is null");
115 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
118 g_mutex_lock(&mrp->lock);
121 mrp_mainloop_quit(mrp->mrp_loop, 0);
124 mrp_res_destroy(mrp->mrp_ctx);
129 mrp_mainloop_destroy(mrp->mrp_loop);
130 mrp->mrp_loop = NULL;
134 g_main_loop_quit(mrp->m_loop);
135 g_main_loop_unref(mrp->m_loop);
139 MM_RM_DEBUG("Joining worker thread...");
140 g_thread_join(mrp->worker);
142 MM_RM_DEBUG("Joined to worker thread");
145 g_mutex_unlock(&mrp->lock);
147 g_mutex_clear(&mrp->lock);
148 g_cond_clear(&mrp->cond);
152 return MM_RESOURCE_MANAGER_ERROR_NONE;
155 int _mm_resource_manager_mloop_is_run(mm_resource_manager_mloop_s *mrp, gboolean *is_run)
157 *is_run = mrp->mrp_ctx->state == MRP_RES_CONNECTED ? TRUE : FALSE;
159 return MM_RESOURCE_MANAGER_ERROR_NONE;
162 int _mm_resource_manager_mloop_set_error_cb(mm_resource_manager_mloop_s *mrp,
163 mm_resource_manager_mloop_error_cb cb, void *user_data)
166 mrp->user_data = user_data;
168 return MM_RESOURCE_MANAGER_ERROR_NONE;
171 static void __mm_resource_manager_mloop_state_callback(mrp_res_context_t *context,
172 mrp_res_error_t err, void *user_data)
174 mm_resource_manager_mloop_s *mrp = NULL;
176 MM_RM_DEBUG("enter");
179 MM_RM_ERROR("user data must be not NULL");
183 mrp = (mm_resource_manager_mloop_s *) user_data;
185 g_mutex_lock(&mrp->lock);
188 case MRP_RES_ERROR_CONNECTION_LOST:
189 case MRP_RES_ERROR_INTERNAL:
190 case MRP_RES_ERROR_MALFORMED:
191 MM_RM_ERROR("error message received from Murphy, err(0x%x)", err);
193 mrp->error_cb(mrp, err, mrp->user_data);
195 g_mutex_unlock(&mrp->lock);
197 case MRP_RES_ERROR_NONE:
202 switch (context->state) {
203 case MRP_RES_CONNECTED:
204 MM_RM_DEBUG("Connected to Murphy");
205 if (__mm_resource_manager_mloop_list_resources(context))
206 g_cond_signal(&mrp->cond);
209 case MRP_RES_DISCONNECTED:
210 MM_RM_DEBUG("Disconnected from Murphy");
216 g_mutex_unlock(&mrp->lock);
219 static gboolean __mm_resource_manager_mloop_list_resources(mrp_res_context_t *context)
221 const mrp_res_resource_set_t *rset;
222 mrp_res_resource_t *resource = NULL;
225 rset = mrp_res_list_resources(context);
227 mrp_res_string_array_t *resource_names = NULL;
229 resource_names = mrp_res_list_resource_names(rset);
230 if (!resource_names) {
231 MM_RM_ERROR("no resources available");
235 for (i = 0; i < resource_names->num_strings; ++i) {
236 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
238 MM_RM_DEBUG("available resource: %s", resource->name);
241 mrp_res_free_string_array(resource_names);
247 static int __mm_resource_manager_mloop_wait_connection(mm_resource_manager_mloop_s *mrp)
249 MM_RM_RETVM_IF(mrp == NULL,
250 MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
251 "mainloop_s is null");
253 g_mutex_lock(&mrp->lock);
255 if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
256 MM_RM_DEBUG("Already connected to resource server");
258 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_SECOND;
260 MM_RM_DEBUG("Not connected to resource server yet. Waiting...");
262 if (!g_cond_wait_until(&mrp->cond, &mrp->lock, end_time)) {
263 MM_RM_ERROR("Could not connect to resource server");
264 g_mutex_unlock(&mrp->lock);
265 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
267 if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
268 MM_RM_DEBUG("Successfully connected to resource server!");
270 MM_RM_ERROR("Failed to connect to resource server");
271 g_mutex_unlock(&mrp->lock);
272 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
277 g_mutex_unlock(&mrp->lock);
279 return MM_RESOURCE_MANAGER_ERROR_NONE;