cedric pushed a commit to branch master.
commit 4dd259f3b159af87e6f569082ffb5353a3886b2f
Author: Cedric Bail <[email protected]>
Date: Wed Jul 31 17:16:20 2013 +0900
eina: add eina_file_refresh().
---
ChangeLog | 2 +-
NEWS | 1 +
src/lib/eina/eina_file.c | 109 +++++++++++++++++++++++++++++++---------
src/lib/eina/eina_file.h | 13 +++++
src/lib/eina/eina_file_common.c | 90 +++++++++++++++++++++++++++++++++
src/lib/eina/eina_file_common.h | 7 +++
src/lib/eina/eina_file_win32.c | 55 ++++++++++++++------
7 files changed, 237 insertions(+), 40 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 637fa0d..2762dad 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
diff --git a/NEWS b/NEWS
index c083459..39b5d59 100644
--- a/NEWS
+++ b/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()
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index 32ae4ea..ceb3e1c 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -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);
diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h
index 36aac58..0e43d2a 100644
--- a/src/lib/eina/eina_file.h
+++ b/src/lib/eina/eina_file.h
@@ -484,6 +484,19 @@ 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.
*
* @param file To duplicate a reference to
diff --git a/src/lib/eina/eina_file_common.c b/src/lib/eina/eina_file_common.c
index 75c9256..91eec16 100644
--- a/src/lib/eina/eina_file_common.c
+++ b/src/lib/eina/eina_file_common.c
@@ -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)
diff --git a/src/lib/eina/eina_file_common.h b/src/lib/eina/eina_file_common.h
index 31f6b6d..06e9a93 100644
--- a/src/lib/eina/eina_file_common.h
+++ b/src/lib/eina/eina_file_common.h
@@ -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;
diff --git a/src/lib/eina/eina_file_win32.c b/src/lib/eina/eina_file_win32.c
index d96720b..6b4e247 100644
--- a/src/lib/eina/eina_file_win32.c
+++ b/src/lib/eina/eina_file_win32.c
@@ -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:
--
------------------------------------------------------------------------------
Get your SQL database under version control now!
Version control is standard for application code, but databases havent
caught up. So what steps can you take to put your SQL databases under
version control? Why should you start doing it? Read more to find out.
http://pubads.g.doubleclick.net/gampad/clk?id=49501711&iu=/4140/ostg.clktrk