eina: add support for in memory only Eina_File.

This commit is contained in:
Cedric Bail 2013-07-31 11:51:51 +09:00
parent 9ffd451029
commit f2de8970a1
7 changed files with 245 additions and 52 deletions

View File

@ -1,3 +1,7 @@
2013-07-31 Cedric Bail
* Eina: add eina_file_virtualize() and eina_file_virtual().
2013-07-25 ChunEon Park (Hermet)
* Evas: Skip the map rendering if all points are transparent.

1
NEWS
View File

@ -34,6 +34,7 @@ Additions:
- Add eina_tiler_area_size_set(), eina_tiler_strict_set(), eina_tiler_area_size_get()
- Add eina_file_map_populate()
- Add eina_tiler_empty()
- Add eina_file_virtualize() and eina_file_virtual()
* Eet:
- Add eet_mmap()
- Add eet_data_descriptor_name_get()

View File

@ -324,27 +324,6 @@ _eina_file_map_close(Eina_File_Map *map)
free(map);
}
static unsigned int
_eina_file_map_key_length(const void *key EINA_UNUSED)
{
return sizeof (unsigned long int) * 2;
}
static int
_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length EINA_UNUSED,
const unsigned long int *key2, int key2_length EINA_UNUSED)
{
if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
return key1[0] - key2[0];
}
static int
_eina_file_map_key_hash(const unsigned long int *key, int key_length EINA_UNUSED)
{
return eina_hash_int64(&key[0], sizeof (unsigned long int))
^ eina_hash_int64(&key[1], sizeof (unsigned long int));
}
#ifndef MAP_POPULATE
static unsigned int
_eina_file_map_populate(char *map, unsigned int size, Eina_Bool hugetlb)
@ -880,9 +859,9 @@ eina_file_open(const char *path, Eina_Bool shared)
memset(n, 0, sizeof(Eina_File));
n->filename = (char*) (n + 1);
strcpy((char*) n->filename, filename);
n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
EINA_KEY_CMP(_eina_file_map_key_cmp),
EINA_KEY_HASH(_eina_file_map_key_hash),
n->map = eina_hash_new(EINA_KEY_LENGTH(eina_file_map_key_length),
EINA_KEY_CMP(eina_file_map_key_cmp),
EINA_KEY_HASH(eina_file_map_key_hash),
EINA_FREE_CB(_eina_file_map_close),
3);
n->rmap = eina_hash_pointer_new(NULL);
@ -931,7 +910,9 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
// bsd people will lack this feature
if (file->virtual) return eina_file_virtual_map_all(file);
// bsd people will lack this feature
#ifdef MAP_POPULATE
if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
#endif
@ -984,6 +965,9 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
if (offset == 0 && length == file->length)
return eina_file_map_all(file, rule);
if (file->virtual)
return eina_file_virtual_map_new(file, offset, length);
key[0] = offset;
key[1] = length;
@ -1048,6 +1032,9 @@ eina_file_map_free(Eina_File *file, void *map)
{
EINA_SAFETY_ON_NULL_RETURN(file);
if (file->virtual)
return eina_file_virtual_map_free(file, map);
eina_lock_take(&file->lock);
if (file->global_map == map)
@ -1104,6 +1091,8 @@ eina_file_map_faulted(Eina_File *file, void *map)
EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
if (file->virtual) return EINA_FALSE;
eina_lock_take(&file->lock);
if (file->global_map == map)
@ -1126,6 +1115,8 @@ eina_file_xattr_get(Eina_File *file)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
if (file->virtual) return NULL;
return eina_xattr_fd_ls(file->fd);
}
@ -1134,6 +1125,8 @@ eina_file_xattr_value_get(Eina_File *file)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
if (file->virtual) return NULL;
return eina_xattr_value_fd_ls(file->fd);
}

View File

@ -444,8 +444,6 @@ typedef enum {
*/
EAPI Eina_Bool eina_file_copy(const char *src, const char *dst, Eina_File_Copy_Flags flags, Eina_File_Copy_Progress cb, const void *cb_data) EINA_ARG_NONNULL(1, 2);
/**
* @brief Get a read-only handler to a file.
*
@ -461,6 +459,30 @@ EAPI Eina_Bool eina_file_copy(const char *src, const char *dst, Eina_File_Copy_F
*/
EAPI Eina_File *eina_file_open(const char *name, Eina_Bool shared) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
/**
* @brief Create a virtual file from a memory pointer.
*
* @param data The memory pointer to take data from
* @param length The length of the data in memory
* @param copy #EINA_TRUE if the data must be copied
* @return Eina_File handle to the file
*
* @since 1.8
*/
EAPI Eina_File *
eina_file_virtualize(const void *data, unsigned long long length, Eina_Bool copy) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
/**
* @brief Tell if a file is a real file or only exist in memory
*
* @param file The file to test
* @return #EINA_TRUE if the file is a virtual file
*
* @since 1.8
*/
EAPI Eina_Bool
eina_file_virtual(Eina_File *file) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
/**
* @brief Dup a read-only handler of a previously open file.
*

View File

@ -129,6 +129,116 @@ _eina_file_escape(char *path, size_t len)
return result;
}
unsigned int
eina_file_map_key_length(const void *key EINA_UNUSED)
{
return sizeof (unsigned long int) * 2;
}
int
eina_file_map_key_cmp(const unsigned long int *key1, int key1_length EINA_UNUSED,
const unsigned long int *key2, int key2_length EINA_UNUSED)
{
if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
return key1[0] - key2[0];
}
int
eina_file_map_key_hash(const unsigned long int *key, int key_length EINA_UNUSED)
{
return eina_hash_int64(&key[0], sizeof (unsigned long int))
^ eina_hash_int64(&key[1], sizeof (unsigned long int));
}
void *
eina_file_virtual_map_all(Eina_File *file)
{
eina_lock_take(&file->lock);
file->global_refcount++;
eina_lock_release(&file->lock);
return file->global_map;
}
void *
eina_file_virtual_map_new(Eina_File *file,
unsigned long int offset, unsigned long int length)
{
Eina_File_Map *map;
unsigned long int key[2];
// offset and length has already been checked by the caller function
key[0] = offset;
key[1] = length;
eina_lock_take(&file->lock);
map = eina_hash_find(file->map, &key);
if (!map)
{
map = malloc(sizeof (Eina_File_Map));
goto on_error;
map->map = ((char*) file->global_map) + offset;
map->offset = offset;
map->length = length;
map->refcount = 0;
eina_hash_add(file->map, &key, map);
eina_hash_direct_add(file->rmap, map->map, map);
}
map->refcount++;
on_error:
eina_lock_release(&file->lock);
return map ? map->map : NULL;
}
void
eina_file_virtual_map_free(Eina_File *file, void *map)
{
Eina_File_Map *em;
eina_lock_take(&file->lock);
// map could equal global_map even if length != file->length
em = eina_hash_find(file->rmap, &map);
if (em)
{
unsigned long int key[2];
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);
}
else
{
if (file->global_map == map)
{
file->global_refcount--;
}
}
on_exit:
eina_lock_release(&file->lock);
}
// Private to this file API
static void
_eina_file_map_close(Eina_File_Map *map)
{
free(map);
}
// Global API
EAPI char *
@ -152,10 +262,71 @@ eina_file_path_sanitize(const char *path)
return _eina_file_escape(eina_file_cleanup(result), len);
}
EAPI Eina_File *
eina_file_virtualize(const void *data, unsigned long long length, Eina_Bool copy)
{
Eina_File *file;
Eina_Nano_Time tp;
long int ti;
const char *tmpname = "/dev/mem/virtual\\/%16x";
// Generate an almost uniq filename based on current nsec time.
if (_eina_time_get(&tp)) return NULL;
ti = _eina_time_convert(&tp);
file = malloc(sizeof (Eina_File) +
strlen(tmpname) + 17 +
(copy ? length : 0));
if (!file) return NULL;
memset(file, 0, sizeof(Eina_File));
file->filename = (char*) (file + 1);
sprintf((char*) file->filename, tmpname, ti);
eina_lock_new(&file->lock);
file->mtime = ti / 1000;
file->length = length;
file->mtime_nsec = ti;
file->refcount = 1;
file->fd = -1;
file->virtual = EINA_TRUE;
file->map = eina_hash_new(EINA_KEY_LENGTH(eina_file_map_key_length),
EINA_KEY_CMP(eina_file_map_key_cmp),
EINA_KEY_HASH(eina_file_map_key_hash),
EINA_FREE_CB(_eina_file_map_close),
3);
file->rmap = eina_hash_pointer_new(NULL);
if (copy)
{
file->global_map = (void*)(file->filename +
strlen(file->filename) + 1);
memcpy((char*) file->global_map, data, length);
}
else
{
file->global_map = (void*) data;
}
return file;
}
EAPI Eina_Bool
eina_file_virtual(Eina_File *file)
{
if (file) return file->virtual;
return EINA_FALSE;
}
EAPI Eina_File *
eina_file_dup(Eina_File *file)
{
if (file) file->refcount++;
if (file)
{
eina_lock_take(&file->lock);
file->refcount++;
eina_lock_release(&file->lock);
}
return file;
}

View File

@ -61,6 +61,7 @@ struct _Eina_File
Eina_Bool shared : 1;
Eina_Bool delete_me : 1;
Eina_Bool global_faulty : 1;
Eina_Bool virtual : 1;
};
struct _Eina_File_Map
@ -123,4 +124,16 @@ extern Eina_Hash *_eina_file_cache;
extern Eina_Lock _eina_file_lock_cache;
extern int _eina_file_log_dom;
// Common function to handle virtual file
void *eina_file_virtual_map_all(Eina_File *file);
void *eina_file_virtual_map_new(Eina_File *file,
unsigned long int offset, unsigned long int length);
void eina_file_virtual_map_free(Eina_File *file, void *map);
// Common hash function
unsigned int eina_file_map_key_length(const void *key);
int eina_file_map_key_cmp(const unsigned long int *key1, int key1_length,
const unsigned long int *key2, int key2_length);
int eina_file_map_key_hash(const unsigned long int *key, int key_length);
#endif /* EINA_FILE_COMMON_H_ */

View File

@ -384,27 +384,6 @@ _eina_file_map_close(Eina_File_Map *map)
free(map);
}
static unsigned int
_eina_file_map_key_length(const void *key EINA_UNUSED)
{
return sizeof (unsigned long int) * 2;
}
static int
_eina_file_map_key_cmp(const unsigned long int *key1, int key1_length EINA_UNUSED,
const unsigned long int *key2, int key2_length EINA_UNUSED)
{
if (key1[0] - key2[0] == 0) return key1[1] - key2[1];
return key1[0] - key2[0];
}
static int
_eina_file_map_key_hash(const unsigned long int *key, int key_length EINA_UNUSED)
{
return eina_hash_int64(&key[0], sizeof (unsigned long int))
^ eina_hash_int64(&key[1], sizeof (unsigned long int));
}
/**
* @endcond
*/
@ -804,9 +783,9 @@ eina_file_open(const char *path, Eina_Bool shared)
memset(n, 0, sizeof(Eina_File));
n->filename = (char*) (n + 1);
strcpy((char*) n->filename, filename);
n->map = eina_hash_new(EINA_KEY_LENGTH(_eina_file_map_key_length),
EINA_KEY_CMP(_eina_file_map_key_cmp),
EINA_KEY_HASH(_eina_file_map_key_hash),
n->map = eina_hash_new(EINA_KEY_LENGTH(eina_file_map_key_length),
EINA_KEY_CMP(eina_file_map_key_cmp),
EINA_KEY_HASH(eina_file_map_key_hash),
EINA_FREE_CB(_eina_file_map_close),
3);
n->rmap = eina_hash_pointer_new(NULL);
@ -859,6 +838,8 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule EINA_UNUSED)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
if (file->virtual) return eina_file_virtual_map_all(file);
eina_lock_take(&file->lock);
if (file->global_map == MAP_FAILED)
{
@ -875,6 +856,7 @@ eina_file_map_all(Eina_File *file, Eina_File_Populate rule EINA_UNUSED)
if (file->global_map != MAP_FAILED)
{
file->global_refcount++;
eina_lock_release(&file->lock);
return file->global_map;
}
@ -899,6 +881,9 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
if (offset == 0 && length == file->length)
return eina_file_map_all(file, rule);
if (file->virtual)
return eina_file_virtual_map_new(file, offset, length);
key[0] = offset;
key[1] = length;
@ -952,6 +937,9 @@ eina_file_map_free(Eina_File *file, void *map)
{
EINA_SAFETY_ON_NULL_RETURN(file);
if (file->virtual)
return eina_file_virtual_map_free(file, map);
eina_lock_take(&file->lock);
if (file->global_map == map)
@ -989,6 +977,7 @@ eina_file_map_free(Eina_File *file, void *map)
EAPI Eina_Bool
eina_file_map_faulted(Eina_File *file, void *map)
{
if (file->virtual) return EINA_FALSE;
/*
* FIXME:
* vc++ : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366801%28v=vs.85%29.aspx