Adding extra logs
[platform/core/pim/contacts-service.git] / client / ctsvc_client_service_helper.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <errno.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <unistd.h>
23
24 #include "contacts.h"
25 #include "ctsvc_internal.h"
26 #include "ctsvc_socket.h"
27 #include "ctsvc_mutex.h"
28 #include "ctsvc_inotify.h"
29 #include "ctsvc_client_ipc.h"
30 #include "ctsvc_client_utils.h"
31 #include "ctsvc_client_handle.h"
32 #include "ctsvc_client_service_helper.h"
33
34 static int _ctsvc_connection = 0;
35 static __thread int _ctsvc_connection_on_thread = 0;
36
37 int ctsvc_client_get_thread_connection_count()
38 {
39         return _ctsvc_connection_on_thread;
40 }
41
42 int ctsvc_client_connect_with_flags(contacts_h contact, unsigned int flags)
43 {
44         CTS_FN_CALL;
45         int ret = CONTACTS_ERROR_NONE;
46
47         /* If new flag is defined, errer check should be updated */
48         RETVM_IF(flags & 0x11111110, CONTACTS_ERROR_INVALID_PARAMETER, "flags is invalid");
49
50         ret = ctsvc_client_connect(contact);
51         if (ret == CONTACTS_ERROR_PERMISSION_DENIED)
52                 return ret;
53         else if (ret == CONTACTS_ERROR_NONE)
54                 return ret;
55
56         if (flags & CONTACTS_CONNECT_FLAG_RETRY) {
57                 int i;
58                 int waiting_time = 500;
59                 for (i = 0; i < 9; i++) {
60                         usleep(waiting_time * 1000);
61                         DBG("retry cnt=%d, ret=%x, %d", (i+1), ret, waiting_time);
62                         ret = ctsvc_client_connect(contact);
63                         if (ret == CONTACTS_ERROR_NONE)
64                                 break;
65                         if (6 < i)
66                                 waiting_time += 30000;
67                         else
68                                 waiting_time *= 2;
69                 }
70         }
71
72         return ret;
73 }
74
75 /* LCOV_EXCL_START */
76 static void _ctsvc_ipc_initialized_cb(void *user_data)
77 {
78         CTS_FN_CALL;
79         if (true == ctsvc_ipc_get_disconnected()) {
80                 ctsvc_ipc_set_disconnected(false);
81                 ctsvc_ipc_recovery();
82                 ctsvc_ipc_recover_for_change_subscription();
83         }
84 }
85 /* LCOV_EXCL_STOP */
86
87 int ctsvc_client_connect(contacts_h contact)
88 {
89         CTS_FN_CALL;
90         int ret;
91         ctsvc_base_s *base = (ctsvc_base_s*)contact;
92         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
93
94         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
95         if (0 == base->connection_count) {
96                 WARN("Contacts service connect(%d)", _ctsvc_connection );
97                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
98                 if (ret != CONTACTS_ERROR_NONE) {
99                         /* LCOV_EXCL_START */
100                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
101                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
102                         return ret;
103                         /* LCOV_EXCL_STOP */
104                 }
105         }
106         base->connection_count++;
107
108         if (0 == _ctsvc_connection) {
109                 ret = ctsvc_socket_init();
110                 if (ret != CONTACTS_ERROR_NONE) {
111                         /* LCOV_EXCL_START */
112                         ERR("ctsvc_socket_init() Fail(%d)", ret);
113                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
114                         return ret;
115                         /* LCOV_EXCL_STOP */
116                 }
117
118                 ret = ctsvc_inotify_init();
119                 if (ret != CONTACTS_ERROR_NONE) {
120                         /* LCOV_EXCL_START */
121                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
122                         ctsvc_socket_final();
123                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
124                         return ret;
125                         /* LCOV_EXCL_STOP */
126                 }
127                 ctsvc_view_uri_init();
128         } else {
129                 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
130         }
131
132         if (1 == base->connection_count)
133                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
134
135         _ctsvc_connection++;
136         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
137
138         return CONTACTS_ERROR_NONE;
139 }
140
141 int ctsvc_client_disconnect(contacts_h contact)
142 {
143         CTS_FN_CALL;
144         int ret;
145         ctsvc_base_s *base = (ctsvc_base_s*)contact;
146         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
147
148         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
149
150         if (1 == base->connection_count) {
151                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
152                 if (ret != CONTACTS_ERROR_NONE) {
153                         /* LCOV_EXCL_START */
154                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
155                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
156                         return ret;
157                         /* LCOV_EXCL_STOP */
158                 }
159                 ctsvc_inotify_unsubscribe_ipc_ready();
160         }
161         base->connection_count--;
162
163         if (1 == _ctsvc_connection) {
164                 ctsvc_ipc_destroy_for_change_subscription(true);
165                 ctsvc_view_uri_deinit();
166                 ctsvc_inotify_close();
167                 ctsvc_socket_final();
168
169         } else if (1 < _ctsvc_connection) {
170                 DBG("connection count is %d", _ctsvc_connection);
171         } else {
172                 /* LCOV_EXCL_START */
173                 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
174                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
175                 return CONTACTS_ERROR_DB;
176                 /* LCOV_EXCL_STOP */
177         }
178
179         _ctsvc_connection--;
180
181         if (0 == base->connection_count) {
182                 INFO("connection_count is 0. remove handle");
183                 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
184                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
185         }
186         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
187
188         return CONTACTS_ERROR_NONE;
189 }
190
191 int ctsvc_client_connect_on_thread(contacts_h contact)
192 {
193         int ret;
194         ctsvc_base_s *base = (ctsvc_base_s*)contact;
195         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
196
197         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
198
199         if (0 == base->connection_count) {
200                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
201                 if (ret != CONTACTS_ERROR_NONE) {
202                         /* LCOV_EXCL_START */
203                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
204                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
205                         return ret;
206                         /* LCOV_EXCL_STOP */
207                 }
208         }
209         base->connection_count++;
210
211         if (0 == _ctsvc_connection_on_thread) {
212                 ret = ctsvc_socket_init();
213                 if (ret != CONTACTS_ERROR_NONE) {
214                         /* LCOV_EXCL_START */
215                         ERR("ctsvc_socket_init() Fail(%d)", ret);
216                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
217                         return ret;
218                         /* LCOV_EXCL_STOP */
219                 }
220
221                 ret = ctsvc_inotify_init();
222                 if (ret != CONTACTS_ERROR_NONE) {
223                         /* LCOV_EXCL_START */
224                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
225                         ctsvc_socket_final();
226                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
227                         return ret;
228                         /* LCOV_EXCL_STOP */
229                 }
230                 ctsvc_view_uri_init();
231         } else if (0 < _ctsvc_connection_on_thread) {
232                 DBG("System : Contacts service has been already connected");
233         }
234
235         if (1 == base->connection_count)
236                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
237
238         _ctsvc_connection_on_thread++;
239
240         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
241
242         return CONTACTS_ERROR_NONE;
243 }
244
245 int ctsvc_client_disconnect_on_thread(contacts_h contact)
246 {
247         int ret;
248         ctsvc_base_s *base = (ctsvc_base_s*)contact;
249         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
250
251         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
252
253         if (1 == base->connection_count) {
254                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
255                                 _ctsvc_connection_on_thread);
256                 if (ret != CONTACTS_ERROR_NONE) {
257                         /* LCOV_EXCL_START */
258                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
259                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
260                         return ret;
261                         /* LCOV_EXCL_STOP */
262                 }
263                 ctsvc_inotify_unsubscribe_ipc_ready();
264         }
265         base->connection_count--;
266
267         if (1 == _ctsvc_connection_on_thread) {
268                 if (0 == _ctsvc_connection)
269                         ctsvc_ipc_destroy_for_change_subscription(true);
270                 ctsvc_view_uri_deinit();
271                 ctsvc_inotify_close();
272                 ctsvc_socket_final();
273                 DBG("System : connection_on_thread was destroyed successfully");
274         } else if (1 < _ctsvc_connection_on_thread) {
275                 DBG("connection count is %d", _ctsvc_connection_on_thread);
276         } else {
277                 /* LCOV_EXCL_START */
278                 DBG("call contacts_connect_on_thread(), connection count is %d",
279                                 _ctsvc_connection_on_thread);
280                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
281                 return CONTACTS_ERROR_DB;
282                 /* LCOV_EXCL_STOP */
283         }
284
285         _ctsvc_connection_on_thread--;
286
287         if (0 == base->connection_count) {
288                 INFO("connection_count is 0. remove handle");
289                 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
290                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
291         }
292         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
293
294         return CONTACTS_ERROR_NONE;
295 }
296