On Thu, 14 Apr 2011, Vincent Torri wrote:

>
>
> eina_file_size_get() returns an unsigned_long, but on Win64, it's of size
> 32 bits. Can't you return a uint_64_t ?

or size_t ?

>
> Vincent
>
> On Wed, 13 Apr 2011, Enlightenment SVN wrote:
>
>> Log:
>> eina: add Eina_File API.
>>
>>  NOTE: the purpose of this API is to replace mmap user in the
>>  EFL, share cache and more code across them. The potential user
>>  are eet, evas, efreet, eio and enlil. More patch are needed for
>>  them to use this infra. Help welcome :-)
>>
>>  NOTE2: this API also need more test and is waiting for some
>>  more pthread infra before being thread safe. But at the end
>>  it will be thread safe if eina thread safety is requested.
>>
>>
>> Author:       cedric
>> Date:         2011-04-13 09:15:30 -0700 (Wed, 13 Apr 2011)
>> New Revision: 58637
>> Trac:         http://trac.enlightenment.org/e/changeset/58637
>>
>> Modified:
>>  trunk/eina/ChangeLog trunk/eina/src/include/eina_file.h 
>> trunk/eina/src/lib/eina_file.c trunk/eina/src/lib/eina_main.c
>>
>> Modified: trunk/eina/ChangeLog
>> ===================================================================
>> --- trunk/eina/ChangeLog     2011-04-13 13:29:54 UTC (rev 58636)
>> +++ trunk/eina/ChangeLog     2011-04-13 16:15:30 UTC (rev 58637)
>> @@ -47,3 +47,8 @@
>>      * Add eina_inlist_sort.
>>      * Add eina_mempool_repack.
>>      * Add Eina_Object API.
>> +
>> +2011-05-13  Cedric Bail & Vincent Torri
>> +
>> +    * Add Eina_File API.
>> +
>>
>> Modified: trunk/eina/src/include/eina_file.h
>> ===================================================================
>> --- trunk/eina/src/include/eina_file.h       2011-04-13 13:29:54 UTC (rev 
>> 58636)
>> +++ trunk/eina/src/include/eina_file.h       2011-04-13 16:15:30 UTC (rev 
>> 58637)
>> @@ -81,6 +81,15 @@
>>   EINA_FILE_WHT      /**< Whiteout file type (unused on Windows). */
>> } Eina_File_Type;
>>
>> +typedef struct _Eina_File Eina_File;
>> +
>> +typedef enum {
>> +  EINA_FILE_RANDOM,     /**< Advise random memory access to the mapped 
>> memory. */
>> +  EINA_FILE_SEQUENTIAL, /**< Advise sequential memory access to the mapped 
>> memory. */
>> +  EINA_FILE_WILLNEED,   /**< Advise need for all the mapped memory. */
>> +  EINA_FILE_POPULATE    /**< Request all the mapped memory. */
>> +} Eina_File_Populate;
>> +
>> /* Why do this? Well PATH_MAX may vary from when eina itself is compiled
>>  * to when the app using eina is compiled. exposing the path buffer below
>>  * cant safely and portably vary based on how/when you compile. it should
>> @@ -239,6 +248,82 @@
>> EAPI Eina_Iterator *eina_file_direct_ls(const char *dir) 
>> EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
>>
>> /**
>> + * @brief Get a read-only handler to a file.
>> + *
>> + * @param name Filename to open
>> + * @param shared Requested a shm
>> + *
>> + * The file are only open in read only mode. Name should be an absolute 
>> path to
>> + * prevent cache mistake. A handler could be shared among multiple instance 
>> and
>> + * will be correctly refcounted. File are automatically closed on exec.
>> + */
>> +EAPI Eina_File *eina_file_open(const char *name, Eina_Bool shared) 
>> EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
>> +
>> +/**
>> + * @brief Unref file handler.
>> + *
>> + * @param file File handler to unref.
>> + *
>> + * This doesn't close the file, it will remain open until it leave the 
>> cache.
>> + */
>> +EAPI void eina_file_close(Eina_File *file);
>> +
>> +/**
>> + * @brief Get file size at open time.
>> + *
>> + * @param file The file handler to request the size from.
>> + * @return The length of the file.
>> + */
>> +EAPI unsigned long int eina_file_size_get(Eina_File *file);
>> +
>> +/**
>> + * @brief Get the last modification time of an open file.
>> + *
>> + * @param file The file handler to request the modification time from.
>> + * @return The last modification time.
>> + */
>> +EAPI time_t eina_file_mtime_get(Eina_File *file);
>> +
>> +/**
>> + * @brief Get the filename of an open file.
>> + *
>> + * @param file The file handler to request the name from.
>> + * @return Stringshared filename of the file.
>> + */
>> +EAPI const char *eina_file_filename_get(Eina_File *file);
>> +
>> +/**
>> + * @brief Map all the file to a buffer.
>> + *
>> + * @param file The file handler to map in memory
>> + * @param rule The rule to apply to the mapped memory
>> + * @return A pointer to a buffer that map all the file content. @c NULL if 
>> it fail.
>> + */
>> +EAPI void *eina_file_map_all(Eina_File *file, Eina_File_Populate rule);
>> +
>> +/**
>> + * @brief Map a part of the file.
>> + *
>> + * @param file The file handler to map in memory
>> + * @param rule The rule to apply to the mapped memory
>> + * @param offset The offset inside the file
>> + * @param length The length of the memory to map
>> + * @return A valid pointer to the system memory with @p length valid byte 
>> in it. And @c NULL if not inside the file or anything else goes wrong.
>> + *
>> + * This does handle refcounting so it will share map that target the same 
>> memory area.
>> + */
>> +EAPI void *eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
>> +                             unsigned long int offset, unsigned long int 
>> length);
>> +
>> +/**
>> + * @brief Unref and unmap memory if possible.
>> + *
>> + * @param file The file handler to unmap memory from.
>> + * @param map Memory map to unref and unmap.
>> + */
>> +EAPI void eina_file_map_free(Eina_File *file, void *map);
>> +
>> +/**
>>  * @}
>>  */
>>
>>
>> Modified: trunk/eina/src/lib/eina_file.c
>> ===================================================================
>> --- trunk/eina/src/lib/eina_file.c   2011-04-13 13:29:54 UTC (rev 58636)
>> +++ trunk/eina/src/lib/eina_file.c   2011-04-13 16:15:30 UTC (rev 58637)
>> @@ -44,6 +44,8 @@
>> #include <sys/types.h>
>> #include <sys/stat.h>
>> #include <unistd.h>
>> +#include <sys/mman.h>
>> +#include <fcntl.h>
>>
>> #define PATH_DELIM '/'
>>
>> @@ -60,15 +62,38 @@
>> #include "eina_safety_checks.h"
>> #include "eina_file.h"
>> #include "eina_stringshare.h"
>> +#include "eina_hash.h"
>> +#include "eina_list.h"
>>
>> /*============================================================================*
>>  *                                  Local                                    
>>  *
>>  
>> *============================================================================*/
>>
>> +#ifndef EINA_LOG_COLOR_DEFAULT
>> +#define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
>> +#endif
>> +
>> +#ifdef ERR
>> +#undef ERR
>> +#endif
>> +#define ERR(...) EINA_LOG_DOM_ERR(_eina_file_log_dom, __VA_ARGS__)
>> +
>> +#ifdef WRN
>> +#undef WRN
>> +#endif
>> +#define WRN(...) EINA_LOG_DOM_WARN(_eina_file_log_dom, __VA_ARGS__)
>> +
>> +#ifdef DBG
>> +#undef DBG
>> +#endif
>> +#define DBG(...) EINA_LOG_DOM_DBG(_eina_file_log_dom, __VA_ARGS__)
>> +
>> /**
>>  * @cond LOCAL
>>  */
>> typedef struct _Eina_File_Iterator Eina_File_Iterator;
>> +typedef struct _Eina_File_Map Eina_File_Map;
>> +
>> struct _Eina_File_Iterator
>> {
>>    Eina_Iterator iterator;
>> @@ -79,6 +104,42 @@
>>    char dir[1];
>> };
>>
>> +struct _Eina_File
>> +{
>> +   const char *filename;
>> +
>> +   Eina_Hash *map;
>> +   Eina_Hash *rmap;
>> +   void *global_map;
>> +
>> +   unsigned long length;
>> +   time_t mtime;
>> +
>> +   int refcount;
>> +   int global_refcount;
>> +
>> +   int fd;
>> +
>> +   Eina_Bool shared : 1;
>> +   Eina_Bool delete_me : 1;
>> +};
>> +
>> +struct _Eina_File_Map
>> +{
>> +   void *map;
>> +
>> +   unsigned long int offset;
>> +   unsigned long int length;
>> +
>> +   int refcount;
>> +};
>> +
>> +static Eina_Hash *_eina_file_cache = NULL;
>> +static Eina_List *_eina_file_cache_lru = NULL;
>> +static Eina_List *_eina_file_cache_delete = NULL;
>> +
>> +static int _eina_file_log_dom = -1;
>> +
>> /*
>>  * This complex piece of code is needed due to possible race condition.
>>  * The code and description of the issue can be found at :
>> @@ -310,6 +371,121 @@
>>    return EINA_TRUE;
>> }
>>
>> +static void
>> +_eina_file_real_close(Eina_File *file)
>> +{
>> +   eina_hash_free(file->rmap);
>> +   eina_hash_free(file->map);
>> +
>> +   if (file->global_map != MAP_FAILED)
>> +     munmap(file->global_map, file->length);
>> +
>> +   close(file->fd);
>> +
>> +   eina_stringshare_del(file->filename);
>> +
>> +   free(file);
>> +}
>> +
>> +static void
>> +_eina_file_map_close(Eina_File_Map *map)
>> +{
>> +   munmap(map->map, map->length);
>> +   free(map);
>> +}
>> +
>> +static unsigned int
>> +_eina_file_map_key_length(__UNUSED__ const void *key)
>> +{
>> +   return sizeof (unsigned long int) * 2;
>> +}
>> +
>> +static int
>> +_eina_file_map_key_cmp(const unsigned long int *key1, __UNUSED__ int 
>> key1_length,
>> +                       const unsigned long int *key2, __UNUSED__ int 
>> key2_length)
>> +{
>> +   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, __UNUSED__ int 
>> key_length)
>> +{
>> +   return eina_hash_int64(&key[0], sizeof (unsigned long int))
>> +     ^ eina_hash_int64(&key[1], sizeof (unsigned long int));
>> +}
>> +
>> +static void
>> +_eina_file_map_rule_apply(Eina_File_Populate rule, void *addr, unsigned 
>> long int size)
>> +{
>> +   int flag;
>> +
>> +   switch (rule)
>> +     {
>> +      case EINA_FILE_RANDOM: flag = MADV_RANDOM; break;
>> +      case EINA_FILE_SEQUENTIAL: flag = MADV_SEQUENTIAL; break;
>> +      case EINA_FILE_WILLNEED:
>> +      case EINA_FILE_POPULATE:
>> +          flag = MADV_WILLNEED;
>> +          break;
>> +     }
>> +
>> +   madvise(addr, size, flag);
>> +}
>> +
>> +Eina_Bool
>> +eina_file_init(void)
>> +{
>> +   _eina_file_log_dom = eina_log_domain_register("eina_file",
>> +                                                 EINA_LOG_COLOR_DEFAULT);
>> +   if (_eina_file_log_dom < 0)
>> +     {
>> +        EINA_LOG_ERR("Could not register log domain: eina_file");
>> +        return EINA_FALSE;
>> +     }
>> +
>> +   _eina_file_cache = 
>> eina_hash_string_djb2_new(EINA_FREE_CB(_eina_file_real_close));
>> +   if (!_eina_file_cache)
>> +     {
>> +        ERR("Could not create cache.");
>> +        eina_log_domain_unregister(_eina_file_log_dom);
>> +        _eina_file_log_dom = -1;
>> +        return EINA_FALSE;
>> +     }
>> +
>> +   return EINA_TRUE;
>> +}
>> +
>> +Eina_Bool
>> +eina_file_shutdown(void)
>> +{
>> +   Eina_File *f;
>> +   Eina_List *l;
>> +
>> +   EINA_LIST_FREE(_eina_file_cache_delete, f)
>> +     _eina_file_real_close(f);
>> +
>> +   EINA_LIST_FOREACH(_eina_file_cache_lru, l, f)
>> +     eina_hash_del(_eina_file_cache, f->filename, f);
>> +
>> +   if (eina_hash_population(_eina_file_cache) > 0)
>> +     {
>> +        Eina_Iterator *it;
>> +        const char *key;
>> +
>> +        it = eina_hash_iterator_key_new(_eina_file_cache);
>> +        EINA_ITERATOR_FOREACH(it, key)
>> +          ERR("File [%s] still open !", key);
>> +        eina_iterator_free(it);
>> +     }
>> +
>> +   eina_hash_free(_eina_file_cache);
>> +
>> +   eina_log_domain_unregister(_eina_file_log_dom);
>> +   _eina_file_log_dom = -1;
>> +   return EINA_FALSE;
>> +}
>> +
>> /**
>>  * @endcond
>>  */
>> @@ -527,3 +703,228 @@
>>
>>    return &it->iterator;
>> }
>> +
>> +EAPI Eina_File *
>> +eina_file_open(const char *filename, Eina_Bool shared)
>> +{
>> +   Eina_File *file;
>> +   Eina_File *n;
>> +   struct stat file_stat;
>> +   int fd;
>> +   Eina_Bool create = EINA_FALSE;
>> +
>> +   /* FIXME: always open absolute path (need to fix filename according to 
>> current
>> +      directory) */
>> +
>> +   if (shared)
>> +     fd = shm_open(filename, O_RDONLY | O_CLOEXEC, ACCESSPERMS);
>> +   else
>> +     fd = open(filename, O_RDONLY | O_CLOEXEC, ACCESSPERMS);
>> +
>> +   if (fd < 0) return NULL;
>> +
>> +   if (fstat(fd, &file_stat))
>> +     {
>> +        close(fd);
>> +        return NULL;
>> +     }
>> +
>> +   file = eina_hash_find(_eina_file_cache, filename);
>> +   if (file && (file->mtime != file_stat.st_mtime
>> +                || file->length != file_stat.st_size))
>> +     {
>> +        create = EINA_TRUE;
>> +
>> +        if (file->refcount == 0)
>> +          {
>> +             _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, 
>> file);
>> +             eina_hash_del(_eina_file_cache, file->filename, file);
>> +
>> +             file = NULL;
>> +          }
>> +        else if (!file->delete_me)
>> +          {
>> +             file->delete_me = EINA_TRUE;
>> +             _eina_file_cache_delete = 
>> eina_list_prepend(_eina_file_cache_delete, file);
>> +          }
>> +     }
>> +
>> +   if (!file || create)
>> +     {
>> +        n = malloc(sizeof (Eina_File));
>> +        if (!n) goto on_error;
>> +
>> +        n->filename = eina_stringshare_add(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),
>> +                               EINA_FREE_CB(_eina_file_map_close),
>> +                               3);
>> +        n->rmap = eina_hash_pointer_new(NULL);
>> +        n->global_map = MAP_FAILED;
>> +        n->length = file_stat.st_size;
>> +        n->mtime = file_stat.st_mtime;
>> +        n->refcount = 0;
>> +        n->fd = fd;
>> +        n->shared = shared;
>> +        n->delete_me = EINA_FALSE;
>> +
>> +        eina_hash_set(_eina_file_cache, filename, n);
>> +     }
>> +   else
>> +     {
>> +        close(fd);
>> +
>> +        n = file;
>> +
>> +        if (n->refcount == 0)
>> +          _eina_file_cache_lru = eina_list_remove(_eina_file_cache_lru, n);
>> +     }
>> +
>> +   n->refcount++;
>> +
>> +   return n;
>> +
>> + on_error:
>> +   close(fd);
>> +   return NULL;
>> +}
>> +
>> +EAPI void
>> +eina_file_close(Eina_File *file)
>> +{
>> +   file->refcount--;
>> +
>> +   if (file->refcount != 0) return ;
>> +
>> +   if (file->delete_me)
>> +     {
>> +        _eina_file_cache_delete = eina_list_remove(_eina_file_cache_delete, 
>> file);
>> +        _eina_file_real_close(file);
>> +     }
>> +   else
>> +     {
>> +        _eina_file_cache_lru = eina_list_prepend(_eina_file_cache_lru, 
>> file);
>> +     }
>> +}
>> +
>> +EAPI unsigned long int
>> +eina_file_size_get(Eina_File *file)
>> +{
>> +   return file->length;
>> +}
>> +
>> +EAPI time_t
>> +eina_file_mtime_get(Eina_File *file)
>> +{
>> +   return file->mtime;
>> +}
>> +
>> +EAPI const char *
>> +eina_file_filename_get(Eina_File *file)
>> +{
>> +   return file->filename;
>> +}
>> +
>> +EAPI void *
>> +eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
>> +{
>> +   int flags = MAP_SHARED;
>> +
>> +   if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
>> +
>> +   if (file->global_map == MAP_FAILED)
>> +     file->global_map = mmap(NULL, file->length, PROT_READ, flags, 
>> file->fd, 0);
>> +
>> +   if (file->global_map != MAP_FAILED)
>> +     {
>> +        _eina_file_map_rule_apply(rule, file->global_map, file->length);
>> +        file->global_refcount++;
>> +        return file->global_map;
>> +     }
>> +   return NULL;
>> +}
>> +
>> +EAPI void *
>> +eina_file_map_new(Eina_File *file, Eina_File_Populate rule,
>> +                  unsigned long int offset, unsigned long int length)
>> +{
>> +   Eina_File_Map *map;
>> +   unsigned long int key[2];
>> +
>> +   if (offset > file->length)
>> +     return NULL;
>> +   if (offset + length > file->length)
>> +     return NULL;
>> +
>> +   if (offset == 0 && length == file->length)
>> +     return eina_file_map_all(file, rule);
>> +
>> +   key[0] = offset;
>> +   key[1] = length;
>> +
>> +   map = eina_hash_find(file->map, &key);
>> +   if (!map)
>> +     {
>> +        int flags = MAP_SHARED;
>> +
>> +        if (rule == EINA_FILE_POPULATE) flags |= MAP_POPULATE;
>> +
>> +        map = malloc(sizeof (Eina_File_Map));
>> +        if (!map) return NULL;
>> +
>> +        map->map = mmap(NULL, length, PROT_READ, flags, file->fd, offset);
>> +        map->offset = offset;
>> +        map->length = length;
>> +        map->refcount = 0;
>> +
>> +        if (map->map == MAP_FAILED)
>> +          {
>> +             free(map);
>> +             return NULL;
>> +          }
>> +
>> +        eina_hash_add(file->map, &key, map);
>> +        eina_hash_direct_add(file->rmap, map->map, map);
>> +     }
>> +
>> +   map->refcount++;
>> +
>> +   _eina_file_map_rule_apply(rule, map->map, length);
>> +
>> +   return map->map;
>> +}
>> +
>> +EAPI void
>> +eina_file_map_free(Eina_File *file, void *map)
>> +{
>> +   if (file->global_map == map)
>> +     {
>> +        file->global_refcount--;
>> +
>> +        if (file->global_refcount > 0) return ;
>> +
>> +        munmap(file->global_map, file->length);
>> +        file->global_map = MAP_FAILED;
>> +     }
>> +   else
>> +     {
>> +        Eina_File_Map *em;
>> +        unsigned long int key[2];
>> +
>> +        em = eina_hash_find(file->rmap, &map);
>> +        if (!em) return ;
>> +
>> +        em->refcount--;
>> +
>> +        if (em->refcount > 0) return ;
>> +
>> +        key[0] = em->offset;
>> +        key[1] = em->length;
>> +
>> +        eina_hash_del(file->rmap, &map, em);
>> +        eina_hash_del(file->map, &key, em);
>> +     }
>> +}
>> +
>> +
>>
>> Modified: trunk/eina/src/lib/eina_main.c
>> ===================================================================
>> --- trunk/eina/src/lib/eina_main.c   2011-04-13 13:29:54 UTC (rev 58636)
>> +++ trunk/eina/src/lib/eina_main.c   2011-04-13 16:15:30 UTC (rev 58637)
>> @@ -124,6 +124,7 @@
>>    S(ustrbuf);
>>    S(quadtree);
>>    S(simple_xml);
>> +   S(file);
>> #undef S
>>
>> struct eina_desc_setup
>> @@ -156,7 +157,8 @@
>>    S(strbuf),
>>    S(ustrbuf),
>>    S(quadtree),
>> -   S(simple_xml)
>> +   S(simple_xml),
>> +   S(file)
>> #undef S
>> };
>> static const size_t _eina_desc_setup_len = sizeof(_eina_desc_setup) /
>>
>>
>> ------------------------------------------------------------------------------
>> Forrester Wave Report - Recovery time is now measured in hours and minutes
>> not days. Key insights are discussed in the 2010 Forrester Wave Report as
>> part of an in-depth evaluation of disaster recovery service providers.
>> Forrester found the best-in-class provider in terms of services and vision.
>> Read this report now!  http://p.sf.net/sfu/ibm-webcastpromo
>> _______________________________________________
>> enlightenment-svn mailing list
>> enlightenment-...@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/enlightenment-svn
>>
>>
>
> ------------------------------------------------------------------------------
> Benefiting from Server Virtualization: Beyond Initial Workload
> Consolidation -- Increasing the use of server virtualization is a top
> priority.Virtualization can reduce costs, simplify management, and improve
> application availability and disaster protection. Learn more about boosting
> the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
> _______________________________________________
> enlightenment-devel mailing list
> enlightenment-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
>
>

------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload 
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve 
application availability and disaster protection. Learn more about boosting 
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to