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
|
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;
|
Eio_Progress *progress;
|
||||||
|
|
||||||
if (copy->progress_cb == NULL)
|
if (op->progress_cb == NULL)
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
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->current = current;
|
||||||
progress->max = max;
|
progress->max = max;
|
||||||
progress->percent = (float) current * 100.0 / (float) 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);
|
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
|
#ifndef MAP_HUGETLB
|
||||||
# define MAP_HUGETLB 0
|
# define MAP_HUGETLB 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Eina_Bool
|
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;
|
char *m = MAP_FAILED;
|
||||||
off_t i;
|
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))
|
if (!_eio_file_write(out, m + k, EIO_PACKET_SIZE))
|
||||||
goto on_error;
|
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))
|
if (!_eio_file_write(out, m + k, c - k))
|
||||||
goto on_error;
|
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);
|
munmap(m, EIO_PACKET_SIZE * EIO_PACKET_COUNT);
|
||||||
m = MAP_FAILED;
|
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
|
#ifdef EFL_HAVE_SPLICE
|
||||||
static int
|
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;
|
int result = 0;
|
||||||
off_t count;
|
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);
|
count = splice(pipefd[0], NULL, out, 0, count, SPLICE_F_MORE | SPLICE_F_MOVE);
|
||||||
if (count < 0) goto on_error;
|
if (count < 0) goto on_error;
|
||||||
|
|
||||||
_eio_file_copy_send(thread, copy, i, size);
|
_eio_file_send(thread, op, i, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = 1;
|
result = 1;
|
||||||
|
@ -298,7 +313,7 @@ _eio_file_copy_splice(Ecore_Thread *thread, Eio_File_Copy *copy, int in, int out
|
||||||
static void
|
static void
|
||||||
_eio_file_copy_heavy(Ecore_Thread *thread, void *data)
|
_eio_file_copy_heavy(Ecore_Thread *thread, void *data)
|
||||||
{
|
{
|
||||||
Eio_File_Copy *copy;
|
Eio_File_Progress *copy;
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
int result = -1;
|
int result = -1;
|
||||||
int in = -1;
|
int in = -1;
|
||||||
|
@ -348,21 +363,15 @@ _eio_file_copy_heavy(Ecore_Thread *thread, void *data)
|
||||||
static void
|
static void
|
||||||
_eio_file_copy_notify(Ecore_Thread *thread __UNUSED__, void *msg_data, void *data)
|
_eio_file_copy_notify(Ecore_Thread *thread __UNUSED__, void *msg_data, void *data)
|
||||||
{
|
{
|
||||||
Eio_File_Copy *copy = data;
|
Eio_File_Progress *copy = data;
|
||||||
Eio_Progress *progress = msg_data;
|
|
||||||
|
|
||||||
copy->progress_cb((void *) copy->common.data, progress);
|
_eio_file_progress(msg_data, copy);
|
||||||
|
|
||||||
pthread_mutex_lock(&lock);
|
|
||||||
eina_trash_push(&trash, progress);
|
|
||||||
trash_count++;
|
|
||||||
pthread_mutex_unlock(&lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_eio_file_copy_end(void *data)
|
_eio_file_copy_end(void *data)
|
||||||
{
|
{
|
||||||
Eio_File_Copy *copy = data;
|
Eio_File_Progress *copy = data;
|
||||||
|
|
||||||
copy->common.done_cb((void*) copy->common.data);
|
copy->common.done_cb((void*) copy->common.data);
|
||||||
|
|
||||||
|
@ -374,7 +383,7 @@ _eio_file_copy_end(void *data)
|
||||||
static void
|
static void
|
||||||
_eio_file_copy_error(void *data)
|
_eio_file_copy_error(void *data)
|
||||||
{
|
{
|
||||||
Eio_File_Copy *copy = data;
|
Eio_File_Progress *copy = data;
|
||||||
|
|
||||||
eio_file_error(©->common);
|
eio_file_error(©->common);
|
||||||
|
|
||||||
|
@ -383,6 +392,130 @@ _eio_file_copy_error(void *data)
|
||||||
free(copy);
|
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.
|
* @brief List content of a directory without locking your app.
|
||||||
* @param dir The directory to list.
|
* @param dir The directory to list.
|
||||||
|
@ -508,12 +641,12 @@ eio_file_copy(const char *source,
|
||||||
Eio_Error_Cb error_cb,
|
Eio_Error_Cb error_cb,
|
||||||
const void *data)
|
const void *data)
|
||||||
{
|
{
|
||||||
Eio_File_Copy *copy = NULL;
|
Eio_File_Progress *copy = NULL;
|
||||||
|
|
||||||
if (!source || !dest || !done_cb || !error_cb)
|
if (!source || !dest || !done_cb || !error_cb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
copy = malloc(sizeof (Eio_File_Copy));
|
copy = malloc(sizeof (Eio_File_Progress));
|
||||||
if (!copy) return NULL;
|
if (!copy) return NULL;
|
||||||
|
|
||||||
copy->progress_cb = progress_cb;
|
copy->progress_cb = progress_cb;
|
||||||
|
@ -533,3 +666,36 @@ eio_file_copy(const char *source,
|
||||||
return ©->common;
|
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_Mkdir Eio_File_Mkdir;
|
||||||
typedef struct _Eio_File_Unlink Eio_File_Unlink;
|
typedef struct _Eio_File_Unlink Eio_File_Unlink;
|
||||||
typedef struct _Eio_File_Stat Eio_File_Stat;
|
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
|
struct _Eio_File
|
||||||
{
|
{
|
||||||
|
@ -79,7 +80,7 @@ struct _Eio_File_Stat
|
||||||
const char *path;
|
const char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Eio_File_Copy
|
struct _Eio_File_Progress
|
||||||
{
|
{
|
||||||
Eio_File common;
|
Eio_File common;
|
||||||
|
|
||||||
|
@ -89,6 +90,13 @@ struct _Eio_File_Copy
|
||||||
const char *dest;
|
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. */
|
/* Be aware that ecore_thread_run could call cancel_cb if something goes wrong. */
|
||||||
Eina_Bool eio_file_set(Eio_File *common,
|
Eina_Bool eio_file_set(Eio_File *common,
|
||||||
Eio_Done_Cb done_cb,
|
Eio_Done_Cb done_cb,
|
||||||
|
|
Loading…
Reference in New Issue