2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
27 #include <sys/syscall.h>
30 #include "mf-move-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"
38 extern pthread_mutex_t gLockMsg;
39 extern pthread_cond_t gCondMsg;
41 struct _mf_move_handle {
56 static double __mf_move_get_time(void)
60 gettimeofday(&timev, NULL);
61 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
64 static void __mf_move_free_handle(struct _mf_move_handle *handle)
68 g_mutex_free(handle->lock);
71 g_cond_free(handle->cond);
73 if (handle->dst_dir) {
74 free(handle->dst_dir);
76 if (handle->src_items) {
77 g_list_foreach(handle->src_items, (GFunc) free, NULL);
78 g_list_free(handle->src_items);
80 if (handle->msg.current_real) {
81 g_free(handle->msg.current_real);
82 handle->msg.current_real = NULL;
90 static gboolean __mf_move_msg_publish(gpointer data)
92 struct _mf_move_handle *handle = NULL;
93 handle = (struct _mf_move_handle *)data;
99 MYFILE_MAGIC_SET(&msg, MYFILE_MAGIC_PIPE_DATA);
101 g_mutex_lock(handle->lock);
102 msg.msg_type = handle->msg.msg_type;
103 msg.error_code = handle->msg.error_code;
104 msg.current = handle->msg.current;
105 msg.current_index = handle->msg.current_index;
106 msg.total_index = handle->msg.total_index;
107 msg.current_size = handle->msg.current_size;
108 msg.total_size = handle->msg.total_size;
109 msg.current_real = handle->msg.current_real;
111 msg.pipe = handle->pipe;
112 g_mutex_unlock(handle->lock);
114 ecore_pipe_write(handle->pipe, &msg, sizeof(msg));
120 static void __mf_move_msg_cb(mf_msg_type msg_type, const char *real, unsigned long long size, int error_code, void *data)
122 struct _mf_move_handle *handle = NULL;
123 handle = (struct _mf_move_handle *)data;
125 pthread_mutex_lock(&gLockMsg);
126 while (flagMsg == 0) {
127 mf_fo_loge("!!!!!!!!!!!! wait");
128 pthread_cond_wait(&gCondMsg, &gLockMsg);
131 pthread_mutex_unlock(&gLockMsg);
134 g_mutex_lock(handle->lock);
135 handle->msg.msg_type = msg_type;
136 if (msg_type == MF_MSG_ERROR) {
137 handle->msg.error_code = error_code;
139 if (handle->msg.current_real) {
140 free(handle->msg.current_real);
142 handle->msg.current_real = strdup(real);
145 handle->msg.error_code = 0;
146 if (msg_type == MF_MSG_DOING) {
148 if (handle->msg.current_real) {
149 free(handle->msg.current_real);
151 handle->msg.current_real = strdup(real);
153 handle->msg.current_size += size;
154 handle->msg.error_code = 0;
155 } else if (msg_type == MF_MSG_SKIP) {
156 handle->msg.total_size -= size;
157 handle->msg.error_code = 0;
160 g_mutex_unlock(handle->lock);
161 __mf_move_msg_publish(handle);
166 static gboolean __mf_move_req_msg_callback(gpointer data)
170 struct _mf_move_handle *mv_handle = NULL;
171 mv_handle = (struct _mf_move_handle *)data;
173 memset(&msg, 0, sizeof(mf_fo_msg));
175 MYFILE_MAGIC_SET(&msg, MYFILE_MAGIC_PIPE_DATA);
180 g_mutex_lock(mv_handle->lock);
181 msg.msg_type = MF_MSG_REQUEST;
182 msg.error_code = mv_handle->msg.error_code;
183 msg.current = mv_handle->msg.current;
184 msg.current_index = mv_handle->msg.current_index;
185 msg.total_index = mv_handle->msg.total_index;
186 msg.current_size = mv_handle->msg.current_size;
187 msg.total_size = mv_handle->msg.total_size;
188 msg.current_real = mv_handle->msg.current_real;
189 msg.request = mv_handle->req;
190 g_mutex_unlock(mv_handle->lock);
191 ecore_pipe_write(mv_handle->pipe, &msg, sizeof(msg));
199 static void __mf_move_req_cb(mf_fo_request *req, void *data)
201 struct _mf_move_handle *handle = NULL;
202 handle = (struct _mf_move_handle *)data;
207 mf_request_set_cond(req, handle->cond);
208 __mf_move_req_msg_callback(handle);
209 g_mutex_lock(handle->lock);
210 while (mf_request_flag_get(req)) {
211 g_cond_wait(handle->cond, handle->lock);
213 mf_request_flag_set(req, 1);
214 g_mutex_unlock(handle->lock);
219 static void *__mf_move_thread_func(void *data)
221 struct _mf_move_handle *handle = NULL;
222 handle = (struct _mf_move_handle *)data;
224 gboolean cancelled = FALSE;
225 double s_start = 0.0;
227 double c_start = 0.0;
229 char err_buf[MF_ERR_BUF] = {0,};
232 GList *tmp_src_list = NULL;
233 unsigned long long t_size = 0;
234 unsigned long long r_size = 0;
235 unsigned long long n_size = 0;
237 struct stat dst_info;
239 errcode = _mf_fo_get_remain_space(handle->dst_dir, &r_size);
242 __mf_move_msg_cb(MF_MSG_ERROR, handle->dst_dir, 0, (MF_FO_ERR_DST_CLASS | _mf_fo_errno_to_mferr(-errcode)), handle);
244 goto ERROR_END_THREAD;
249 int err = MF_FO_ERR_SET(MF_FO_ERR_DST_CLASS | MF_FO_ERR_SPACE);
250 __mf_move_msg_cb(MF_MSG_ERROR, handle->dst_dir, 0, err, handle);
252 goto ERROR_END_THREAD;
257 if (stat(handle->dst_dir, &dst_info)) {
259 __mf_move_msg_cb(MF_MSG_ERROR, handle->dst_dir, 0, (MF_FO_ERR_DST_CLASS | _mf_fo_errno_to_mferr(errno)), handle);
261 goto ERROR_END_THREAD;
264 s_start = __mf_move_get_time();
265 tmp_src_list = handle->src_items;
266 while (tmp_src_list) {
267 if (tmp_src_list->data) {
268 const char *s_path = NULL;
269 unsigned long long size = 0;
271 s_path = tmp_src_list->data;
272 if (access(s_path, R_OK) == 0) {
273 errcode = _mf_fo_get_total_item_size(s_path, &size);
275 mf_fo_loge("Fail to get size of %s", s_path);
277 __mf_move_msg_cb(MF_MSG_ERROR, s_path, 0,
278 (MF_FO_ERR_SRC_CLASS | _mf_fo_errno_to_mferr(-errcode)), handle);
281 goto ERROR_END_THREAD;
283 struct stat src_info;
284 mf_fo_logi("size of %s - %lld", s_path, size);
287 if (stat(s_path, &src_info)) {
289 __mf_move_msg_cb(MF_MSG_ERROR, handle->dst_dir, 0,
290 (MF_FO_ERR_DST_CLASS | _mf_fo_errno_to_mferr(errno)), handle);
292 goto ERROR_END_THREAD;
295 if (dst_info.st_dev != src_info.st_dev) {
299 mf_fo_loge("remain size [%lld], needed size [%lld], current item size [%lld] -[%s]",
300 r_size, n_size, size, s_path);
303 int err = MF_FO_ERR_SET(MF_FO_ERR_DST_CLASS | MF_FO_ERR_SPACE);
304 __mf_move_msg_cb(MF_MSG_ERROR, handle->dst_dir, 0, err, handle);
306 goto ERROR_END_THREAD;
311 MF_FILE_ERROR_LOG(err_buf, "Unable to access", s_path);
313 __mf_move_msg_cb(MF_MSG_ERROR, s_path, 0, (MF_FO_ERR_SRC_CLASS | _mf_fo_errno_to_mferr(errno)), handle);
315 goto ERROR_END_THREAD;
318 tmp_src_list = g_list_next(tmp_src_list);
320 s_stop = __mf_move_get_time();
321 g_mutex_lock(handle->lock);
322 handle->msg.total_size = t_size;
323 g_mutex_unlock(handle->lock);
325 mf_fo_logi("total size [%lld], remain size [%lld] -[%s]", t_size, r_size, handle->dst_dir);
327 c_start = __mf_move_get_time();
328 tmp_src_list = handle->src_items;
329 while (tmp_src_list) {
330 if (tmp_src_list->data) {
331 const char *s_path = NULL;
332 s_path = tmp_src_list->data;
334 g_mutex_lock(handle->lock);
335 handle->msg.current_index++;
336 handle->msg.current = s_path;
337 g_mutex_unlock(handle->lock);
338 ret = _mf_move_move_internal(s_path, handle->dst_dir, handle->cancel, __mf_move_req_cb, __mf_move_msg_cb, handle);
341 if (handle->cancel) {
342 mf_cancel_set_cancelled(handle->cancel);
348 mf_fo_loge("Fail to move [%s] to [%s]", s_path, handle->dst_dir);
352 tmp_src_list = g_list_next(tmp_src_list);
355 c_stop = __mf_move_get_time();
356 mf_fo_logi("## Total src size - %lld byte, size time : %lf sec, move time : %lf sec",
357 handle->msg.total_size, s_stop - s_start, c_stop - c_start);
360 __mf_move_msg_cb(MF_MSG_CANCELLED, NULL, 0, 0, handle);
368 __mf_move_msg_cb(MF_MSG_SYNC, NULL, 0, 0, handle);
369 start = __mf_move_get_time();
371 stop = __mf_move_get_time();
372 mf_fo_logi("sync time : %lf sec", stop - start);
375 __mf_move_msg_cb(MF_MSG_END, NULL, 0, 0, handle);
377 __mf_move_free_handle(handle);
380 mf_fo_loge("handle is NULL");
384 mf_fo_logd("The end of __mf_move_thread_func");
389 int mf_move_move_items(GList *item_list, const char *dst_dir, mf_cancel *cancel, gboolean sync, void *u_data)
391 struct _mf_move_handle *handle = NULL;
392 GList *tmp_list = NULL;
396 mf_fo_loge("item_list is NULL");
397 return -(MF_FO_ERR_ARGUMENT);
400 mf_fo_loge("dst_dir is NULL");
401 return -(MF_FO_ERR_ARGUMENT);
404 if (!_mf_fo_check_exist(dst_dir)) {
405 mf_fo_loge("dst_dir[%s] is not existed", dst_dir);
406 return -(MF_FO_ERR_ARGUMENT);
409 if (!g_thread_supported()) {
413 handle = malloc(sizeof(struct _mf_move_handle));
415 mf_fo_loge("Fail to allocate handle");
416 return -(MF_FO_ERR_MEM);
418 memset(handle, 0x00, sizeof(struct _mf_move_handle));
420 handle->lock = g_mutex_new();
422 mf_fo_loge("Fail to allocate mutex");
426 handle->cond = g_cond_new();
428 mf_fo_loge("Fail to allocate cond");
433 handle->dst_dir = strdup(dst_dir);
434 if (!handle->dst_dir) {
435 mf_fo_loge("Fail to allocate memory");
439 handle->cancel = cancel;
440 handle->u_data = u_data;
443 pthread_mutex_lock(&gLockMsg);
445 pthread_mutex_unlock(&gLockMsg);
447 tmp_list = item_list;
449 if (tmp_list->data) {
450 char *src_item = NULL;
451 src_item = strdup((char *)tmp_list->data);
453 if (_mf_fo_check_exist(src_item)) {
454 handle->src_items = g_list_append(handle->src_items, src_item);
456 mf_fo_loge("src_item[%s] is not existed", src_item);
457 err = MF_FO_ERR_ARGUMENT;
462 mf_fo_loge("Fail to allocate memory");
467 tmp_list = g_list_next(tmp_list);
470 if (!handle->src_items) {
471 mf_fo_loge("Fail to create src list");
472 err = MF_FO_ERR_ARGUMENT;
476 handle->pipe = ecore_pipe_add(mf_callback_thread_pipe_cb, u_data);
477 if (!g_thread_create((GThreadFunc) __mf_move_thread_func, handle, FALSE, NULL)) {
478 mf_fo_loge("Fail to create move thread");
486 __mf_move_free_handle(handle);