summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--NEWS1
-rw-r--r--src/lib/eina/eina_file.c109
-rw-r--r--src/lib/eina/eina_file.h13
-rw-r--r--src/lib/eina/eina_file_common.c90
-rw-r--r--src/lib/eina/eina_file_common.h7
-rw-r--r--src/lib/eina/eina_file_win32.c55
7 files changed, 237 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 637fa0d3e1..2762dad52b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,7 +4,7 @@
4 4
52013-07-31 Cedric Bail 52013-07-31 Cedric Bail
6 6
7 * Eina: add eina_file_virtualize() and eina_file_virtual(). 7 * Eina: add eina_file_refresh(), eina_file_virtualize() and eina_file_virtual().
8 * Evas: use eina_file_virtualize() for evas_object_image_memfile_set(). 8 * Evas: use eina_file_virtualize() for evas_object_image_memfile_set().
9 9
102013-07-25 ChunEon Park (Hermet) 102013-07-25 ChunEon Park (Hermet)
diff --git a/NEWS b/NEWS
index c0834591f0..39b5d5946e 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,7 @@ Additions:
35 - Add eina_file_map_populate() 35 - Add eina_file_map_populate()
36 - Add eina_tiler_empty() 36 - Add eina_tiler_empty()
37 - Add eina_file_virtualize() and eina_file_virtual() 37 - Add eina_file_virtualize() and eina_file_virtual()
38 - Add eina_file_refresh()
38 * Eet: 39 * Eet:
39 - Add eet_mmap() 40 - Add eet_mmap()
40 - Add eet_data_descriptor_name_get() 41 - Add eet_data_descriptor_name_get()
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index 32ae4ea2fa..ceb3e1cc0c 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)
304void 304void
305eina_file_real_close(Eina_File *file) 305eina_file_real_close(Eina_File *file)
306{ 306{
307 Eina_File_Map *map;
308
307 if (file->refcount != 0) return; 309 if (file->refcount != 0) return;
308 310
309 eina_hash_free(file->rmap); 311 eina_hash_free(file->rmap);
310 eina_hash_free(file->map); 312 eina_hash_free(file->map);
311 313
314 EINA_LIST_FREE(file->dead_map, map)
315 {
316 munmap(map->map, map->length);
317 free(map);
318 }
319
312 if (file->global_map != MAP_FAILED) 320 if (file->global_map != MAP_FAILED)
313 munmap(file->global_map, file->length); 321 munmap(file->global_map, file->length);
314 322
@@ -462,6 +470,19 @@ eina_file_shutdown(void)
462 return EINA_TRUE; 470 return EINA_TRUE;
463} 471}
464 472
473static Eina_Bool
474_eina_file_mmap_faulty_one(void *addr, long page_size,
475 Eina_File_Map *m)
476{
477 if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) &&
478 (((unsigned char *) addr) + page_size) >= (unsigned char *) m->map)
479 {
480 m->faulty = EINA_TRUE;
481 return EINA_TRUE;
482 }
483 return EINA_FALSE;
484}
485
465void 486void
466eina_file_mmap_faulty(void *addr, long page_size) 487eina_file_mmap_faulty(void *addr, long page_size)
467{ 488{
@@ -497,17 +518,23 @@ eina_file_mmap_faulty(void *addr, long page_size)
497 itm = eina_hash_iterator_data_new(f->map); 518 itm = eina_hash_iterator_data_new(f->map);
498 EINA_ITERATOR_FOREACH(itm, m) 519 EINA_ITERATOR_FOREACH(itm, m)
499 { 520 {
500 if ((unsigned char *) addr < (((unsigned char *)m->map) + m->length) && 521 faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
501 (((unsigned char *) addr) + page_size) >= (unsigned char *) m->map) 522 if (faulty) break;
502 {
503 m->faulty = EINA_TRUE;
504 faulty = EINA_TRUE;
505 break;
506 }
507 } 523 }
508 eina_iterator_free(itm); 524 eina_iterator_free(itm);
509 } 525 }
510 526
527 if (!faulty)
528 {
529 Eina_List *l;
530
531 EINA_LIST_FOREACH(f->dead_map, l, m)
532 {
533 faulty = _eina_file_mmap_faulty_one(addr, page_size, m);
534 if (faulty) break;
535 }
536 }
537
511 eina_lock_release(&f->lock); 538 eina_lock_release(&f->lock);
512 539
513 if (faulty) break; 540 if (faulty) break;
@@ -902,6 +929,39 @@ eina_file_open(const char *path, Eina_Bool shared)
902 return NULL; 929 return NULL;
903} 930}
904 931
932EAPI Eina_Bool
933eina_file_refresh(Eina_File *file)
934{
935 struct stat file_stat;
936 Eina_Bool r = EINA_FALSE;
937
938 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
939
940 if (file->virtual) return EINA_FALSE;
941
942 if (fstat(file->fd, &file_stat))
943 return EINA_FALSE;
944
945 if (file->length != (unsigned long int) file_stat.st_size)
946 {
947 eina_file_flush(file, file_stat.st_size);
948 r = EINA_TRUE;
949 }
950
951 file->length = file_stat.st_size;
952 file->mtime = file_stat.st_mtime;
953#ifdef _STAT_VER_LINUX
954# if (defined __USE_MISC && defined st_mtime)
955 file->mtime_nsec = (unsigned long int)file_stat.st_mtim.tv_nsec;
956# else
957 file->mtime_nsec = (unsigned long int)file_stat.st_mtimensec;
958# endif
959#endif
960 file->inode = file_stat.st_ino;
961
962 return r;
963}
964
905EAPI void * 965EAPI void *
906eina_file_map_all(Eina_File *file, Eina_File_Populate rule) 966eina_file_map_all(Eina_File *file, Eina_File_Populate rule)
907{ 967{
@@ -1048,21 +1108,7 @@ eina_file_map_free(Eina_File *file, void *map)
1048 } 1108 }
1049 else 1109 else
1050 { 1110 {
1051 Eina_File_Map *em; 1111 eina_file_common_map_free(file, map, _eina_file_map_close);
1052 unsigned long int key[2];
1053
1054 em = eina_hash_find(file->rmap, &map);
1055 if (!em) goto on_exit;
1056
1057 em->refcount--;
1058
1059 if (em->refcount > 0) goto on_exit;
1060
1061 key[0] = em->offset;
1062 key[1] = em->length;
1063
1064 eina_hash_del(file->rmap, &map, em);
1065 eina_hash_del(file->map, &key, em);
1066 } 1112 }
1067 1113
1068 on_exit: 1114 on_exit:
@@ -1086,7 +1132,6 @@ eina_file_map_populate(Eina_File *file, Eina_File_Populate rule, void *map,
1086EAPI Eina_Bool 1132EAPI Eina_Bool
1087eina_file_map_faulted(Eina_File *file, void *map) 1133eina_file_map_faulted(Eina_File *file, void *map)
1088{ 1134{
1089 Eina_File_Map *em;
1090 Eina_Bool r = EINA_FALSE; 1135 Eina_Bool r = EINA_FALSE;
1091 1136
1092 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE); 1137 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
@@ -1101,8 +1146,24 @@ eina_file_map_faulted(Eina_File *file, void *map)
1101 } 1146 }
1102 else 1147 else
1103 { 1148 {
1149 Eina_File_Map *em;
1150
1104 em = eina_hash_find(file->rmap, &map); 1151 em = eina_hash_find(file->rmap, &map);
1105 if (em) r = em->faulty; 1152 if (em)
1153 {
1154 r = em->faulty;
1155 }
1156 else
1157 {
1158 Eina_List *l;
1159
1160 EINA_LIST_FOREACH(file->dead_map, l, em)
1161 if (em->map == map)
1162 {
1163 r = em->faulty;
1164 break;
1165 }
1166 }
1106 } 1167 }
1107 1168
1108 eina_lock_release(&file->lock); 1169 eina_lock_release(&file->lock);
diff --git a/src/lib/eina/eina_file.h b/src/lib/eina/eina_file.h
index 36aac586e4..0e43d2acb8 100644
--- a/src/lib/eina/eina_file.h
+++ b/src/lib/eina/eina_file.h
@@ -484,6 +484,19 @@ EAPI Eina_Bool
484eina_file_virtual(Eina_File *file) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1); 484eina_file_virtual(Eina_File *file) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
485 485
486/** 486/**
487 * @brief Refresh file information
488 *
489 * @param file The file to refresh
490 * @return #EINA_TRUE if the file has changed
491 *
492 * All current map continue to exist. You need to manually delete
493 * and recreate them to have the new correct mapping.
494 *
495 * @since 1.8
496 */
497EAPI Eina_Bool eina_file_refresh(Eina_File *file);
498
499/**
487 * @brief Dup a read-only handler of a previously open file. 500 * @brief Dup a read-only handler of a previously open file.
488 * 501 *
489 * @param file To duplicate a reference to 502 * @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 75c92564dd..91eec161b7 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)
232 eina_lock_release(&file->lock); 232 eina_lock_release(&file->lock);
233} 233}
234 234
235void
236eina_file_common_map_free(Eina_File *file, void *map,
237 void (*free_func)(Eina_File_Map *map))
238{
239 Eina_File_Map *em;
240 unsigned long int key[2];
241 Eina_List *l = NULL;
242 Eina_Bool hashed = EINA_TRUE;
243
244 em = eina_hash_find(file->rmap, &map);
245 if (!em)
246 {
247 EINA_LIST_FOREACH(file->dead_map, l, em)
248 if (em->map == map)
249 {
250 hashed = EINA_FALSE;
251 break ;
252 }
253 if (hashed) return ;
254 }
255
256 em->refcount--;
257
258 if (em->refcount > 0) return ;
259
260 key[0] = em->offset;
261 key[1] = em->length;
262
263 if (hashed)
264 {
265 eina_hash_del(file->rmap, &map, em);
266 eina_hash_del(file->map, &key, em);
267 }
268 else
269 {
270 file->dead_map = eina_list_remove_list(file->dead_map, l);
271 free_func(em);
272 }
273}
274
275void
276eina_file_flush(Eina_File *file, unsigned long int length)
277{
278 Eina_File_Map *tmp;
279 Eina_Iterator *it;
280 Eina_List *dead_map = NULL;
281 Eina_List *l;
282
283 // File size changed
284 if (file->global_map)
285 {
286 // Forget global map
287 tmp = malloc(sizeof (Eina_File_Map));
288 if (tmp)
289 {
290 tmp->map = file->global_map;
291 tmp->offset = 0;
292 tmp->length = file->length;
293 tmp->refcount = file->refcount;
294
295 file->dead_map = eina_list_append(file->dead_map, tmp);
296 }
297
298 file->global_map = NULL;
299 file->refcount = 0;
300 }
301
302 it = eina_hash_iterator_data_new(file->map);
303 EINA_ITERATOR_FOREACH(it, tmp)
304 {
305 // Add out of limit map to dead_map
306 if (tmp->offset + tmp->length > length)
307 dead_map = eina_list_append(dead_map, tmp);
308 }
309 eina_iterator_free(it);
310
311 EINA_LIST_FOREACH(dead_map, l, tmp)
312 {
313 unsigned long int key[2];
314
315 key[0] = tmp->offset;
316 key[1] = tmp->length;
317
318 eina_hash_del(file->rmap, &tmp->map, tmp);
319 eina_hash_del(file->map, &key, tmp);
320 }
321
322 file->dead_map = eina_list_merge(file->dead_map, dead_map);
323}
324
235// Private to this file API 325// Private to this file API
236static void 326static void
237_eina_file_map_close(Eina_File_Map *map) 327_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 31f6b6d306..06e9a93143 100644
--- a/src/lib/eina/eina_file_common.h
+++ b/src/lib/eina/eina_file_common.h
@@ -22,6 +22,7 @@
22#include "eina_file.h" 22#include "eina_file.h"
23#include "eina_tmpstr.h" 23#include "eina_tmpstr.h"
24#include "eina_lock.h" 24#include "eina_lock.h"
25#include "eina_list.h"
25 26
26typedef struct _Eina_File_Map Eina_File_Map; 27typedef struct _Eina_File_Map Eina_File_Map;
27typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator; 28typedef struct _Eina_Lines_Iterator Eina_Lines_Iterator;
@@ -58,6 +59,8 @@ struct _Eina_File
58 HANDLE fm; 59 HANDLE fm;
59#endif 60#endif
60 61
62 Eina_List *dead_map;
63
61 Eina_Bool shared : 1; 64 Eina_Bool shared : 1;
62 Eina_Bool delete_me : 1; 65 Eina_Bool delete_me : 1;
63 Eina_Bool global_faulty : 1; 66 Eina_Bool global_faulty : 1;
@@ -119,6 +122,10 @@ Eina_Bool eina_file_path_relative(const char *path);
119Eina_Tmpstr *eina_file_current_directory_get(const char *path, size_t len); 122Eina_Tmpstr *eina_file_current_directory_get(const char *path, size_t len);
120char *eina_file_cleanup(Eina_Tmpstr *path); 123char *eina_file_cleanup(Eina_Tmpstr *path);
121void eina_file_real_close(Eina_File *file); 124void eina_file_real_close(Eina_File *file);
125void eina_file_flush(Eina_File *file, unsigned long int length);
126void eina_file_common_map_free(Eina_File *file, void *map,
127 void (*free_func)(Eina_File_Map *map));
128
122 129
123extern Eina_Hash *_eina_file_cache; 130extern Eina_Hash *_eina_file_cache;
124extern Eina_Lock _eina_file_lock_cache; 131extern 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 d96720bbd2..6b4e247531 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)
364void 364void
365eina_file_real_close(Eina_File *file) 365eina_file_real_close(Eina_File *file)
366{ 366{
367 Eina_File_Map *map;
368
367 eina_hash_free(file->rmap); 369 eina_hash_free(file->rmap);
368 eina_hash_free(file->map); 370 eina_hash_free(file->map);
369 371
372 EINA_LIST_FREE(file->dead_map, map)
373 {
374 UnmapViewOfFile(map->map);
375 free(map);
376 }
377
370 if (file->global_map != MAP_FAILED) 378 if (file->global_map != MAP_FAILED)
371 UnmapViewOfFile(file->global_map); 379 UnmapViewOfFile(file->global_map);
372 380
@@ -715,6 +723,37 @@ eina_file_stat_ls(const char *dir)
715 return eina_file_direct_ls(dir); 723 return eina_file_direct_ls(dir);
716} 724}
717 725
726EAPI Eina_Bool
727eina_file_refresh(Eina_File *file)
728{
729 WIN32_FILE_ATTRIBUTE_DATA fad;
730 ULARGE_INTEGER length;
731 ULARGE_INTEGER mtime;
732
733 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
734
735 if (file->virtual) return EINA_FALSE;
736
737 if (!GetFileAttributesEx(file->filename, GetFileExInfoStandard, &fad))
738 return EINA_FALSE;
739
740 length.u.LowPart = fad.nFileSizeLow;
741 length.u.HighPart = fad.nFileSizeHigh;
742 mtime.u.LowPart = fad.ftLastWriteTime.dwLowDateTime;
743 mtime.u.HighPart = fad.ftLastWriteTime.dwHighDateTime;
744
745 if (file->length != length.QuadPart)
746 {
747 eina_file_flush(file, file_stat.st_size);
748 r = EINA_TRUE;
749 }
750
751 n->length = length.QuadPart;
752 n->mtime = mtime.QuadPart;
753
754 return r;
755}
756
718EAPI Eina_File * 757EAPI Eina_File *
719eina_file_open(const char *path, Eina_Bool shared) 758eina_file_open(const char *path, Eina_Bool shared)
720{ 759{
@@ -953,21 +992,7 @@ eina_file_map_free(Eina_File *file, void *map)
953 } 992 }
954 else 993 else
955 { 994 {
956 Eina_File_Map *em; 995 eina_file_common_map_free(file, map, _eina_file_map_close);
957 unsigned long int key[2];
958
959 em = eina_hash_find(file->rmap, &map);
960 if (!em) goto on_exit;
961
962 em->refcount--;
963
964 if (em->refcount > 0) goto on_exit;
965
966 key[0] = em->offset;
967 key[1] = em->length;
968
969 eina_hash_del(file->rmap, &map, em);
970 eina_hash_del(file->map, &key, em);
971 } 996 }
972 997
973 on_exit: 998 on_exit: