forked from enlightenment/efl
* eio: add eio_file_move (completly asynchronous and non
blocking move). It first try a rename, then fallback to an eio_file_copy + eio_file_unlink. Small example on how to use it : #include <Ecore.h> #include <Eio.h> static void _test_done_cb(void *data) { printf("move done\n"); ecore_main_loop_quit(); } static void _test_error_cb(int error, void *data) { fprintf(stderr, "error: [%s]\n", strerror(error)); ecore_main_loop_quit(); } int main(int argc, char **argv) { Eio_File *cp; if (argc != 3) { fprintf(stderr, "eio_cp source_file destination_file\n"); return -1; } ecore_init(); eio_init(); cp = eio_file_move(argv[1], argv[2], NULL, _test_done_cb, _test_error_cb, NULL); ecore_main_loop_begin(); eio_shutdown(); ecore_shutdown(); return 0; } SVN revision: 52845
This commit is contained in:
parent
9f505cd3d9
commit
7088845157
|
@ -187,11 +187,11 @@ _eio_file_write(int fd, void *mem, ssize_t length)
|
|||
}
|
||||
|
||||
static void
|
||||
_eio_file_copy_send(Ecore_Thread *thread, Eio_File_Copy *copy, off_t current, off_t max)
|
||||
_eio_file_send(Ecore_Thread *thread, Eio_File_Progress *op, off_t current, off_t max)
|
||||
{
|
||||
Eio_Progress *progress;
|
||||
|
||||
if (copy->progress_cb == NULL)
|
||||
if (op->progress_cb == NULL)
|
||||
return ;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
|
@ -205,16 +205,31 @@ _eio_file_copy_send(Ecore_Thread *thread, Eio_File_Copy *copy, off_t current, of
|
|||
progress->current = current;
|
||||
progress->max = max;
|
||||
progress->percent = (float) current * 100.0 / (float) max;
|
||||
progress->source = eina_stringshare_ref(op->source);
|
||||
progress->dest = eina_stringshare_ref(op->dest);
|
||||
|
||||
ecore_thread_feedback(thread, progress);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_progress(Eio_Progress *progress, Eio_File_Progress *op)
|
||||
{
|
||||
op->progress_cb((void *) op->common.data, progress);
|
||||
eina_stringshare_del(progress->source);
|
||||
eina_stringshare_del(progress->dest);
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
eina_trash_push(&trash, progress);
|
||||
trash_count++;
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
#ifndef MAP_HUGETLB
|
||||
# define MAP_HUGETLB 0
|
||||
#endif
|
||||
|
||||
static Eina_Bool
|
||||
_eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out, off_t size)
|
||||
_eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Progress *op, int in, int out, off_t size)
|
||||
{
|
||||
char *m = MAP_FAILED;
|
||||
off_t i;
|
||||
|
@ -242,13 +257,13 @@ _eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out,
|
|||
if (!_eio_file_write(out, m + k, EIO_PACKET_SIZE))
|
||||
goto on_error;
|
||||
|
||||
_eio_file_copy_send(thread, copy, i + j, size);
|
||||
_eio_file_send(thread, op, i + j, size);
|
||||
}
|
||||
|
||||
if (!_eio_file_write(out, m + k, c - k))
|
||||
goto on_error;
|
||||
|
||||
_eio_file_copy_send(thread, copy, i + c, size);
|
||||
_eio_file_send(thread, op, i + c, size);
|
||||
|
||||
munmap(m, EIO_PACKET_SIZE * EIO_PACKET_COUNT);
|
||||
m = MAP_FAILED;
|
||||
|
@ -263,7 +278,7 @@ _eio_file_copy_mmap(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out,
|
|||
|
||||
#ifdef EFL_HAVE_SPLICE
|
||||
static int
|
||||
_eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out, off_t size)
|
||||
_eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Progress *op, int in, int out, off_t size)
|
||||
{
|
||||
int result = 0;
|
||||
off_t count;
|
||||
|
@ -281,7 +296,7 @@ _eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out
|
|||
count = splice(pipefd[0], NULL, out, 0, count, SPLICE_F_MORE | SPLICE_F_MOVE);
|
||||
if (count < 0) goto on_error;
|
||||
|
||||
_eio_file_copy_send(thread, copy, i, size);
|
||||
_eio_file_send(thread, op, i, size);
|
||||
}
|
||||
|
||||
result = 1;
|
||||
|
@ -298,7 +313,7 @@ _eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out
|
|||
static void
|
||||
_eio_file_copy_heavy(Ecore_Thread *thread, void *data)
|
||||
{
|
||||
Eio_File_Copy *copy;
|
||||
Eio_File_Progress *copy;
|
||||
struct stat buf;
|
||||
int result = -1;
|
||||
int in = -1;
|
||||
|
@ -348,21 +363,15 @@ _eio_file_copy_heavy(Ecore_Thread *thread, void *data)
|
|||
static void
|
||||
_eio_file_copy_notify(Ecore_Thread *thread __UNUSED__, void *msg_data, void *data)
|
||||
{
|
||||
Eio_File_Copy *copy = data;
|
||||
Eio_Progress *progress = msg_data;
|
||||
Eio_File_Progress *copy = data;
|
||||
|
||||
copy->progress_cb((void *) copy->common.data, progress);
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
eina_trash_push(&trash, progress);
|
||||
trash_count++;
|
||||
pthread_mutex_unlock(&lock);
|
||||
_eio_file_progress(msg_data, copy);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_copy_end(void *data)
|
||||
{
|
||||
Eio_File_Copy *copy = data;
|
||||
Eio_File_Progress *copy = data;
|
||||
|
||||
copy->common.done_cb((void*) copy->common.data);
|
||||
|
||||
|
@ -374,7 +383,7 @@ _eio_file_copy_end(void *data)
|
|||
static void
|
||||
_eio_file_copy_error(void *data)
|
||||
{
|
||||
Eio_File_Copy *copy = data;
|
||||
Eio_File_Progress *copy = data;
|
||||
|
||||
eio_file_error(©->common);
|
||||
|
||||
|
@ -383,6 +392,130 @@ _eio_file_copy_error(void *data)
|
|||
free(copy);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_copy_progress(void *data, const Eio_Progress *info)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
move->progress.progress_cb((void*) move->progress.common.data, info);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_unlink_done(void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
move->progress.common.done_cb((void*) move->progress.common.data);
|
||||
|
||||
eina_stringshare_del(move->progress.source);
|
||||
eina_stringshare_del(move->progress.dest);
|
||||
free(move);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_unlink_error(int error, void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
move->copy = NULL;
|
||||
|
||||
move->progress.common.error = error;
|
||||
eio_file_error(&move->progress.common);
|
||||
|
||||
eina_stringshare_del(move->progress.source);
|
||||
eina_stringshare_del(move->progress.dest);
|
||||
free(move);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_copy_done(void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
Eio_File *rm;
|
||||
|
||||
rm = eio_file_unlink(move->progress.source,
|
||||
_eio_file_move_unlink_done,
|
||||
_eio_file_move_unlink_error,
|
||||
move);
|
||||
if (rm) move->copy = rm;
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_copy_error(int error, void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
move->progress.common.error = error;
|
||||
eio_file_error(&move->progress.common);
|
||||
|
||||
eina_stringshare_del(move->progress.source);
|
||||
eina_stringshare_del(move->progress.dest);
|
||||
free(move);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_heavy(Ecore_Thread *thread, void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
if (rename(move->progress.source, move->progress.dest) < 0)
|
||||
eio_file_thread_error(&move->progress.common);
|
||||
else
|
||||
_eio_file_send(thread, &move->progress, 1, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_notify(Ecore_Thread *thread __UNUSED__, void *msg_data, void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
_eio_file_progress(msg_data, &move->progress);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_end(void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
move->progress.common.done_cb((void*) move->progress.common.data);
|
||||
|
||||
eina_stringshare_del(move->progress.source);
|
||||
eina_stringshare_del(move->progress.dest);
|
||||
free(move);
|
||||
}
|
||||
|
||||
static void
|
||||
_eio_file_move_error(void *data)
|
||||
{
|
||||
Eio_File_Move *move = data;
|
||||
|
||||
if (move->copy)
|
||||
{
|
||||
eio_file_cancel(move->copy);
|
||||
return ;
|
||||
}
|
||||
|
||||
if (move->progress.common.error == EXDEV)
|
||||
{
|
||||
Eio_File *eio_cp;
|
||||
|
||||
eio_cp = eio_file_copy(move->progress.source, move->progress.dest,
|
||||
move->progress.progress_cb ? _eio_file_move_copy_progress : NULL,
|
||||
_eio_file_move_copy_done,
|
||||
_eio_file_move_copy_error,
|
||||
move);
|
||||
|
||||
if (eio_cp) move->copy = eio_cp;
|
||||
return ;
|
||||
}
|
||||
|
||||
eio_file_error(&move->progress.common);
|
||||
|
||||
eina_stringshare_del(move->progress.source);
|
||||
eina_stringshare_del(move->progress.dest);
|
||||
free(move);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief List content of a directory without locking your app.
|
||||
* @param dir The directory to list.
|
||||
|
@ -508,12 +641,12 @@ eio_file_copy(const char *source,
|
|||
Eio_Error_Cb error_cb,
|
||||
const void *data)
|
||||
{
|
||||
Eio_File_Copy *copy = NULL;
|
||||
Eio_File_Progress *copy = NULL;
|
||||
|
||||
if (!source || !dest || !done_cb || !error_cb)
|
||||
return NULL;
|
||||
|
||||
copy = malloc(sizeof (Eio_File_Copy));
|
||||
copy = malloc(sizeof (Eio_File_Progress));
|
||||
if (!copy) return NULL;
|
||||
|
||||
copy->progress_cb = progress_cb;
|
||||
|
@ -533,3 +666,36 @@ eio_file_copy(const char *source,
|
|||
return ©->common;
|
||||
}
|
||||
|
||||
EAPI Eio_File *
|
||||
eio_file_move(const char *source,
|
||||
const char *dest,
|
||||
Eio_Progress_Cb progress_cb,
|
||||
Eio_Done_Cb done_cb,
|
||||
Eio_Error_Cb error_cb,
|
||||
const void *data)
|
||||
{
|
||||
Eio_File_Move *move = NULL;
|
||||
|
||||
if (!source || !dest || !done_cb || !error_cb)
|
||||
return NULL;
|
||||
|
||||
move = malloc(sizeof (Eio_File_Move));
|
||||
if (!move) return NULL;
|
||||
|
||||
move->progress.progress_cb = progress_cb;
|
||||
move->progress.source = eina_stringshare_add(source);
|
||||
move->progress.dest = eina_stringshare_add(dest);
|
||||
move->copy = NULL;
|
||||
|
||||
if (!eio_long_file_set(&move->progress.common,
|
||||
done_cb,
|
||||
error_cb,
|
||||
data,
|
||||
_eio_file_move_heavy,
|
||||
_eio_file_move_notify,
|
||||
_eio_file_move_end,
|
||||
_eio_file_move_error))
|
||||
return NULL;
|
||||
|
||||
return &move->progress.common;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ typedef struct _Eio_File_Char_Ls Eio_File_Char_Ls;
|
|||
typedef struct _Eio_File_Mkdir Eio_File_Mkdir;
|
||||
typedef struct _Eio_File_Unlink Eio_File_Unlink;
|
||||
typedef struct _Eio_File_Stat Eio_File_Stat;
|
||||
typedef struct _Eio_File_Copy Eio_File_Copy;
|
||||
typedef struct _Eio_File_Progress Eio_File_Progress;
|
||||
typedef struct _Eio_File_Move Eio_File_Move;
|
||||
|
||||
struct _Eio_File
|
||||
{
|
||||
|
@ -79,7 +80,7 @@ struct _Eio_File_Stat
|
|||
const char *path;
|
||||
};
|
||||
|
||||
struct _Eio_File_Copy
|
||||
struct _Eio_File_Progress
|
||||
{
|
||||
Eio_File common;
|
||||
|
||||
|
@ -89,6 +90,13 @@ struct _Eio_File_Copy
|
|||
const char *dest;
|
||||
};
|
||||
|
||||
struct _Eio_File_Move
|
||||
{
|
||||
Eio_File_Progress progress;
|
||||
|
||||
Eio_File *copy;
|
||||
};
|
||||
|
||||
/* Be aware that ecore_thread_run could call cancel_cb if something goes wrong. */
|
||||
Eina_Bool eio_file_set(Eio_File *common,
|
||||
Eio_Done_Cb done_cb,
|
||||
|
|
Loading…
Reference in New Issue