improve line coverage
[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                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
97                 if (ret != CONTACTS_ERROR_NONE) {
98                         /* LCOV_EXCL_START */
99                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
100                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
101                         return ret;
102                         /* LCOV_EXCL_STOP */
103                 }
104         }
105         base->connection_count++;
106
107         if (0 == _ctsvc_connection) {
108                 ret = ctsvc_socket_init();
109                 if (ret != CONTACTS_ERROR_NONE) {
110                         /* LCOV_EXCL_START */
111                         ERR("ctsvc_socket_init() Fail(%d)", ret);
112                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
113                         return ret;
114                         /* LCOV_EXCL_STOP */
115                 }
116
117                 ret = ctsvc_inotify_init();
118                 if (ret != CONTACTS_ERROR_NONE) {
119                         /* LCOV_EXCL_START */
120                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
121                         ctsvc_socket_final();
122                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
123                         return ret;
124                         /* LCOV_EXCL_STOP */
125                 }
126                 ctsvc_view_uri_init();
127         } else {
128                 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
129         }
130
131         if (1 == base->connection_count)
132                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
133
134         _ctsvc_connection++;
135         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
136
137         return CONTACTS_ERROR_NONE;
138 }
139
140 int ctsvc_client_disconnect(contacts_h contact)
141 {
142         CTS_FN_CALL;
143         int ret;
144         ctsvc_base_s *base = (ctsvc_base_s*)contact;
145         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
146
147         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
148
149         if (1 == base->connection_count) {
150                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
151                 if (ret != CONTACTS_ERROR_NONE) {
152                         /* LCOV_EXCL_START */
153                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
154                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
155                         return ret;
156                         /* LCOV_EXCL_STOP */
157                 }
158                 ctsvc_inotify_unsubscribe_ipc_ready();
159         }
160         base->connection_count--;
161
162         if (1 == _ctsvc_connection) {
163                 ctsvc_ipc_destroy_for_change_subscription(true);
164                 ctsvc_view_uri_deinit();
165                 ctsvc_inotify_close();
166                 ctsvc_socket_final();
167
168         } else if (1 < _ctsvc_connection) {
169                 DBG("connection count is %d", _ctsvc_connection);
170         } else {
171                 /* LCOV_EXCL_START */
172                 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
173                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
174                 return CONTACTS_ERROR_DB;
175                 /* LCOV_EXCL_STOP */
176         }
177
178         _ctsvc_connection--;
179
180         if (0 == base->connection_count) {
181                 INFO("connection_count is 0. remove handle");
182                 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
183                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
184         }
185         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
186
187         return CONTACTS_ERROR_NONE;
188 }
189
190 int ctsvc_client_connect_on_thread(contacts_h contact)
191 {
192         int ret;
193         ctsvc_base_s *base = (ctsvc_base_s*)contact;
194         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
195
196         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
197
198         if (0 == base->connection_count) {
199                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
200                 if (ret != CONTACTS_ERROR_NONE) {
201                         /* LCOV_EXCL_START */
202                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
203                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
204                         return ret;
205                         /* LCOV_EXCL_STOP */
206                 }
207         }
208         base->connection_count++;
209
210         if (0 == _ctsvc_connection_on_thread) {
211                 ret = ctsvc_socket_init();
212                 if (ret != CONTACTS_ERROR_NONE) {
213                         /* LCOV_EXCL_START */
214                         ERR("ctsvc_socket_init() Fail(%d)", ret);
215                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
216                         return ret;
217                         /* LCOV_EXCL_STOP */
218                 }
219
220                 ret = ctsvc_inotify_init();
221                 if (ret != CONTACTS_ERROR_NONE) {
222                         /* LCOV_EXCL_START */
223                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
224                         ctsvc_socket_final();
225                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
226                         return ret;
227                         /* LCOV_EXCL_STOP */
228                 }
229                 ctsvc_view_uri_init();
230         } else if (0 < _ctsvc_connection_on_thread) {
231                 DBG("System : Contacts service has been already connected");
232         }
233
234         if (1 == base->connection_count)
235                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
236
237         _ctsvc_connection_on_thread++;
238
239         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
240
241         return CONTACTS_ERROR_NONE;
242 }
243
244 int ctsvc_client_disconnect_on_thread(contacts_h contact)
245 {
246         int ret;
247         ctsvc_base_s *base = (ctsvc_base_s*)contact;
248         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
249
250         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
251
252         if (1 == base->connection_count) {
253                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
254                                 _ctsvc_connection_on_thread);
255                 if (ret != CONTACTS_ERROR_NONE) {
256                         /* LCOV_EXCL_START */
257                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
258                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
259                         return ret;
260                         /* LCOV_EXCL_STOP */
261                 }
262                 ctsvc_inotify_unsubscribe_ipc_ready();
263         }
264         base->connection_count--;
265
266         if (1 == _ctsvc_connection_on_thread) {
267                 if (0 == _ctsvc_connection)
268                         ctsvc_ipc_destroy_for_change_subscription(true);
269                 ctsvc_view_uri_deinit();
270                 ctsvc_inotify_close();
271                 ctsvc_socket_final();
272                 DBG("System : connection_on_thread was destroyed successfully");
273         } else if (1 < _ctsvc_connection_on_thread) {
274                 DBG("connection count is %d", _ctsvc_connection_on_thread);
275         } else {
276                 /* LCOV_EXCL_START */
277                 DBG("call contacts_connect_on_thread(), connection count is %d",
278                                 _ctsvc_connection_on_thread);
279                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
280                 return CONTACTS_ERROR_DB;
281                 /* LCOV_EXCL_STOP */
282         }
283
284         _ctsvc_connection_on_thread--;
285
286         if (0 == base->connection_count) {
287                 INFO("connection_count is 0. remove handle");
288                 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
289                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
290         }
291         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
292
293         return CONTACTS_ERROR_NONE;
294 }
295