forked from enlightenment/efl
evas/cserve2: Scan shared indexes in client side
Read Image descriptors from the shared arrays But, accessing the shared index can be a bit expensive, so try to read from the socket before scanning the index, without blocking.
This commit is contained in:
parent
08648ab2a5
commit
f5d0f0aec3
|
@ -549,8 +549,10 @@ evas_cache2_shutdown(Evas_Cache2 *cache)
|
|||
free(cache);
|
||||
}
|
||||
|
||||
static void
|
||||
_create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key, size_t keylen, Evas_Image_Load_Opts *lo)
|
||||
EAPI void
|
||||
evas_cache2_image_cache_key_create(char *hkey, const char *path, size_t pathlen,
|
||||
const char *key, size_t keylen,
|
||||
const Evas_Image_Load_Opts *lo)
|
||||
{
|
||||
const char *ckey = "(null)";
|
||||
size_t size;
|
||||
|
@ -561,6 +563,7 @@ _create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key,
|
|||
memcpy(hkey + size, "//://", 5);
|
||||
size += 5;
|
||||
if (key) ckey = key;
|
||||
else keylen = 6;
|
||||
memcpy(hkey + size, ckey, keylen);
|
||||
size += keylen;
|
||||
if (lo)
|
||||
|
@ -634,7 +637,8 @@ _create_hash_key(char *hkey, const char *path, size_t pathlen, const char *key,
|
|||
}
|
||||
|
||||
EAPI Image_Entry *
|
||||
evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Evas_Image_Load_Opts *lo, int *error)
|
||||
evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key,
|
||||
Evas_Image_Load_Opts *lo, int *error)
|
||||
{
|
||||
size_t size;
|
||||
size_t pathlen;
|
||||
|
@ -659,7 +663,7 @@ evas_cache2_image_open(Evas_Cache2 *cache, const char *path, const char *key, Ev
|
|||
size = pathlen + keylen + HKEY_LOAD_OPTS_STR_LEN;
|
||||
hkey = alloca(sizeof(char) * size);
|
||||
|
||||
_create_hash_key(hkey, path, pathlen, key, keylen, lo);
|
||||
evas_cache2_image_cache_key_create(hkey, path, pathlen, key, keylen, lo);
|
||||
DBG("Looking at the hash for key '%s'", hkey);
|
||||
|
||||
/* use local var to copy default load options to the image entry */
|
||||
|
@ -816,7 +820,8 @@ _scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h,
|
|||
if (!smooth)
|
||||
{
|
||||
lo.scale_load.smooth = 1;
|
||||
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
|
||||
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
|
||||
im->key, keylen, &lo);
|
||||
|
||||
ret = eina_hash_find(im->cache2->activ, hkey);
|
||||
if (ret) goto found;
|
||||
|
@ -827,7 +832,8 @@ _scaled_image_find(Image_Entry *im, int src_x, int src_y, int src_w, int src_h,
|
|||
lo.scale_load.smooth = smooth;
|
||||
}
|
||||
|
||||
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
|
||||
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
|
||||
im->key, keylen, &lo);
|
||||
|
||||
ret = eina_hash_find(im->cache2->activ, hkey);
|
||||
if (ret) goto found;
|
||||
|
@ -896,7 +902,8 @@ evas_cache2_image_scale_load(Image_Entry *im,
|
|||
lo.scale_load.smooth = smooth;
|
||||
lo.scale_load.scale_hint = im->scale_hint;
|
||||
|
||||
_create_hash_key(hkey, im->file, pathlen, im->key, keylen, &lo);
|
||||
evas_cache2_image_cache_key_create(hkey, im->file, pathlen,
|
||||
im->key, keylen, &lo);
|
||||
|
||||
ret = _evas_cache_image_entry_new(im->cache2, hkey, NULL, im->file, im->key,
|
||||
&lo, &error);
|
||||
|
|
|
@ -66,6 +66,7 @@ EAPI void evas_cache2_image_close(Image_Entry *im);
|
|||
EAPI int evas_cache2_image_load_data(Image_Entry *ie);
|
||||
EAPI void evas_cache2_image_unload_data(Image_Entry *im);
|
||||
EAPI void evas_cache2_image_preload_data(Image_Entry *im, const void *target);
|
||||
EAPI void evas_cache2_image_cache_key_create(char *hkey, const char *path, size_t pathlen, const char *key, size_t keylen, const Evas_Image_Load_Opts *lo);
|
||||
|
||||
EAPI DATA32 * evas_cache2_image_pixels(Image_Entry *im);
|
||||
EAPI Image_Entry * evas_cache2_image_writable(Image_Entry *im);
|
||||
|
|
|
@ -275,6 +275,7 @@ struct _Msg_Font_Debug {
|
|||
*/
|
||||
struct _Msg_Index_List {
|
||||
Msg_Base base;
|
||||
int generation_id;
|
||||
char strings_index_path[64];
|
||||
char strings_entries_path[64];
|
||||
char files_index_path[64];
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
|
||||
#ifdef EVAS_CSERVE2
|
||||
|
||||
#define USE_SHARED_INDEX 1
|
||||
#define SHARED_INDEX_ADD_TO_HASH 1
|
||||
#define HKEY_LOAD_OPTS_STR_LEN 215
|
||||
typedef void (*Op_Callback)(void *data, const void *msg, int size);
|
||||
|
||||
struct _File_Entry {
|
||||
|
@ -47,6 +50,8 @@ static Eina_List *_requests = NULL;
|
|||
static Index_Table _index;
|
||||
static const char *_shared_string_get(int id);
|
||||
static int _server_index_list_set(Msg_Base *data, int size);
|
||||
static const File_Data *_shared_file_data_get_by_id(unsigned int id);
|
||||
static const Shm_Object *_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id);
|
||||
static const File_Data *_shared_image_entry_file_data_find(Image_Entry *ie);
|
||||
static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie);
|
||||
|
||||
|
@ -902,10 +907,21 @@ int
|
|||
evas_cserve2_image_load_wait(Image_Entry *ie)
|
||||
{
|
||||
const File_Data *fd;
|
||||
Eina_Bool failed;
|
||||
unsigned int rrid, rid;
|
||||
|
||||
if (!ie)
|
||||
return CSERVE2_GENERIC;
|
||||
|
||||
if (!ie->open_rid)
|
||||
return CSERVE2_NONE;
|
||||
|
||||
rid = ie->open_rid;
|
||||
rrid = _server_dispatch(&failed);
|
||||
if (rid == rrid)
|
||||
return CSERVE2_NONE;
|
||||
|
||||
#if USE_SHARED_INDEX
|
||||
fd = _shared_image_entry_file_data_find(ie);
|
||||
if (fd)
|
||||
{
|
||||
|
@ -919,6 +935,7 @@ evas_cserve2_image_load_wait(Image_Entry *ie)
|
|||
ie->open_rid = 0;
|
||||
return CSERVE2_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ie->open_rid)
|
||||
{
|
||||
|
@ -959,6 +976,7 @@ evas_cserve2_image_load_data_wait(Image_Entry *ie)
|
|||
if (!ie)
|
||||
return CSERVE2_GENERIC;
|
||||
|
||||
#if USE_SHARED_INDEX
|
||||
idata = _shared_image_entry_image_data_find(ie);
|
||||
if (idata)
|
||||
{
|
||||
|
@ -997,6 +1015,7 @@ evas_cserve2_image_load_data_wait(Image_Entry *ie)
|
|||
ie->load_rid = 0;
|
||||
return CSERVE2_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
load_wait:
|
||||
if (ie->load_rid)
|
||||
|
@ -1607,6 +1626,7 @@ evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, Font_Hint_F
|
|||
|
||||
// Fast access to shared index tables
|
||||
|
||||
static Eina_Bool _shared_index_remap_check(Shared_Index *si, int elemsize);
|
||||
|
||||
// Returns the number of correctly opened index arrays
|
||||
static int
|
||||
|
@ -1614,7 +1634,6 @@ _server_index_list_set(Msg_Base *data, int size)
|
|||
{
|
||||
Msg_Index_List *msg = (Msg_Index_List *) data;
|
||||
unsigned sz;
|
||||
int ret = 0;
|
||||
|
||||
// TODO #1: Check populate rule.
|
||||
// TODO #2: Protect memory for read-only access.
|
||||
|
@ -1627,276 +1646,162 @@ _server_index_list_set(Msg_Base *data, int size)
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Reset index table
|
||||
if (_index.strings.index_file)
|
||||
if (_index.generation_id == msg->generation_id)
|
||||
{
|
||||
if (_index.strings.index_header)
|
||||
eina_file_map_free(_index.strings.index_file,
|
||||
(void *) _index.strings.index_header);
|
||||
eina_file_close(_index.strings.index_file);
|
||||
}
|
||||
if (_index.strings.entries_file)
|
||||
{
|
||||
if (_index.strings.index_header)
|
||||
eina_file_map_free(_index.strings.entries_file,
|
||||
(void *) _index.strings.index_header);
|
||||
eina_file_close(_index.strings.entries_file);
|
||||
}
|
||||
if (_index.files.f)
|
||||
{
|
||||
if (_index.files.header)
|
||||
eina_file_map_free(_index.files.f, (void *) _index.files.header);
|
||||
eina_file_close(_index.files.f);
|
||||
}
|
||||
if (_index.images.f)
|
||||
{
|
||||
if (_index.images.header)
|
||||
eina_file_map_free(_index.images.f, (void *) _index.images.header);
|
||||
eina_file_close(_index.images.f);
|
||||
}
|
||||
if (_index.fonts.f)
|
||||
{
|
||||
if (_index.fonts.header)
|
||||
eina_file_map_free(_index.fonts.f, (void *) _index.fonts.header);
|
||||
eina_file_close(_index.fonts.f);
|
||||
ERR("New index generation_id is the same as before: %d",
|
||||
_index.generation_id);
|
||||
}
|
||||
|
||||
// Open new indexes
|
||||
eina_strlcpy(_index.strings.index_path, msg->strings_index_path, 64);
|
||||
eina_strlcpy(_index.strings.entries_path, msg->strings_entries_path, 64);
|
||||
eina_strlcpy(_index.files.path, msg->files_index_path, 64);
|
||||
eina_strlcpy(_index.images.path, msg->images_index_path, 64);
|
||||
eina_strlcpy(_index.fonts.path, msg->fonts_index_path, 64);
|
||||
_index.generation_id = msg->generation_id;
|
||||
|
||||
if (_index.strings.index_path[0] && _index.strings.entries_path[0])
|
||||
// 1. Strings (indexes and entries)
|
||||
|
||||
if (_index.strings_entries.data
|
||||
&& strncmp(_index.strings_entries.path, msg->strings_entries_path,
|
||||
SHARED_BUFFER_PATH_MAX) != 0)
|
||||
{
|
||||
_index.strings.index_file = eina_file_open(_index.strings.index_path,
|
||||
EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.strings.index_file);
|
||||
_index.strings.index_header = eina_file_map_all(
|
||||
_index.strings.index_file, EINA_FILE_POPULATE);
|
||||
if (_index.strings.index_header && sz > sizeof(Shared_Array_Header)
|
||||
&& sz >= (_index.strings.index_header->count * sizeof(Index_Entry)
|
||||
+ sizeof(Shared_Array_Header)))
|
||||
DBG("Updating string entries shm to: '%s'", msg->strings_entries_path);
|
||||
eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
|
||||
eina_file_close(_index.strings_entries.f);
|
||||
_index.strings_entries.f = NULL;
|
||||
_index.strings_entries.data = NULL;
|
||||
}
|
||||
|
||||
if (_index.strings_index.data
|
||||
&& strncmp(_index.strings_index.path, msg->strings_index_path,
|
||||
SHARED_BUFFER_PATH_MAX) != 0)
|
||||
{
|
||||
_index.strings.indexes = (Index_Entry *)
|
||||
&(_index.strings.index_header[1]);
|
||||
_index.strings.entries_file = eina_file_open(
|
||||
_index.strings.entries_path, EINA_TRUE);
|
||||
_index.strings.entries_size = eina_file_size_get(
|
||||
_index.strings.entries_file);
|
||||
_index.strings.data = eina_file_map_all(
|
||||
_index.strings.entries_file, EINA_FILE_RANDOM);
|
||||
if (!_index.strings.entries_size || !_index.strings.data)
|
||||
goto strings_map_failed;
|
||||
DBG("Mapped shared string table with indexes in %s and data in %s",
|
||||
_index.strings.index_path, _index.strings.entries_path);
|
||||
DBG("Updating string indexes shm to: '%s'", msg->strings_index_path);
|
||||
eina_file_map_free(_index.strings_index.f, _index.strings_index.data);
|
||||
eina_file_close(_index.strings_index.f);
|
||||
_index.strings_index.f = NULL;
|
||||
_index.strings_index.data = NULL;
|
||||
}
|
||||
|
||||
eina_strlcpy(_index.strings_entries.path, msg->strings_entries_path, SHARED_BUFFER_PATH_MAX);
|
||||
eina_strlcpy(_index.strings_index.path, msg->strings_index_path, SHARED_BUFFER_PATH_MAX);
|
||||
|
||||
if (!_index.strings_entries.data
|
||||
&& _index.strings_entries.path[0]
|
||||
&& _index.strings_index.path[0])
|
||||
{
|
||||
_index.strings_entries.f = eina_file_open(_index.strings_entries.path, EINA_TRUE);
|
||||
_index.strings_entries.size = eina_file_size_get(_index.strings_entries.f);
|
||||
if (_index.strings_entries.size > 0)
|
||||
_index.strings_entries.data = eina_file_map_all(_index.strings_entries.f, EINA_FILE_RANDOM);
|
||||
|
||||
if (!_index.strings_entries.data)
|
||||
{
|
||||
ERR("Could not map strings entries from: '%s'", _index.strings_entries.path);
|
||||
eina_file_close(_index.strings_entries.f);
|
||||
_index.strings_entries.f = NULL;
|
||||
_index.strings_entries.data = NULL;
|
||||
}
|
||||
else DBG("Mapped string entries from %s", _index.strings_entries.path);
|
||||
}
|
||||
|
||||
if (_index.strings_entries.data &&
|
||||
(!_index.strings_index.data && _index.strings_index.path[0]))
|
||||
{
|
||||
_index.strings_index.f = eina_file_open(_index.strings_index.path, EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.strings_index.f);
|
||||
if (sz >= sizeof(Shared_Array_Header))
|
||||
_index.strings_index.data = eina_file_map_all(_index.strings_index.f, EINA_FILE_RANDOM);
|
||||
|
||||
if (_index.strings_index.data)
|
||||
{
|
||||
DBG("Mapped string indexes from %s", _index.strings_index.path);
|
||||
sz = eina_file_size_get(_index.strings_index.f);
|
||||
_index.strings_index.count = (sz - sizeof(Shared_Array_Header)) / sizeof(Index_Entry);
|
||||
if (_index.strings_index.count > _index.strings_index.header->count)
|
||||
{
|
||||
WRN("Detected larger index than advertised: %d > %d",
|
||||
_index.strings_index.count, _index.strings_index.header->count);
|
||||
_index.strings_index.count = _index.strings_index.header->count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strings_map_failed:
|
||||
eina_file_map_free(_index.strings.entries_file,
|
||||
(void *) _index.strings.data);
|
||||
eina_file_close(_index.strings.entries_file);
|
||||
eina_file_map_free(_index.strings.index_file,
|
||||
(void *) _index.strings.index_header);
|
||||
eina_file_close(_index.strings.index_file);
|
||||
memset(&_index.strings, 0, sizeof(_index.strings));
|
||||
ERR("Could not map string indexes from %s", _index.strings_index.path);
|
||||
eina_file_close(_index.strings_index.f);
|
||||
eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
|
||||
eina_file_close(_index.strings_entries.f);
|
||||
_index.strings_index.f = NULL;
|
||||
_index.strings_entries.f = NULL;
|
||||
_index.strings_entries.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (_index.files.path[0])
|
||||
_shared_index_remap_check(&_index.strings_index, sizeof(Index_Entry));
|
||||
if (_index.strings_entries.data)
|
||||
{
|
||||
_index.files.f = eina_file_open(_index.files.path, EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.files.f);
|
||||
if (sz < sizeof(Shared_Array_Header))
|
||||
if (eina_file_refresh(_index.strings_entries.f))
|
||||
{
|
||||
ERR("Shared index for files is too small: %u", sz);
|
||||
eina_file_close(_index.files.f);
|
||||
_index.files.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.files.header = eina_file_map_all(_index.files.f,
|
||||
EINA_FILE_POPULATE);
|
||||
if (sz < (_index.files.header->count * sizeof(File_Data)
|
||||
+ sizeof(Shared_Array_Header)))
|
||||
{
|
||||
ERR("Shared index size does not match array size: %u / %u",
|
||||
sz, _index.files.header->count);
|
||||
eina_file_map_free(_index.files.f,
|
||||
(void *) _index.files.header);
|
||||
eina_file_close(_index.files.f);
|
||||
_index.files.f = NULL;
|
||||
_index.files.header = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.files.entries.fdata =
|
||||
(File_Data *) &(_index.files.header[1]);
|
||||
DBG("Mapped files shared index '%s' at %p: %u entries max",
|
||||
_index.files.path, _index.files.header,
|
||||
_index.files.header->count);
|
||||
ret++;
|
||||
}
|
||||
eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data);
|
||||
_index.strings_entries.data = eina_file_map_all(_index.strings_entries.f, EINA_FILE_RANDOM);
|
||||
_index.strings_entries.size = eina_file_size_get(_index.strings_entries.f);
|
||||
}
|
||||
}
|
||||
|
||||
if (_index.images.path[0])
|
||||
{
|
||||
_index.images.f = eina_file_open(_index.images.path, EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.images.f);
|
||||
if (sz < sizeof(Shared_Array_Header))
|
||||
{
|
||||
ERR("Shared index for images is too small: %u", sz);
|
||||
eina_file_close(_index.images.f);
|
||||
_index.images.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = eina_file_size_get(_index.images.f);
|
||||
_index.images.header = eina_file_map_all(_index.images.f,
|
||||
EINA_FILE_POPULATE);
|
||||
if (sz < (_index.images.header->count * sizeof(Image_Data)
|
||||
+ sizeof(Shared_Array_Header)))
|
||||
{
|
||||
ERR("Shared index size does not match array size: %u / %u",
|
||||
sz, _index.images.header->count);
|
||||
eina_file_map_free(_index.images.f,
|
||||
(void *) _index.images.header);
|
||||
eina_file_close(_index.images.f);
|
||||
_index.images.f = NULL;
|
||||
_index.images.header = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.images.count = (size - sizeof(Shared_Array_Header))
|
||||
/ sizeof(Image_Data);
|
||||
_index.images.entries.idata =
|
||||
(Image_Data *) &(_index.images.header[1]);
|
||||
DBG("Mapped images shared index '%s' at %p: %u entries max",
|
||||
_index.images.path, _index.images.header,
|
||||
_index.images.header->count);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_index.fonts.path[0])
|
||||
ERR("Not implemented yet: fonts shared index");
|
||||
// 2. File indexes
|
||||
|
||||
return ret;
|
||||
}
|
||||
eina_strlcpy(_index.files.path, msg->files_index_path, SHARED_BUFFER_PATH_MAX);
|
||||
_shared_index_remap_check(&_index.files, sizeof(File_Data));
|
||||
|
||||
// FIXME: Copy & paste from evas_cserve2_cache.c
|
||||
static int
|
||||
_shm_object_id_cmp_cb(const void *data1, const void *data2)
|
||||
{
|
||||
const Shm_Object *obj;
|
||||
unsigned int key;
|
||||
|
||||
if (data1 == data2) return 0;
|
||||
if (!data1) return 1;
|
||||
if (!data2) return -1;
|
||||
// 3. Image indexes
|
||||
|
||||
obj = data1;
|
||||
key = *((unsigned int *) data2);
|
||||
if (obj->id == key) return 0;
|
||||
if (obj->id < key)
|
||||
return -1;
|
||||
else
|
||||
return +1;
|
||||
eina_strlcpy(_index.images.path, msg->images_index_path, SHARED_BUFFER_PATH_MAX);
|
||||
_shared_index_remap_check(&_index.images, sizeof(Image_Data));
|
||||
|
||||
|
||||
// 4. Font indexes
|
||||
// TODO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: (almost) copy & paste from evas_cserve2_cache.c
|
||||
static const char *
|
||||
_shared_string_get(int id)
|
||||
{
|
||||
const char *ret;
|
||||
const Index_Entry *ie = NULL;
|
||||
int k;
|
||||
Index_Entry *ie;
|
||||
|
||||
if (id <= 0) return NULL;
|
||||
if (!_index.strings.data) return NULL;
|
||||
|
||||
// Binary search
|
||||
if (_index.strings.index_header->sortedidx > 0)
|
||||
{
|
||||
int low = 0;
|
||||
int high = _index.strings.index_header->sortedidx;
|
||||
int prev = -1;
|
||||
int r;
|
||||
k = high / 2;
|
||||
while (prev != k)
|
||||
{
|
||||
ie = &(_index.strings.indexes[k]);
|
||||
r = _shm_object_id_cmp_cb(ie, &id);
|
||||
if (!r)
|
||||
goto found;
|
||||
else if (r > 0)
|
||||
high = k;
|
||||
else
|
||||
low = k;
|
||||
prev = k;
|
||||
k = low + (high - low) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Linear search O(n)
|
||||
k = _index.strings.index_header->sortedidx;
|
||||
for (; k < _index.strings.index_header->emptyidx; k++)
|
||||
{
|
||||
ie = &(_index.strings.indexes[k]);
|
||||
if (!_shm_object_id_cmp_cb(ie, &id))
|
||||
goto found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
ie = (Index_Entry *)
|
||||
_shared_index_item_get_by_id(&_index.strings_index, sizeof(*ie), id);
|
||||
if (!ie) return NULL;
|
||||
if (ie->offset < 0) return NULL;
|
||||
if (!ie->refcount) return NULL;
|
||||
if (ie->length + ie->offset > (int) _index.strings.entries_size)
|
||||
return NULL;
|
||||
if (ie->offset + ie->length > _index.strings_entries.size) return NULL;
|
||||
|
||||
ret = _index.strings.data + ie->offset;
|
||||
return ret;
|
||||
return _index.strings_entries.data + ie->offset;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_shared_image_entry_file_data_match(Image_Entry *ie, const File_Data *fd)
|
||||
#define SHARED_INDEX_CHECK(si, typ) \
|
||||
do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \
|
||||
CRIT("Failed to remap index"); return NULL; } } while (0)
|
||||
|
||||
static const char *
|
||||
_shared_file_data_hkey_get(char *hkey, const char *file, const char *key,
|
||||
size_t hkey_size)
|
||||
{
|
||||
const char *path, *key, *loader;
|
||||
size_t keylen, filelen;
|
||||
|
||||
if (!fd || !ie) return EINA_FALSE;
|
||||
if (!ie->file && !ie->key)
|
||||
return EINA_FALSE;
|
||||
if (key) keylen = strlen(key) + 1;
|
||||
filelen = strlen(file);
|
||||
|
||||
path = _shared_string_get(fd->path);
|
||||
key = _shared_string_get(fd->key);
|
||||
loader = _shared_string_get(fd->loader_data);
|
||||
if (filelen + keylen + 1 > hkey_size)
|
||||
return NULL;
|
||||
|
||||
if (!path && ie->file)
|
||||
return EINA_FALSE;
|
||||
if (ie->file && strcmp(path, ie->file))
|
||||
return EINA_FALSE;
|
||||
memcpy(hkey, file, filelen);
|
||||
hkey[filelen] = ':';
|
||||
if (key)
|
||||
memcpy(hkey + filelen + 1, key, keylen);
|
||||
else
|
||||
memcpy(hkey + filelen + 1, "(null)", 7);
|
||||
|
||||
if (!key && ie->key)
|
||||
return EINA_FALSE;
|
||||
if (ie->key && strcmp(key, ie->key))
|
||||
return EINA_FALSE;
|
||||
|
||||
/*
|
||||
if (!loader && ie->loader_data)
|
||||
return EINA_FALSE;
|
||||
if (strcmp(loader, ie->loader_data))
|
||||
return EINA_FALSE;
|
||||
*/
|
||||
|
||||
// Check w,h ?
|
||||
// Not sure which load opts should be checked here
|
||||
DBG("Found a match for %s:%s", ie->file, ie->key);
|
||||
return EINA_TRUE;
|
||||
return hkey;
|
||||
}
|
||||
|
||||
static const File_Data *
|
||||
|
@ -1904,32 +1809,122 @@ _shared_image_entry_file_data_find(Image_Entry *ie)
|
|||
{
|
||||
const File_Data *fdata = NULL;
|
||||
File_Entry *fe;
|
||||
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
|
||||
char hkey[PATH_MAX];
|
||||
int k;
|
||||
|
||||
DBG("Trying to find if image '%s:%s' is already opened by cserve2",
|
||||
ie->file, ie->key);
|
||||
|
||||
if (!_index.files.entries.fdata)
|
||||
SHARED_INDEX_CHECK(_index.files, File_Data);
|
||||
|
||||
if (!_index.strings_index.header || !_index.strings_entries.data)
|
||||
return NULL;
|
||||
|
||||
#warning FIXME Use safe count
|
||||
for (k = 0; k < _index.files.header->count; k++)
|
||||
if (!_index.files.header || !_index.files.entries.fdata)
|
||||
return NULL;
|
||||
|
||||
// Direct access
|
||||
fe = ie->data1;
|
||||
if (fe->server_file_id)
|
||||
{
|
||||
const File_Data *fd = &(_index.files.entries.fdata[k]);
|
||||
if (!fd->id) return NULL;
|
||||
if ((fdata = _shared_file_data_get_by_id(fe->server_file_id)) != NULL)
|
||||
return fdata;
|
||||
}
|
||||
|
||||
// Check hash
|
||||
_shared_file_data_hkey_get(hkey, ie->file, ie->key, PATH_MAX);
|
||||
fdata = eina_hash_find(_index.files.entries_by_hkey, hkey);
|
||||
if (fdata)
|
||||
return fdata;
|
||||
|
||||
// Scan shared index
|
||||
for (k = _index.files.last_entry_in_hash;
|
||||
k < _index.files.count && k < _index.files.header->emptyidx; k++)
|
||||
{
|
||||
const char *file, *key;
|
||||
const File_Data *fd;
|
||||
char fd_hkey[PATH_MAX];
|
||||
|
||||
fd = &(_index.files.entries.fdata[k]);
|
||||
if (!fd->id) break;
|
||||
if (!fd->refcount) continue;
|
||||
|
||||
if (_shared_image_entry_file_data_match(ie, fd))
|
||||
file = _shared_string_get(fd->path);
|
||||
if (!file)
|
||||
{
|
||||
fdata = fd;
|
||||
break;
|
||||
ERR("Could not find filename for file %d", fd->id);
|
||||
add_to_hash = EINA_FALSE;
|
||||
continue;
|
||||
}
|
||||
key = _shared_string_get(fd->key);
|
||||
|
||||
_shared_file_data_hkey_get(fd_hkey, file, key, PATH_MAX);
|
||||
|
||||
if (add_to_hash)
|
||||
{
|
||||
eina_hash_add(_index.files.entries_by_hkey, fd_hkey, fd);
|
||||
_index.files.last_entry_in_hash = k;
|
||||
}
|
||||
|
||||
DBG("Found file data for %s:%s: %d", ie->file, ie->key, fdata->id);
|
||||
fe = ie->data1;
|
||||
fe->server_file_id = fdata->id;
|
||||
return fdata;
|
||||
if (!strcmp(hkey, fd_hkey))
|
||||
return fd;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const Shm_Object *
|
||||
_shared_index_item_get_by_id(Shared_Index *si, int elemsize, unsigned int id)
|
||||
{
|
||||
const Shm_Object *obj;
|
||||
const char *base;
|
||||
int low = 0, high, start_high;
|
||||
int cur;
|
||||
|
||||
if (!si || elemsize <= 0 || !id)
|
||||
return NULL;
|
||||
|
||||
// FIXME: HACK (consider all arrays always sorted by id)
|
||||
high = si->header->emptyidx; // Should be si->header->sortedidx
|
||||
|
||||
if (high > si->count)
|
||||
high = si->count;
|
||||
|
||||
base = si->data + sizeof(Shared_Array_Header);
|
||||
|
||||
// Binary search
|
||||
start_high = high;
|
||||
while(high != low)
|
||||
{
|
||||
cur = low + ((high - low) / 2);
|
||||
obj = (Shm_Object *) (base + (elemsize * cur));
|
||||
if (obj->id == id)
|
||||
return obj;
|
||||
if (obj->id < id)
|
||||
low = cur + 1;
|
||||
else
|
||||
high = cur;
|
||||
}
|
||||
|
||||
// Linear search
|
||||
for (cur = start_high; cur < si->count; cur++)
|
||||
{
|
||||
obj = (Shm_Object *) (base + (elemsize * cur));
|
||||
if (!obj->id)
|
||||
return NULL;
|
||||
if (obj->id == id)
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const File_Data *
|
||||
_shared_file_data_get_by_id(unsigned int id)
|
||||
{
|
||||
return (const File_Data *)
|
||||
_shared_index_item_get_by_id(&_index.files, sizeof(File_Data), id);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
|
@ -1945,9 +1940,6 @@ _shared_image_entry_image_data_match(Image_Entry *ie, const Image_Data *id)
|
|||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
#define SHARED_INDEX_CHECK(si, typ) \
|
||||
if (!_shared_index_remap_check(&(si), sizeof(typ))) return NULL
|
||||
|
||||
static Eina_Bool
|
||||
_shared_index_remap_check(Shared_Index *si, int elemsize)
|
||||
{
|
||||
|
@ -1957,10 +1949,25 @@ _shared_index_remap_check(Shared_Index *si, int elemsize)
|
|||
// Note: all checks are unlikely to be true.
|
||||
|
||||
if (!si || elemsize <= 0) return EINA_FALSE;
|
||||
|
||||
if (si->generation_id != _index.generation_id)
|
||||
{
|
||||
DBG("Generation ID changed.");
|
||||
if (si->f && si->data)
|
||||
DBG("Generation ID changed from %d to %d.",
|
||||
si->generation_id, _index.generation_id);
|
||||
if (si->f)
|
||||
{
|
||||
if (strncmp(si->path, eina_file_filename_get(si->f),
|
||||
SHARED_BUFFER_PATH_MAX) != 0)
|
||||
{
|
||||
DBG("Index file changed. Closing and reopening.");
|
||||
eina_file_map_free(si->f, si->data);
|
||||
eina_file_close(si->f);
|
||||
si->f = NULL;
|
||||
si->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (si->data)
|
||||
{
|
||||
if (eina_file_refresh(si->f))
|
||||
{
|
||||
|
@ -1969,11 +1976,13 @@ _shared_index_remap_check(Shared_Index *si, int elemsize)
|
|||
si->data = NULL;
|
||||
}
|
||||
}
|
||||
else if (si->f)
|
||||
else
|
||||
{
|
||||
eina_file_close(si->f);
|
||||
si->f = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
si->generation_id = _index.generation_id;
|
||||
}
|
||||
if (!si->f)
|
||||
|
@ -2039,6 +2048,7 @@ _shared_index_remap_check(Shared_Index *si, int elemsize)
|
|||
if (si->entries_by_hkey) eina_hash_free_buckets(si->entries_by_hkey);
|
||||
else si->entries_by_hkey = eina_hash_string_small_new(NULL);
|
||||
si->last_entry_in_hash = 0;
|
||||
si->entries.p = si->data + sizeof(Shared_Array_Header);
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
|
@ -2048,16 +2058,28 @@ static const Image_Data *
|
|||
_shared_image_entry_image_data_find(Image_Entry *ie)
|
||||
{
|
||||
const Image_Data *idata = NULL;
|
||||
const char *shmpath;
|
||||
File_Entry *fe;
|
||||
unsigned int file_id = 0;
|
||||
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
|
||||
int k;
|
||||
|
||||
|
||||
DBG("Trying to find if image '%s:%s' is already loaded by cserve2",
|
||||
ie->file, ie->key);
|
||||
|
||||
if (!_index.strings_entries.data || !_index.strings_index.data)
|
||||
return NULL;
|
||||
|
||||
if (!_index.images.entries.idata || !_index.images.count)
|
||||
return NULL;
|
||||
|
||||
if (!ie->cache_key)
|
||||
{
|
||||
CRIT("Looking for an image in remote cache without hash key?");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fe = ie->data1;
|
||||
if (fe && fe->server_file_id)
|
||||
file_id = fe->server_file_id;
|
||||
|
@ -2074,32 +2096,79 @@ _shared_image_entry_image_data_find(Image_Entry *ie)
|
|||
|
||||
SHARED_INDEX_CHECK(_index.images, Image_Data);
|
||||
|
||||
DBG("Looking for loaded image with file id %d", file_id);
|
||||
for (k = 0; k < _index.images.count; k++)
|
||||
// Find in known entries hash. O(log n)
|
||||
DBG("Looking for %s in hash", ie->cache_key);
|
||||
idata = (const Image_Data *)
|
||||
eina_hash_find(_index.images.entries_by_hkey, ie->cache_key);
|
||||
if (idata)
|
||||
{
|
||||
ERR("Image found in shared index (by cache_key).");
|
||||
goto found;
|
||||
}
|
||||
|
||||
// Linear search in non-hashed entries. O(n)
|
||||
DBG("Looking for loaded image with file id %d", file_id);
|
||||
for (k = _index.images.last_entry_in_hash; k < _index.images.count; k++)
|
||||
{
|
||||
const char *file, *key;
|
||||
size_t keylen, filelen;
|
||||
const File_Data *fd;
|
||||
char *hkey;
|
||||
const Image_Data *id = &(_index.images.entries.idata[k]);
|
||||
|
||||
if (!id->id) return NULL;
|
||||
if (!id->refcount) continue;
|
||||
|
||||
if (add_to_hash)
|
||||
{
|
||||
fd = _shared_file_data_get_by_id(id->file_id);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Did not find file data for %d", id->file_id);
|
||||
add_to_hash = EINA_FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
key = _shared_string_get(fd->key);
|
||||
file = _shared_string_get(fd->path);
|
||||
if (!file)
|
||||
{
|
||||
ERR("No filename for file %d", fd->id);
|
||||
add_to_hash = EINA_FALSE;
|
||||
continue;
|
||||
}
|
||||
keylen = key ? strlen(key) : 0;
|
||||
filelen = strlen(file);
|
||||
|
||||
hkey = alloca(filelen + keylen + HKEY_LOAD_OPTS_STR_LEN);
|
||||
evas_cache2_image_cache_key_create(hkey, file, filelen,
|
||||
key, keylen, &id->opts);
|
||||
eina_hash_add(_index.images.entries_by_hkey, hkey, id);
|
||||
_index.images.last_entry_in_hash = k;
|
||||
}
|
||||
|
||||
if (id->file_id != file_id) continue;
|
||||
|
||||
if (_shared_image_entry_image_data_match(ie, id))
|
||||
{
|
||||
idata = id;
|
||||
break;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
if (!idata)
|
||||
return NULL;
|
||||
|
||||
if (!_shared_string_get(idata->shm_id))
|
||||
found:
|
||||
shmpath = _shared_string_get(idata->shm_id);
|
||||
if (!shmpath)
|
||||
{
|
||||
ERR("Found image but it is not loaded yet: %d (doload %d shm %s)",
|
||||
idata->id, idata->doload, _shared_string_get(idata->shm_id));
|
||||
ERR("Found image but it is not loaded yet: %d (doload %d)",
|
||||
idata->id, idata->doload);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBG("Found image, loaded, in shm %s", _shared_string_get(idata->shm_id));
|
||||
DBG("Found image, loaded, in shm %s", shmpath);
|
||||
return idata;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,15 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_cs2.h"
|
||||
|
||||
#define SHARED_BUFFER_PATH_MAX 64
|
||||
typedef struct _Data_Entry Data_Entry;
|
||||
typedef struct _Font_Entry Font_Entry;
|
||||
typedef struct _Index_Table Index_Table;
|
||||
typedef struct _Shared_Index Shared_Index;
|
||||
typedef struct _Shared_Buffer Shared_Buffer;
|
||||
|
||||
struct _Data_Entry {
|
||||
struct _Data_Entry
|
||||
{
|
||||
unsigned int image_id;
|
||||
void (*preloaded_cb)(void *, Eina_Bool);
|
||||
struct {
|
||||
|
@ -23,14 +26,15 @@ struct _Data_Entry {
|
|||
} shm;
|
||||
};
|
||||
|
||||
struct _Shared_Index {
|
||||
char path[64];
|
||||
struct _Shared_Index
|
||||
{
|
||||
char path[SHARED_BUFFER_PATH_MAX];
|
||||
int generation_id;
|
||||
Eina_File *f;
|
||||
union
|
||||
{
|
||||
const Shared_Array_Header *header;
|
||||
void *data;
|
||||
char *data;
|
||||
};
|
||||
union
|
||||
{
|
||||
|
@ -45,19 +49,19 @@ struct _Shared_Index {
|
|||
int last_entry_in_hash;
|
||||
};
|
||||
|
||||
struct _Index_Table {
|
||||
struct _Shared_Buffer
|
||||
{
|
||||
char path[SHARED_BUFFER_PATH_MAX];
|
||||
Eina_File *f;
|
||||
char *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct _Index_Table
|
||||
{
|
||||
int generation_id;
|
||||
// TODO: use Shared_Index
|
||||
struct {
|
||||
char index_path[64];
|
||||
char entries_path[64];
|
||||
Eina_File *index_file;
|
||||
Eina_File *entries_file;
|
||||
const Shared_Array_Header *index_header;
|
||||
const Index_Entry *indexes;
|
||||
const char *data;
|
||||
size_t entries_size;
|
||||
} strings;
|
||||
Shared_Buffer strings_entries;
|
||||
Shared_Index strings_index;
|
||||
Shared_Index files;
|
||||
Shared_Index images;
|
||||
Shared_Index fonts; // TODO
|
||||
|
|
Loading…
Reference in New Issue