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