forked from enlightenment/efl
eina: add eina_file_refresh().
This commit is contained in:
parent
5ae4cfd192
commit
4dd259f3b1
|
@ -4,7 +4,7 @@
|
|||
|
||||
2013-07-31 Cedric Bail
|
||||
|
||||
* Eina: add eina_file_virtualize() and eina_file_virtual().
|
||||
* Eina: add eina_file_refresh(), eina_file_virtualize() and eina_file_virtual().
|
||||
* Evas: use eina_file_virtualize() for evas_object_image_memfile_set().
|
||||
|
||||
2013-07-25 ChunEon Park (Hermet)
|
||||
|
|
1
NEWS
1
NEWS
|
@ -35,6 +35,7 @@ Additions:
|
|||
- Add eina_file_map_populate()
|
||||
- Add eina_tiler_empty()
|
||||
- Add eina_file_virtualize() and eina_file_virtual()
|
||||
- Add eina_file_refresh()
|
||||
* Eet:
|
||||
- Add eet_mmap()
|
||||
- Add eet_data_descriptor_name_get()
|
||||
|
|
|
@ -304,11 +304,19 @@ _eina_file_stat_ls_iterator_next(Eina_File_Direct_Iterator *it, void **data)
|
|||
void
|
||||
eina_file_real_close(Eina_File *file)
|
||||
{
|
||||
Eina_File_Map *map;
|
||||
|
||||
if (file->refcount != 0) return;
|
||||
|
||||
eina_hash_free(file->rmap);
|
||||
eina_hash_free(file->map);
|
||||
|
||||
EINA_LIST_FREE(file->dead_map, map)
|
||||
{
|
||||
munmap(map->map, map->length);
|
||||
free(map);
|
||||
}
|
||||
|
||||
if (file->global_map != MAP_FAILED)
|
||||
munmap(file->global_map, file->length);
|
||||
|
||||
|
@ -462,6 +470,19 @@ eina_file_shutdown(void)
|
|||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eina_file_mmap_faulty_one(void *addr, long page_size,
|
||||
Eina_File_Map *m)
|
||||
{
|
||||
if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
|
||||
(((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
|
||||
{
|
||||
m->faulty = EINA_TRUE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
eina_file_mmap_faulty(void *addr, long page_size)
|
||||
{
|
||||
|
@ -497,17 +518,23 @@ eina_file_mmap_faulty(void *addr, long page_size)
|
|||
itm = eina_hash_iterator_data_new(f->map);
|
||||
EINA_ITERATOR_FOREACH(itm, m)
|
||||
{
|
||||
if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
|
||||
(((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
|
||||
{
|
||||
m->faulty = EINA_TRUE;
|
||||
faulty = EINA_TRUE;
|
||||
break;
|
||||
}
|
||||
faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
|
||||
if (faulty) break;
|
||||
}
|
||||
eina_iterator_free(itm);
|
||||
}
|
||||
|
||||
if (!faulty)
|
||||
{
|
||||
Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(f->dead_map, l, m)
|
||||
{
|
||||
faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
|
||||
if (faulty) break;
|
||||
}
|
||||
}
|
||||
|
||||
eina_lock_release(&f->lock);
|
||||
|
||||
if (faulty) break;
|
||||
|
@ -902,6 +929,39 @@ eina_file_open(const char *path, Eina_Bool shared)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_file_refresh(Eina_File *file)
|
||||
{
|
||||
struct stat file_stat;
|
||||
Eina_Bool r = EINA_FALSE;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
||||
|
||||
if (file->virtual) return EINA_FALSE;
|
||||
|
||||
if (fstat(file->fd, &file_stat))
|
||||
return EINA_FALSE;
|
||||
|
||||
if (file->length != (unsigned long int) file_stat.st_size)
|
||||
{
|
||||
eina_file_flush(file, file_stat.st_size);
|
||||
r = EINA_TRUE;
|
||||
}
|
||||
|
||||
file->length = file_stat.st_size;
|
||||
file->mtime = file_stat.st_mtime;
|
||||
#ifdef _STAT_VER_LINUX
|
||||
# if (defined __USE_MISC && defined st_mtime)
|
||||
file->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
|
||||
# else
|
||||
file->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
|
||||
# endif
|
||||
#endif
|
||||
file->inode = file_stat.st_ino;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
|
||||
{
|
||||
|
@ -1048,21 +1108,7 @@ eina_file_map_free(Eina_File *file, void *map)
|
|||
}
|
||||
else
|
||||
{
|
||||
Eina_File_Map *em;
|
||||
unsigned long int key[2];
|
||||
|
||||
em = eina_hash_find(file->rmap, &map);
|
||||
if (!em) goto on_exit;
|
||||
|
||||
em->refcount--;
|
||||
|
||||
if (em->refcount > 0) goto on_exit;
|
||||
|
||||
key[0] = em->offset;
|
||||
key[1] = em->length;
|
||||
|
||||
eina_hash_del(file->rmap, &map, em);
|
||||
eina_hash_del(file->map, &key, em);
|
||||
eina_file_common_map_free(file, map, _eina_file_map_close);
|
||||
}
|
||||
|
||||
on_exit:
|
||||
|
@ -1086,7 +1132,6 @@ eina_file_map_populate(Eina_File *file, Eina_File_Populate rule, void *map,
|
|||
EAPI Eina_Bool
|
||||
eina_file_map_faulted(Eina_File *file, void *map)
|
||||
{
|
||||
Eina_File_Map *em;
|
||||
Eina_Bool r = EINA_FALSE;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
||||
|
@ -1101,8 +1146,24 @@ eina_file_map_faulted(Eina_File *file, void *map)
|
|||
}
|
||||
else
|
||||
{
|
||||
Eina_File_Map *em;
|
||||
|
||||
em = eina_hash_find(file->rmap, &map);
|
||||
if (em) r = em->faulty;
|
||||
if (em)
|
||||
{
|
||||
r = em->faulty;
|
||||
}
|
||||
else
|
||||
{
|
||||
Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(file->dead_map, l, em)
|
||||
if (em->map == map)
|
||||
{
|
||||
r = em->faulty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eina_lock_release(&file->lock);
|
||||
|
|
|
@ -483,6 +483,19 @@ eina_file_virtualize(const void *data, unsigned long long length, Eina_Bool copy
|
|||
EAPI Eina_Bool
|
||||
eina_file_virtual(Eina_File *file) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
/**
|
||||
* @brief Refresh file information
|
||||
*
|
||||
* @param file The file to refresh
|
||||
* @return #EINA_TRUE if the file has changed
|
||||
*
|
||||
* All current map continue to exist. You need to manually delete
|
||||
* and recreate them to have the new correct mapping.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
EAPI Eina_Bool eina_file_refresh(Eina_File *file);
|
||||
|
||||
/**
|
||||
* @brief Dup a read-only handler of a previously open file.
|
||||
*
|
||||
|
|
|
@ -232,6 +232,96 @@ eina_file_virtual_map_free(Eina_File *file, void *map)
|
|||
eina_lock_release(&file->lock);
|
||||
}
|
||||
|
||||
void
|
||||
eina_file_common_map_free(Eina_File *file, void *map,
|
||||
void (*free_func)(Eina_File_Map *map))
|
||||
{
|
||||
Eina_File_Map *em;
|
||||
unsigned long int key[2];
|
||||
Eina_List *l = NULL;
|
||||
Eina_Bool hashed = EINA_TRUE;
|
||||
|
||||
em = eina_hash_find(file->rmap, &map);
|
||||
if (!em)
|
||||
{
|
||||
EINA_LIST_FOREACH(file->dead_map, l, em)
|
||||
if (em->map == map)
|
||||
{
|
||||
hashed = EINA_FALSE;
|
||||
break ;
|
||||
}
|
||||
if (hashed) return ;
|
||||
}
|
||||
|
||||
em->refcount--;
|
||||
|
||||
if (em->refcount > 0) return ;
|
||||
|
||||
key[0] = em->offset;
|
||||
key[1] = em->length;
|
||||
|
||||
if (hashed)
|
||||
{
|
||||
eina_hash_del(file->rmap, &map, em);
|
||||
eina_hash_del(file->map, &key, em);
|
||||
}
|
||||
else
|
||||
{
|
||||
file->dead_map = eina_list_remove_list(file->dead_map, l);
|
||||
free_func(em);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
eina_file_flush(Eina_File *file, unsigned long int length)
|
||||
{
|
||||
Eina_File_Map *tmp;
|
||||
Eina_Iterator *it;
|
||||
Eina_List *dead_map = NULL;
|
||||
Eina_List *l;
|
||||
|
||||
// File size changed
|
||||
if (file->global_map)
|
||||
{
|
||||
// Forget global map
|
||||
tmp = malloc(sizeof (Eina_File_Map));
|
||||
if (tmp)
|
||||
{
|
||||
tmp->map = file->global_map;
|
||||
tmp->offset = 0;
|
||||
tmp->length = file->length;
|
||||
tmp->refcount = file->refcount;
|
||||
|
||||
file->dead_map = eina_list_append(file->dead_map, tmp);
|
||||
}
|
||||
|
||||
file->global_map = NULL;
|
||||
file->refcount = 0;
|
||||
}
|
||||
|
||||
it = eina_hash_iterator_data_new(file->map);
|
||||
EINA_ITERATOR_FOREACH(it, tmp)
|
||||
{
|
||||
// Add out of limit map to dead_map
|
||||
if (tmp->offset + tmp->length > length)
|
||||
dead_map = eina_list_append(dead_map, tmp);
|
||||
}
|
||||
eina_iterator_free(it);
|
||||
|
||||
EINA_LIST_FOREACH(dead_map, l, tmp)
|
||||
{
|
||||
unsigned long int key[2];
|
||||
|
||||
key[0] = tmp->offset;
|
||||
key[1] = tmp->length;
|
||||
|
||||
eina_hash_del(file->rmap, &tmp->map, tmp);
|
||||
eina_hash_del(file->map, &key, tmp);
|
||||
}
|
||||
|
||||
file->dead_map = eina_list_merge(file->dead_map, dead_map);
|
||||
}
|
||||
|
||||
// Private to this file API
|
||||
static void
|
||||
_eina_file_map_close(Eina_File_Map *map)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "eina_file.h"
|
||||
#include "eina_tmpstr.h"
|
||||
#include "eina_lock.h"
|
||||
#include "eina_list.h"
|
||||
|
||||
typedef struct _Eina_File_Map Eina_File_Map;
|
||||
typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
|
||||
|
@ -58,6 +59,8 @@ struct _Eina_File
|
|||
HANDLE fm;
|
||||
#endif
|
||||
|
||||
Eina_List *dead_map;
|
||||
|
||||
Eina_Bool shared : 1;
|
||||
Eina_Bool delete_me : 1;
|
||||
Eina_Bool global_faulty : 1;
|
||||
|
@ -119,6 +122,10 @@ Eina_Bool eina_file_path_relative(const char *path);
|
|||
Eina_Tmpstr *eina_file_current_directory_get(const char *path, size_t len);
|
||||
char *eina_file_cleanup(Eina_Tmpstr *path);
|
||||
void eina_file_real_close(Eina_File *file);
|
||||
void eina_file_flush(Eina_File *file, unsigned long int length);
|
||||
void eina_file_common_map_free(Eina_File *file, void *map,
|
||||
void (*free_func)(Eina_File_Map *map));
|
||||
|
||||
|
||||
extern Eina_Hash *_eina_file_cache;
|
||||
extern Eina_Lock _eina_file_lock_cache;
|
||||
|
|
|
@ -364,9 +364,17 @@ _eina_file_win32_direct_ls_iterator_free(Eina_File_Direct_Iterator *it)
|
|||
void
|
||||
eina_file_real_close(Eina_File *file)
|
||||
{
|
||||
Eina_File_Map *map;
|
||||
|
||||
eina_hash_free(file->rmap);
|
||||
eina_hash_free(file->map);
|
||||
|
||||
EINA_LIST_FREE(file->dead_map, map)
|
||||
{
|
||||
UnmapViewOfFile(map->map);
|
||||
free(map);
|
||||
}
|
||||
|
||||
if (file->global_map != MAP_FAILED)
|
||||
UnmapViewOfFile(file->global_map);
|
||||
|
||||
|
@ -715,6 +723,37 @@ eina_file_stat_ls(const char *dir)
|
|||
return eina_file_direct_ls(dir);
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
eina_file_refresh(Eina_File *file)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA fad;
|
||||
ULARGE_INTEGER length;
|
||||
ULARGE_INTEGER mtime;
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
|
||||
|
||||
if (file->virtual) return EINA_FALSE;
|
||||
|
||||
if (!GetFileAttributesEx(file->filename, GetFileExInfoStandard, &fad))
|
||||
return EINA_FALSE;
|
||||
|
||||
length.u.LowPart = fad.nFileSizeLow;
|
||||
length.u.HighPart = fad.nFileSizeHigh;
|
||||
mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime;
|
||||
mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime;
|
||||
|
||||
if (file->length != length.QuadPart)
|
||||
{
|
||||
eina_file_flush(file, file_stat.st_size);
|
||||
r = EINA_TRUE;
|
||||
}
|
||||
|
||||
n->length = length.QuadPart;
|
||||
n->mtime = mtime.QuadPart;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
EAPI Eina_File *
|
||||
eina_file_open(const char *path, Eina_Bool shared)
|
||||
{
|
||||
|
@ -953,21 +992,7 @@ eina_file_map_free(Eina_File *file, void *map)
|
|||
}
|
||||
else
|
||||
{
|
||||
Eina_File_Map *em;
|
||||
unsigned long int key[2];
|
||||
|
||||
em = eina_hash_find(file->rmap, &map);
|
||||
if (!em) goto on_exit;
|
||||
|
||||
em->refcount--;
|
||||
|
||||
if (em->refcount > 0) goto on_exit;
|
||||
|
||||
key[0] = em->offset;
|
||||
key[1] = em->length;
|
||||
|
||||
eina_hash_del(file->rmap, &map, em);
|
||||
eina_hash_del(file->map, &key, em);
|
||||
eina_file_common_map_free(file, map, _eina_file_map_close);
|
||||
}
|
||||
|
||||
on_exit:
|
||||
|
|
Loading…
Reference in New Issue