Tizen 2.0 Release
[apps/core/preloaded/myfiles.git] / src / common / file-operation / mf-delete.c
1 /*
2  * Copyright 2013         Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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://floralicense.org/license/
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
18
19
20 #include <stdio.h>
21 #include <glib.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <sys/time.h>
27 #include <sys/syscall.h>
28
29 #include "mf-delete.h"
30 #include "mf-delete-internal.h"
31 #include "mf-cancel.h"
32 #include "mf-fo-common.h"
33 #include "mf-fo-internal.h"
34 #include "mf-fo-debug.h"
35 #include "mf-callback.h"
36
37 extern int flagMsg;
38 extern pthread_mutex_t gLockMsg;
39 extern pthread_cond_t gCondMsg;
40
41 struct _mf_del_handle {
42         GList *src_items;
43         mf_cancel *cancel;
44         void *u_data;
45         gboolean sync;
46
47         GMutex *lock;
48         GCond *cond;
49         guint msg_idle_cb;
50
51         mf_fo_msg msg;
52         Ecore_Pipe *pipe;
53 };
54
55 static double get_time(void)
56 {
57         struct timeval timev;
58
59         gettimeofday(&timev, NULL);
60         return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
61 }
62
63 static void __mf_delete_free_handle(struct _mf_del_handle *handle)
64 {
65         if (handle) {
66                 /*free cp_handle*/
67                 if (handle->lock) {
68                         g_mutex_free(handle->lock);
69                 }
70                 if (handle->cond) {
71                         g_cond_free(handle->cond);
72                 }
73                 if (handle->src_items) {
74                         g_list_foreach(handle->src_items, (GFunc)free, NULL);
75                         g_list_free(handle->src_items);
76                 }
77                 if (handle->msg.current_real) {
78                         g_free(handle->msg.current_real);
79                         handle->msg.current_real = NULL;
80                 }
81                 free(handle);
82         }
83
84         return;
85 }
86
87 static gboolean _del_msg_publish(gpointer data)
88 {
89         struct _mf_del_handle *handle = NULL;
90         handle = (struct _mf_del_handle *)data;
91         mf_fo_msg msg;
92
93         if (!handle) {
94                 goto EXIT;
95         }
96         MYFILE_MAGIC_SET(&msg, MYFILE_MAGIC_PIPE_DATA);
97
98         g_mutex_lock(handle->lock);
99         msg.msg_type = handle->msg.msg_type;
100         msg.error_code = handle->msg.error_code;
101         msg.current = handle->msg.current;
102         msg.current_index = handle->msg.current_index;
103         msg.total_index = handle->msg.total_index;
104         msg.current_size = handle->msg.current_size;
105         msg.total_size = handle->msg.total_size;
106         msg.current_real = handle->msg.current_real;
107         msg.pipe = handle->pipe;
108         g_mutex_unlock(handle->lock);
109
110         /*pulish message*/
111         ecore_pipe_write(handle->pipe, &msg, sizeof(msg));
112
113 EXIT:
114         return FALSE;
115 }
116
117 static void _del_msg_cb(mf_msg_type msg_type, const char *real, unsigned long long size, int error_code, void *data)
118 {
119         struct _mf_del_handle *handle = NULL;
120         handle = (struct _mf_del_handle *)data;
121
122         pthread_mutex_lock(&gLockMsg);
123         while (flagMsg == 0) {
124                 mf_fo_loge("!!!!!!!!!!!! wait");
125                 pthread_cond_wait(&gCondMsg, &gLockMsg);
126         }
127         flagMsg = 0;
128         pthread_mutex_unlock(&gLockMsg);
129
130         if (handle) {
131                 g_mutex_lock(handle->lock);
132                 handle->msg.msg_type = msg_type;
133                 if (msg_type == MF_MSG_ERROR) {
134                         handle->msg.error_code = error_code;
135                         if (real) {
136                                 if (handle->msg.current_real) {
137                                         free(handle->msg.current_real);
138                                 }
139                                 handle->msg.current_real = strdup(real);
140                         }
141                 } else {
142                         handle->msg.error_code = 0;
143                         if (msg_type == MF_MSG_DOING) {
144                                 if (real) {
145                                         if (handle->msg.current_real) {
146                                                 free(handle->msg.current_real);
147                                         }
148                                         handle->msg.current_real = strdup(real);
149                                 }
150                                 handle->msg.current_size += size;
151                                 handle->msg.error_code = 0;
152                         } else if (msg_type == MF_MSG_SKIP) {
153                                 handle->msg.total_size -= size;
154                                 handle->msg.error_code = 0;
155                         }
156                 }
157                 g_mutex_unlock(handle->lock);
158
159                 _del_msg_publish(handle);
160         }
161         return;
162 }
163
164
165 static void *delete_thread(void *data)
166 {
167         struct _mf_del_handle *handle = NULL;
168         handle = (struct _mf_del_handle *)data;
169
170         _mf_fo_msg_cb msg_cb = NULL;
171         gboolean cancelled = FALSE;
172         double s_start = 0.0;
173         double s_stop = 0.0;
174         double c_start = 0.0;
175         double c_stop = 0.0;
176         char err_buf[MF_ERR_BUF] = { 0, };
177
178         if (handle) {
179                 GList *tmp_src_list = NULL;
180                 unsigned long long t_size = 0;
181
182                 msg_cb = _del_msg_cb;
183
184                 s_start = get_time();
185                 tmp_src_list = handle->src_items;
186                 while (tmp_src_list) {
187                         if (tmp_src_list->data) {
188                                 const char *s_path = NULL;
189                                 unsigned long long size = 0;
190
191                                 s_path = tmp_src_list->data;
192                                 if (access(s_path, R_OK) == 0) {
193                                         int err = _mf_fo_get_total_item_size(s_path, &size);
194                                         if (err < 0) {
195                                                 mf_fo_loge("Fail to get size of %s", s_path);
196                                                 /*handle->src_items = g_list_remove(handle->src_items, s_path);*/
197
198                                                 _del_msg_cb(MF_MSG_ERROR, s_path, 0, (MF_FO_ERR_SRC_CLASS | _mf_fo_errno_to_mferr(-err)), handle);
199
200                                                 goto ERROR_END_THREAD;
201                                         } else {
202                                                 mf_fo_logi("size of %s - %lld", s_path, size);
203                                                 t_size += size;
204                                         }
205                                 } else {
206                                         MF_FILE_ERROR_LOG(err_buf, "Unable to access ", s_path);
207                                         /*handle->src_items = g_list_remove(handle->src_items, s_path);*/
208
209                                         _del_msg_cb(MF_MSG_ERROR, s_path, 0, (MF_FO_ERR_SRC_CLASS | _mf_fo_errno_to_mferr(errno)), handle);
210
211                                         goto ERROR_END_THREAD;
212                                 }
213                         }
214                         tmp_src_list = g_list_next(tmp_src_list);
215                 }
216                 s_stop = get_time();
217                 g_mutex_lock(handle->lock);
218                 handle->msg.total_size = t_size;
219                 g_mutex_unlock(handle->lock);
220
221                 /*delete items*/
222                 c_start = get_time();
223                 tmp_src_list = handle->src_items;
224                 while (tmp_src_list) {
225                         if (tmp_src_list->data) {
226                                 const char *s_path = NULL;
227                                 s_path = tmp_src_list->data;
228                                 int ret = 0;
229                                 g_mutex_lock(handle->lock);
230                                 handle->msg.current_index++;
231                                 handle->msg.current = s_path;
232                                 g_mutex_unlock(handle->lock);
233                                 ret = _mf_delete_del_internal(s_path, handle->cancel, msg_cb, handle);
234
235                                 if (ret > 0) {
236                                         if (handle->cancel) {
237                                                 mf_cancel_set_cancelled(handle->cancel);
238                                         }
239                                         cancelled = TRUE;
240                                         break;
241                                 }
242                                 if (ret < 0) {
243                                         mf_fo_loge("Fail to delete [%s]", s_path);
244                                 }
245                         }
246                         tmp_src_list = g_list_next(tmp_src_list);
247                 }
248                 c_stop = get_time();
249                 mf_fo_logi("## Total src size - %lld byte, size time : %lf sec, delete time : %lf sec",
250                            handle->msg.total_size, s_stop - s_start, c_stop - c_start);
251
252                 if (cancelled) {
253                         /*cancel message*/
254                         _del_msg_cb(MF_MSG_CANCELLED, NULL, 0, 0, handle);
255                 }
256
257 ERROR_END_THREAD:
258                 if (handle->sync) {
259                         double start = 0.0;
260                         double stop = 0.0;
261                         _del_msg_cb(MF_MSG_SYNC, NULL, 0, 0, handle);
262                         start = get_time();
263                         sync();
264                         stop = get_time();
265                         mf_fo_logi("sync time : %lf sec", stop - start);
266                 }
267
268                 _del_msg_cb(MF_MSG_END, NULL, 0, 0, handle);
269
270                 __mf_delete_free_handle(handle);
271                 handle = NULL;
272         } else {
273                 mf_fo_loga("handle is NULL");
274                 abort();
275         }
276
277         mf_fo_logd("The end of del_thread");
278         return NULL;
279 }
280
281 int mf_delete_items(GList *item_list, mf_cancel *cancel, gboolean sync, void *u_data)
282 {
283         struct _mf_del_handle *handle = NULL;
284         GList *tmp_list = NULL;
285         int err = 0;
286
287         if (!item_list) {
288                 mf_fo_loge("item_list is NULL");
289                 return -(MF_FO_ERR_ARGUMENT);
290         }
291
292         if (!g_thread_supported()) {
293                 g_thread_init(NULL);
294         }
295
296         handle = malloc(sizeof(struct _mf_del_handle));
297         if (!handle) {
298                 mf_fo_loge("Fail to allocate handle");
299                 return -(MF_FO_ERR_MEM);
300         }
301         memset(handle, 0x00, sizeof(struct _mf_del_handle));
302
303         handle->lock = g_mutex_new();
304         if (!handle->lock) {
305                 mf_fo_loge("Fail to allocate mutex");
306                 err = MF_FO_ERR_MEM;
307                 goto ERROR_FREE_MEM;
308         }
309         handle->cond = g_cond_new();
310         if (!handle->cond) {
311                 mf_fo_loge("Fail to allocate cond");
312                 err = MF_FO_ERR_MEM;
313                 goto ERROR_FREE_MEM;
314         }
315
316         handle->cancel = cancel;
317         handle->u_data = u_data;
318         handle->sync = sync;
319         pthread_mutex_lock(&gLockMsg);
320         flagMsg = 1;
321         pthread_mutex_unlock(&gLockMsg);
322
323         tmp_list = item_list;
324         while (tmp_list) {
325                 if (tmp_list->data) {
326                         char *src_item = NULL;
327                         src_item = strdup((char *)tmp_list->data);
328                         if (src_item) {
329                                 if (_mf_fo_check_exist(src_item)) {
330                                         handle->src_items = g_list_append(handle->src_items, src_item);
331                                 } else {
332                                         mf_fo_loge("src_item[%s] is not existed", src_item);
333                                         err = MF_FO_ERR_ARGUMENT;
334                                         free(src_item);
335                                         src_item = NULL;
336                                 }
337                         } else {
338                                 mf_fo_loge("Fail to allocate memory");
339                                 err = MF_FO_ERR_MEM;
340                                 goto ERROR_FREE_MEM;
341                         }
342                 }
343                 tmp_list = g_list_next(tmp_list);
344         }
345
346         if (!handle->src_items) {
347                 mf_fo_loge("Fail to create src list");
348                 err = MF_FO_ERR_ARGUMENT;
349                 goto ERROR_FREE_MEM;
350         }
351
352         handle->pipe = ecore_pipe_add(mf_callback_thread_pipe_cb, u_data);
353
354         if (!g_thread_create((GThreadFunc) delete_thread, handle, FALSE, NULL)) {
355                 mf_fo_loge("Fail to create delete thread");
356                 err = MF_FO_ERR_MEM;
357                 goto ERROR_FREE_MEM;
358         }
359
360         return 0;
361
362 ERROR_FREE_MEM:
363         __mf_delete_free_handle(handle);
364         return -(err);
365 }