Add thread name for debugging and revise typo
[platform/core/multimedia/mm-resource-manager.git] / src / daemon / backend / murphy / mm_resource_manager_mloop.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
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"
21
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);
25
26 #define RM_RESOURCE_TIMEOUT 300
27
28 static gpointer thread_func(mm_resource_manager_mloop_s *mrp)
29 {
30         MM_RM_DEBUG("Worker thread is active");
31
32         g_mutex_lock(&mrp->lock);
33
34         GMainContext *m_ctx = g_main_context_new();
35         if (!m_ctx) {
36                 MM_RM_ERROR("Failed to create main context for resource manager");
37                 g_mutex_unlock(&mrp->lock);
38                 goto EXIT;
39         }
40
41         mrp->m_loop = g_main_loop_new(m_ctx, FALSE);
42         g_main_context_unref(m_ctx);
43         if (!mrp->m_loop) {
44                 MM_RM_ERROR("Failed to create main loop for resource manager");
45                 g_mutex_unlock(&mrp->lock);
46                 goto EXIT;
47         }
48
49         mrp->mrp_loop = mrp_mainloop_glib_get(mrp->m_loop);
50         if (!mrp->mrp_loop) {
51                 MM_RM_ERROR("Failed to create mrp_loop for resource manager");
52                 g_mutex_unlock(&mrp->lock);
53                 goto EXIT;
54         }
55
56         mrp->mrp_ctx = mrp_res_create(mrp->mrp_loop,
57                 __mm_resource_manager_mloop_state_callback, mrp);
58         if (!mrp->mrp_ctx) {
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);
62                 goto EXIT;
63         }
64
65         g_mutex_unlock(&mrp->lock);
66
67         g_main_loop_run(mrp->m_loop);
68
69 EXIT:
70         return NULL;
71 }
72
73 int _mm_resource_manager_mloop_create(mm_resource_manager_mloop_s **mrp)
74 {
75         mm_resource_manager_mloop_s *handle = NULL;
76         int ret = MM_RESOURCE_MANAGER_ERROR_NONE;
77
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");
80
81         g_mutex_init(&handle->lock);
82         g_cond_init(&handle->cond);
83
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;
89         }
90
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;
99         }
100
101         *mrp = handle;
102
103         MM_RM_INFO("Successfully performed mloop create");
104
105         return ret;
106 }
107
108 int _mm_resource_manager_mloop_destroy(mm_resource_manager_mloop_s *mrp)
109 {
110         if (mrp == NULL) {
111                 MM_RM_ERROR("mrp is null");
112                 return MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER;
113         }
114
115         g_mutex_lock(&mrp->lock);
116
117         if (mrp->mrp_loop)
118                 mrp_mainloop_quit(mrp->mrp_loop, 0);
119
120         if (mrp->mrp_ctx) {
121                 mrp_res_destroy(mrp->mrp_ctx);
122                 mrp->mrp_ctx = NULL;
123         }
124
125         if (mrp->mrp_loop) {
126                 mrp_mainloop_destroy(mrp->mrp_loop);
127                 mrp->mrp_loop = NULL;
128         }
129
130         if (mrp->m_loop) {
131                 g_main_loop_quit(mrp->m_loop);
132                 g_main_loop_unref(mrp->m_loop);
133         }
134
135         if (mrp->worker) {
136                 MM_RM_DEBUG("Joining worker thread...");
137                 g_thread_join(mrp->worker);
138                 mrp->worker = NULL;
139                 MM_RM_DEBUG("Joined to worker thread");
140         }
141
142         g_mutex_unlock(&mrp->lock);
143
144         g_mutex_clear(&mrp->lock);
145         g_cond_clear(&mrp->cond);
146
147         free(mrp);
148
149         return MM_RESOURCE_MANAGER_ERROR_NONE;
150 }
151
152 int _mm_resource_manager_mloop_is_run(mm_resource_manager_mloop_s *mrp, gboolean *is_run)
153 {
154         *is_run = mrp->mrp_ctx->state == MRP_RES_CONNECTED ? TRUE : FALSE;
155
156         return MM_RESOURCE_MANAGER_ERROR_NONE;
157 }
158
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)
161 {
162         mrp->error_cb = cb;
163         mrp->user_data = user_data;
164
165         return MM_RESOURCE_MANAGER_ERROR_NONE;
166 }
167
168 static void __mm_resource_manager_mloop_state_callback(mrp_res_context_t *context,
169         mrp_res_error_t err, void *user_data)
170 {
171         mm_resource_manager_mloop_s *mrp = NULL;
172
173         MM_RM_DEBUG("enter");
174
175         if (!user_data) {
176                 MM_RM_ERROR("user data must be not NULL");
177                 return;
178         }
179
180         mrp = (mm_resource_manager_mloop_s *) user_data;
181
182         g_mutex_lock(&mrp->lock);
183
184         switch (err) {
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);
189                 if (mrp->error_cb)
190                         mrp->error_cb(mrp, err, mrp->user_data);
191
192                 g_mutex_unlock(&mrp->lock);
193                 break;
194         case MRP_RES_ERROR_NONE:
195         default:
196                 break;
197         }
198
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);
204
205                 break;
206         case MRP_RES_DISCONNECTED:
207                 MM_RM_DEBUG("Disconnected from Murphy");
208                 break;
209         default:
210                 break;
211         }
212
213         g_mutex_unlock(&mrp->lock);
214 }
215
216 static gboolean __mm_resource_manager_mloop_list_resources(mrp_res_context_t *context)
217 {
218         const mrp_res_resource_set_t *rset;
219         mrp_res_resource_t *resource = NULL;
220         int i = 0;
221
222         rset = mrp_res_list_resources(context);
223         if (rset) {
224                 mrp_res_string_array_t *resource_names = NULL;
225
226                 resource_names = mrp_res_list_resource_names(rset);
227                 if (!resource_names) {
228                         MM_RM_ERROR("no resources available");
229                         return FALSE;
230                 }
231
232                 for (i = 0; i < resource_names->num_strings; ++i) {
233                         resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
234                         if (resource)
235                                 MM_RM_DEBUG("available resource: %s", resource->name);
236                 }
237
238                 mrp_res_free_string_array(resource_names);
239         }
240
241         return TRUE;
242 }
243
244 static int __mm_resource_manager_mloop_wait_connection(mm_resource_manager_mloop_s *mrp)
245 {
246         MM_RM_RETVM_IF(mrp == NULL, MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER, "mainloop_s is null");
247
248         g_mutex_lock(&mrp->lock);
249
250         if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
251                 MM_RM_DEBUG("Already connected to resource server");
252         } else {
253                 gint64 end_time = g_get_monotonic_time() + RM_RESOURCE_TIMEOUT * G_TIME_SPAN_MILLISECOND;
254
255                 MM_RM_DEBUG("Not connected to resource server yet. Waiting...");
256
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;
261                 } else {
262                         if (mrp->mrp_ctx && MRP_RES_CONNECTED == mrp->mrp_ctx->state) {
263                                 MM_RM_DEBUG("Successfully connected to resource server!");
264                         } else {
265                                 MM_RM_ERROR("Failed to connect to resource server");
266                                 g_mutex_unlock(&mrp->lock);
267                                 return MM_RESOURCE_MANAGER_ERROR_INVALID_STATE;
268                         }
269                 }
270         }
271
272         g_mutex_unlock(&mrp->lock);
273
274         return MM_RESOURCE_MANAGER_ERROR_NONE;
275 }