forked from enlightenment/efl
evas/cserve2: Use Shared_Array storage for File_Data
File_Entry and File_Data are now two different types, one being stored in the shared array, the other one is only a reference counting entry.
This commit is contained in:
parent
c57a319df3
commit
acae35b4d1
|
@ -14,20 +14,15 @@
|
|||
|
||||
#include <Evas_Loader.h>
|
||||
|
||||
// For testing purposes only.
|
||||
#define EXPERIMENTAL_SHARED_INDEX 0
|
||||
#if EXPERIMENTAL_SHARED_INDEX
|
||||
typedef int string_t;
|
||||
#else
|
||||
#define cserve2_shared_string_get(str) (str)
|
||||
#define cserve2_shared_string_del(str) (eina_stringshare_del(str))
|
||||
#define cserve2_shared_string_add(str) (eina_stringshare_add(str))
|
||||
#define cserve2_shared_string_ref(str) (eina_stringshare_ref(str))
|
||||
typedef Eina_Stringshare* string_t;
|
||||
#endif
|
||||
#define ENTRY Entry base
|
||||
#define ASENTRY(a) (&(a->base))
|
||||
#define SHMOBJECT unsigned int id; unsigned int refcount
|
||||
|
||||
typedef struct _Entry Entry;
|
||||
typedef struct _Shm_Object Shm_Object;
|
||||
typedef struct _Reference Reference;
|
||||
typedef struct _File_Entry File_Entry;
|
||||
typedef struct _File_Data File_Data;
|
||||
typedef struct _Image_Data Image_Data;
|
||||
typedef struct _File_Watch File_Watch;
|
||||
|
@ -55,8 +50,19 @@ struct _Entry {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct _Shm_Object
|
||||
{
|
||||
SHMOBJECT;
|
||||
};
|
||||
|
||||
struct _File_Entry {
|
||||
ENTRY;
|
||||
File_Watch *watcher;
|
||||
Eina_List *images;
|
||||
};
|
||||
|
||||
struct _File_Data {
|
||||
Entry base;
|
||||
SHMOBJECT;
|
||||
string_t path;
|
||||
string_t key;
|
||||
string_t loader_data;
|
||||
|
@ -64,8 +70,6 @@ struct _File_Data {
|
|||
int frame_count;
|
||||
int loop_count;
|
||||
int loop_hint;
|
||||
File_Watch *watcher;
|
||||
Eina_List *images;
|
||||
Eina_Bool alpha : 1;
|
||||
Eina_Bool invalid : 1;
|
||||
};
|
||||
|
@ -74,7 +78,6 @@ struct _File_Data {
|
|||
struct _Image_Data {
|
||||
Entry base;
|
||||
unsigned int file_id;
|
||||
File_Data *file;
|
||||
Evas_Image_Load_Opts opts;
|
||||
Shm_Handle *shm;
|
||||
Eina_Bool alpha_sparse : 1;
|
||||
|
@ -172,6 +175,8 @@ struct _File_Watch {
|
|||
};
|
||||
|
||||
static unsigned int _entry_id = 0;
|
||||
static Shared_Array *_file_data_array = NULL;
|
||||
|
||||
static Eina_Hash *file_ids = NULL; // maps path + key --> file_id
|
||||
static Eina_Hash *file_entries = NULL; // maps file_id --> entry
|
||||
|
||||
|
@ -235,6 +240,54 @@ _entry_load_reused(Entry *e)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_shm_object_id_find_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;
|
||||
|
||||
obj = data1;
|
||||
key = *((unsigned int *) data2);
|
||||
if (obj->id == key) return 0;
|
||||
if (obj->id < key)
|
||||
return -1;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
|
||||
static inline File_Data *
|
||||
_file_data_find(unsigned int file_id)
|
||||
{
|
||||
File_Data *fd;
|
||||
|
||||
fd = cserve2_shared_array_item_data_find(_file_data_array, &file_id,
|
||||
_shm_object_id_find_cb);
|
||||
if (fd && !fd->refcount)
|
||||
{
|
||||
ERR("Can not access object %u with refcount 0", file_id);
|
||||
return NULL;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static inline File_Entry *
|
||||
_file_entry_find(unsigned int entry_id)
|
||||
{
|
||||
Entry *e;
|
||||
|
||||
e = (Entry *) eina_hash_find(file_entries, &entry_id);
|
||||
if (!e || e->type != CSERVE2_IMAGE_FILE)
|
||||
return NULL;
|
||||
|
||||
return (File_Entry *) e;
|
||||
}
|
||||
|
||||
|
||||
static Msg_Opened *
|
||||
_image_opened_msg_create(File_Data *fd, int *size)
|
||||
{
|
||||
|
@ -260,7 +313,7 @@ _image_opened_send(Client *client, File_Data *fd, unsigned int rid)
|
|||
int size;
|
||||
Msg_Opened *msg;
|
||||
|
||||
DBG("Sending OPENED reply for entry: %d and RID: %d.", fd->base.id, rid);
|
||||
DBG("Sending OPENED reply for entry: %d and RID: %d.", fd->id, rid);
|
||||
// clear the struct with possible paddings, since it is not aligned.
|
||||
|
||||
msg = _image_opened_msg_create(fd, &size);
|
||||
|
@ -334,12 +387,20 @@ _font_loaded_send(Client *client, unsigned int rid)
|
|||
}
|
||||
|
||||
static void *
|
||||
_open_request_build(File_Data *fd, int *bufsize)
|
||||
_open_request_build(Entry *entry, int *bufsize)
|
||||
{
|
||||
const char *loader_data;
|
||||
char *buf;
|
||||
int size, pathlen, keylen, loaderlen;
|
||||
Slave_Msg_Image_Open msg;
|
||||
File_Data *fd;
|
||||
|
||||
fd = _file_data_find(entry->id);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Could not find file data for entry %u", entry->id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pathlen = strlen(cserve2_shared_string_get(fd->path)) + 1;
|
||||
keylen = strlen(cserve2_shared_string_get(fd->key)) + 1;
|
||||
|
@ -361,7 +422,7 @@ _open_request_build(File_Data *fd, int *bufsize)
|
|||
|
||||
*bufsize = size;
|
||||
|
||||
_entry_load_start(&fd->base);
|
||||
_entry_load_start(entry);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -373,11 +434,19 @@ _request_free(void *msg, void *data EINA_UNUSED)
|
|||
}
|
||||
|
||||
static Msg_Opened *
|
||||
_open_request_response(File_Data *fd, Slave_Msg_Image_Opened *resp, int *size)
|
||||
_open_request_response(Entry *entry, Slave_Msg_Image_Opened *resp, int *size)
|
||||
{
|
||||
_entry_load_finish(&fd->base);
|
||||
File_Data *fd;
|
||||
|
||||
fd->base.request = NULL;
|
||||
_entry_load_finish(entry);
|
||||
entry->request = NULL;
|
||||
|
||||
fd = _file_data_find(entry->id);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Could not find file data for entry %u", entry->id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd->w = resp->w;
|
||||
fd->h = resp->h;
|
||||
|
@ -436,18 +505,26 @@ _load_request_build(Image_Data *i, int *bufsize)
|
|||
int size;
|
||||
int shmlen, filelen, keylen, loaderlen;
|
||||
Slave_Msg_Image_Load msg;
|
||||
File_Data *fd;
|
||||
|
||||
fd = _file_data_find(i->file_id);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Could not find file data %u for image %u", i->file_id, i->base.id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// opening shm for this file
|
||||
i->shm = cserve2_shm_request("img", i->file->w * i->file->h * 4);
|
||||
i->shm = cserve2_shm_request("img", fd->w * fd->h * 4);
|
||||
if (!i->shm)
|
||||
return NULL;
|
||||
|
||||
shmpath = cserve2_shm_name_get(i->shm);
|
||||
|
||||
shmlen = strlen(shmpath) + 1;
|
||||
filelen = strlen(cserve2_shared_string_get(i->file->path)) + 1;
|
||||
keylen = strlen(cserve2_shared_string_get(i->file->key)) + 1;
|
||||
loader_data = cserve2_shared_string_get(i->file->loader_data);
|
||||
filelen = strlen(cserve2_shared_string_get(fd->path)) + 1;
|
||||
keylen = strlen(cserve2_shared_string_get(fd->key)) + 1;
|
||||
loader_data = cserve2_shared_string_get(fd->loader_data);
|
||||
if (loader_data)
|
||||
loaderlen = strlen(loader_data) + 1;
|
||||
else
|
||||
|
@ -458,9 +535,9 @@ _load_request_build(Image_Data *i, int *bufsize)
|
|||
if (!buf) return NULL;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.w = i->file->w;
|
||||
msg.h = i->file->h;
|
||||
msg.alpha = i->file->alpha;
|
||||
msg.w = fd->w;
|
||||
msg.h = fd->h;
|
||||
msg.alpha = fd->alpha;
|
||||
|
||||
// NOTE: Not passing scale_load options
|
||||
msg.opts.w = i->opts.w;
|
||||
|
@ -483,11 +560,11 @@ _load_request_build(Image_Data *i, int *bufsize)
|
|||
|
||||
memcpy(ptr, shmpath, shmlen);
|
||||
ptr += shmlen;
|
||||
memcpy(ptr, cserve2_shared_string_get(i->file->path), filelen);
|
||||
memcpy(ptr, cserve2_shared_string_get(fd->path), filelen);
|
||||
ptr += filelen;
|
||||
memcpy(ptr, cserve2_shared_string_get(i->file->key), keylen);
|
||||
memcpy(ptr, cserve2_shared_string_get(fd->key), keylen);
|
||||
ptr += keylen;
|
||||
if (loaderlen > 0) memcpy(ptr, cserve2_shared_string_get(i->file->loader_data), loaderlen);
|
||||
if (loaderlen > 0) memcpy(ptr, cserve2_shared_string_get(fd->loader_data), loaderlen);
|
||||
|
||||
*bufsize = size;
|
||||
|
||||
|
@ -509,6 +586,15 @@ _scaling_do(Shm_Handle *scale_shm, Image_Data *entry, Image_Data *original)
|
|||
{
|
||||
char *scale_map, *orig_map;
|
||||
void *src_data, *dst_data;
|
||||
File_Data *fd;
|
||||
|
||||
fd = _file_data_find(entry->file_id);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Could not find file data %u for image %u",
|
||||
entry->file_id, entry->base.id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
scale_map = cserve2_shm_map(scale_shm);
|
||||
if (scale_map == MAP_FAILED)
|
||||
|
@ -540,7 +626,7 @@ _scaling_do(Shm_Handle *scale_shm, Image_Data *entry, Image_Data *original)
|
|||
entry->opts.scale_load.src_w, entry->opts.scale_load.src_h,
|
||||
0, 0,
|
||||
entry->opts.scale_load.dst_w, entry->opts.scale_load.dst_h,
|
||||
entry->file->alpha, entry->opts.scale_load.smooth);
|
||||
fd->alpha, entry->opts.scale_load.smooth);
|
||||
|
||||
cserve2_shm_unmap(original->shm);
|
||||
cserve2_shm_unmap(scale_shm);
|
||||
|
@ -572,9 +658,6 @@ _scaling_prepare_and_do(Image_Data *orig)
|
|||
static Msg_Loaded *
|
||||
_load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size)
|
||||
{
|
||||
const char *path = cserve2_shared_string_get(e->file->path);
|
||||
const char *key = cserve2_shared_string_get(e->file->key);
|
||||
|
||||
_entry_load_finish(&e->base);
|
||||
|
||||
e->base.request = NULL;
|
||||
|
@ -586,17 +669,15 @@ _load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size)
|
|||
if (_scaling_needed(e, resp))
|
||||
{
|
||||
|
||||
DBG("About to scale down image '%s%s'", path, key);
|
||||
DBG("About to scale down image %u", ASENTRY(e)->id);
|
||||
|
||||
if (!_scaling_prepare_and_do(e))
|
||||
DBG("Image '%s:%s' has been scaled down.",
|
||||
path, key);
|
||||
DBG("Image %u has been scaled down.", ASENTRY(e)->id);
|
||||
else
|
||||
ERR("Failed to scale down image '%s%s'",
|
||||
path, key);
|
||||
ERR("Failed to scale down image %u", ASENTRY(e)->id);
|
||||
}
|
||||
else
|
||||
DBG("No scaling needed for image '%s%s'", path, key);
|
||||
DBG("No scaling needed for image %u", ASENTRY(e)->id);
|
||||
|
||||
return _image_loaded_msg_create(e, size);
|
||||
}
|
||||
|
@ -652,9 +733,11 @@ _file_id_free(File_Data *fd)
|
|||
char buf[4096];
|
||||
|
||||
DBG("Removing entry file id: %d, file: \"%s:%s\"",
|
||||
fd->base.id, cserve2_shared_string_get(fd->path), cserve2_shared_string_get(fd->key));
|
||||
fd->id, cserve2_shared_string_get(fd->path),
|
||||
cserve2_shared_string_get(fd->key));
|
||||
snprintf(buf, sizeof(buf), "%s:%s",
|
||||
cserve2_shared_string_get(fd->path), cserve2_shared_string_get(fd->key));
|
||||
cserve2_shared_string_get(fd->path),
|
||||
cserve2_shared_string_get(fd->key));
|
||||
eina_hash_del_by_key(file_ids, buf);
|
||||
}
|
||||
|
||||
|
@ -672,7 +755,8 @@ _image_id_free(Image_Data *entry)
|
|||
static void
|
||||
_image_entry_free(Image_Data *entry)
|
||||
{
|
||||
File_Data *fd = entry->file;
|
||||
File_Data *fd;
|
||||
File_Entry *fentry;
|
||||
|
||||
if (entry->base.request)
|
||||
cserve2_request_cancel_all(entry->base.request, CSERVE2_REQUEST_CANCEL);
|
||||
|
@ -683,12 +767,17 @@ _image_entry_free(Image_Data *entry)
|
|||
unused_mem_usage -= _image_entry_size_get(entry);
|
||||
}
|
||||
|
||||
fd = _file_data_find(entry->file_id);
|
||||
if (fd)
|
||||
{
|
||||
fd->images = eina_list_remove(fd->images, entry);
|
||||
if (!fd->images && !fd->base.references)
|
||||
eina_hash_del_by_key(file_entries, &fd->base.id);
|
||||
fentry = _file_entry_find(fd->id);
|
||||
fentry->images = eina_list_remove(fentry->images, entry);
|
||||
if (fentry && !fentry->images && !ASENTRY(fentry)->references)
|
||||
eina_hash_del_by_key(file_entries, &fd->id);
|
||||
}
|
||||
else
|
||||
ERR("Could not find file data %u for image %u",
|
||||
entry->file_id, ASENTRY(entry)->id);
|
||||
if (entry->shm)
|
||||
cserve2_shm_unref(entry->shm);
|
||||
free(entry);
|
||||
|
@ -704,44 +793,60 @@ _hash_image_entry_free(void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
_file_entry_free(File_Data *fd)
|
||||
_file_entry_free(File_Entry *fentry)
|
||||
{
|
||||
File_Watch *fw;
|
||||
|
||||
if (!fentry) return;
|
||||
|
||||
// Should we call free for each of the images too?
|
||||
// If everything goes fine, it's not necessary.
|
||||
if (fd->images)
|
||||
|
||||
if (fentry->images)
|
||||
{
|
||||
ERR("Freeing file %d (\"%s:%s\") image data still referenced.",
|
||||
fd->base.id, cserve2_shared_string_get(fd->path), cserve2_shared_string_get(fd->key));
|
||||
eina_list_free(fd->images);
|
||||
ERR("Freeing file %u image data still referenced.", ASENTRY(fentry)->id);
|
||||
eina_list_free(fentry->images);
|
||||
}
|
||||
if (ASENTRY(fentry)->request)
|
||||
cserve2_request_cancel_all(ASENTRY(fentry)->request,
|
||||
CSERVE2_REQUEST_CANCEL);
|
||||
|
||||
if (fd->base.request)
|
||||
cserve2_request_cancel_all(fd->base.request, CSERVE2_REQUEST_CANCEL);
|
||||
|
||||
if ((fw = fd->watcher))
|
||||
if ((fw = fentry->watcher))
|
||||
{
|
||||
fw->entries = eina_list_remove(fw->entries, fd);
|
||||
fw->entries = eina_list_remove(fw->entries, fentry);
|
||||
if (!fw->entries)
|
||||
eina_hash_del_by_key(file_watch, fw->path);
|
||||
}
|
||||
|
||||
free(fentry);
|
||||
}
|
||||
|
||||
static void
|
||||
_file_data_free(File_Data *fd)
|
||||
{
|
||||
if (!fd) return;
|
||||
if (!fd->refcount) return;
|
||||
if (--fd->refcount == 0)
|
||||
{
|
||||
cserve2_shared_string_del(fd->key);
|
||||
cserve2_shared_string_del(fd->path);
|
||||
cserve2_shared_string_del(fd->loader_data);
|
||||
free(fd);
|
||||
memset((char *) fd + sizeof(fd->id), 0, sizeof(*fd) - sizeof(fd->id));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_hash_file_entry_free(void *data)
|
||||
{
|
||||
File_Data *fd = data;
|
||||
File_Entry *fentry = data;
|
||||
File_Data *fd;
|
||||
// TODO: Add some checks to make sure that we are freeing an
|
||||
// unused entry.
|
||||
|
||||
fd = _file_data_find(ASENTRY(fentry)->id);
|
||||
_file_id_free(fd);
|
||||
_file_entry_free(fd);
|
||||
_file_entry_free(fentry);
|
||||
_file_data_free(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -904,6 +1009,8 @@ cserve2_cache_init(void)
|
|||
EINA_KEY_HASH(_font_entry_key_hash),
|
||||
EINA_FREE_CB(_font_entry_free),
|
||||
5);
|
||||
|
||||
_file_data_array = cserve2_shared_array_new(1, sizeof(File_Data), 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -922,6 +1029,8 @@ cserve2_cache_shutdown(void)
|
|||
|
||||
eina_hash_free(font_entries);
|
||||
eina_hash_free(font_sources);
|
||||
|
||||
cserve2_shared_array_del(_file_data_array);
|
||||
}
|
||||
|
||||
static Reference *
|
||||
|
@ -983,22 +1092,32 @@ _entry_reference_del(Entry *entry, Reference *ref)
|
|||
|
||||
if (entry->type == CSERVE2_IMAGE_FILE)
|
||||
{
|
||||
File_Data *fd = (File_Data *)entry;
|
||||
File_Entry *fentry = (File_Entry *) entry;
|
||||
File_Data *fd = _file_data_find(entry->id);
|
||||
|
||||
if (fd)
|
||||
{
|
||||
if (fd->invalid)
|
||||
_file_entry_free(fd);
|
||||
else if (!fd->images)
|
||||
{
|
||||
_file_entry_free(fentry);
|
||||
_file_data_free(fd);
|
||||
}
|
||||
else if (!fentry->images)
|
||||
eina_hash_del_by_key(file_entries, &entry->id);
|
||||
}
|
||||
else
|
||||
ERR("File data not found for id %u", entry->id);
|
||||
/* don't free file entries that have images attached to it, they will
|
||||
* be freed when the last unused image is freed */
|
||||
}
|
||||
else if (entry->type == CSERVE2_IMAGE_DATA)
|
||||
{
|
||||
Image_Data *ientry = (Image_Data *)entry;
|
||||
Image_Data *ientry = (Image_Data *) entry;
|
||||
File_Data *fd = _file_data_find(entry->id);
|
||||
|
||||
if (!ientry->file)
|
||||
if (!fd)
|
||||
eina_hash_del_by_key(image_entries, &entry->id);
|
||||
else if (ientry->file->invalid)
|
||||
else if (fd->invalid)
|
||||
_image_entry_free(ientry);
|
||||
else
|
||||
_entry_unused_push(ientry);
|
||||
|
@ -1090,22 +1209,24 @@ cserve2_cache_client_del(Client *client)
|
|||
|
||||
static Image_Data *
|
||||
_image_entry_new(Client *client, int rid,
|
||||
unsigned int file_id, unsigned int image_id,
|
||||
unsigned int client_file_id, unsigned int image_id,
|
||||
Evas_Image_Load_Opts *opts)
|
||||
{
|
||||
Reference *ref;
|
||||
Image_Data *im_entry;
|
||||
File_Data *fd;
|
||||
|
||||
ref = eina_hash_find(client->files.referencing, &file_id);
|
||||
ref = eina_hash_find(client->files.referencing, &client_file_id);
|
||||
if (!ref)
|
||||
{
|
||||
ERR("Couldn't find file id: %d, for image id: %d",
|
||||
file_id, image_id);
|
||||
client_file_id, image_id);
|
||||
cserve2_client_error_send(client, rid,
|
||||
CSERVE2_INVALID_CACHE);
|
||||
return NULL;
|
||||
}
|
||||
if (((File_Data *)ref->entry)->invalid)
|
||||
fd = _file_data_find(ref->entry->id);
|
||||
if (!fd || fd->invalid)
|
||||
{
|
||||
cserve2_client_error_send(client, rid,
|
||||
CSERVE2_FILE_CHANGED);
|
||||
|
@ -1115,7 +1236,6 @@ _image_entry_new(Client *client, int rid,
|
|||
im_entry = calloc(1, sizeof(*im_entry));
|
||||
im_entry->base.type = CSERVE2_IMAGE_DATA;
|
||||
im_entry->file_id = ref->entry->id;
|
||||
im_entry->file = (File_Data *)ref->entry;
|
||||
if (opts)
|
||||
{
|
||||
im_entry->opts.dpi = opts->dpi;
|
||||
|
@ -1152,11 +1272,19 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
|
|||
{
|
||||
Eina_List *ll;
|
||||
Image_Data *ie;
|
||||
File_Entry *fentry;
|
||||
|
||||
fd->invalid = EINA_TRUE;
|
||||
fd->watcher = NULL;
|
||||
fentry = _file_entry_find(fd->id);
|
||||
if (!fentry)
|
||||
{
|
||||
ERR("Could not find file entry for id %u", fd->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
EINA_LIST_FOREACH(fd->images, ll, ie)
|
||||
fentry->watcher = NULL;
|
||||
|
||||
EINA_LIST_FOREACH(fentry->images, ll, ie)
|
||||
{
|
||||
_image_id_free(ie);
|
||||
eina_hash_set(image_entries, &ie->base.id, NULL);
|
||||
|
@ -1169,12 +1297,19 @@ _file_changed_cb(const char *path EINA_UNUSED, Eina_Bool deleted EINA_UNUSED, vo
|
|||
}
|
||||
|
||||
_file_id_free(fd);
|
||||
eina_hash_set(file_entries, &fd->base.id, NULL);
|
||||
if (fd->base.request /*&& !fd->base.request->processing*/)
|
||||
cserve2_request_cancel_all(fd->base.request, CSERVE2_FILE_CHANGED);
|
||||
fd->base.request = NULL;
|
||||
if (!fd->images && !fd->base.references)
|
||||
_file_entry_free(fd);
|
||||
eina_hash_set(file_entries, &fd->id, NULL);
|
||||
if (ASENTRY(fentry)->request
|
||||
/*&& !ASENTRY(fentry)->request->processing*/)
|
||||
{
|
||||
cserve2_request_cancel_all(ASENTRY(fentry)->request,
|
||||
CSERVE2_FILE_CHANGED);
|
||||
ASENTRY(fentry)->request = NULL;
|
||||
}
|
||||
if (!fentry->images && !ASENTRY(fentry)->references)
|
||||
{
|
||||
_file_entry_free(fentry);
|
||||
_file_data_free(fd);
|
||||
}
|
||||
}
|
||||
|
||||
eina_hash_del_by_key(file_watch, fw->path);
|
||||
|
@ -1220,8 +1355,6 @@ _font_load_request_build(void *data, int *size)
|
|||
msg->rend_flags = fe->rend_flags;
|
||||
msg->size = fe->size;
|
||||
msg->dpi = fe->dpi;
|
||||
|
||||
#warning TODO Use shared index on client side
|
||||
msg->name = cserve2_shared_string_get(fe->src->name);
|
||||
msg->file = cserve2_shared_string_get(fe->src->file);
|
||||
|
||||
|
@ -1751,21 +1884,21 @@ static Eina_Bool
|
|||
_image_file_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, void *data, void *fdata)
|
||||
{
|
||||
Msg_Stats *msg = fdata;
|
||||
File_Data *fd = data;
|
||||
File_Entry *fentry = data;
|
||||
|
||||
// accounting numbers
|
||||
msg->images.files_loaded++;
|
||||
|
||||
// accounting size
|
||||
msg->images.files_size += sizeof(File_Data) +
|
||||
eina_list_count(fd->images) * sizeof(Eina_List *) +
|
||||
eina_list_count(fd->base.references) *
|
||||
eina_list_count(fentry->images) * sizeof(Eina_List *) +
|
||||
eina_list_count(ASENTRY(fentry)->references) *
|
||||
(sizeof(Slave_Request *) + sizeof(Eina_List *));
|
||||
|
||||
#ifdef DEBUG_LOAD_TIME
|
||||
// accounting file entries load time
|
||||
msg->images.files_load_time += fd->base.load_time;
|
||||
msg->images.files_saved_time += fd->base.saved_time;
|
||||
msg->images.files_load_time += ASENTRY(fentry)->load_time;
|
||||
msg->images.files_saved_time += ASENTRY(fentry)->saved_time;
|
||||
#endif
|
||||
|
||||
return EINA_TRUE;
|
||||
|
@ -1776,7 +1909,7 @@ _image_data_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EI
|
|||
{
|
||||
Msg_Stats *msg = fdata;
|
||||
Image_Data *id = data;
|
||||
unsigned int image_size;
|
||||
File_Data *fd;
|
||||
|
||||
// accounting numbers
|
||||
msg->images.images_loaded++;
|
||||
|
@ -1786,9 +1919,13 @@ _image_data_entry_stats_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EI
|
|||
msg->images.images_size += _image_entry_size_get(id) * 1024;
|
||||
if (id->unused) msg->images.unused_size += _image_entry_size_get(id) * 1024;
|
||||
|
||||
image_size = id->file->w * id->file->h * 4;
|
||||
fd = _file_data_find(id->file_id);
|
||||
if (fd)
|
||||
{
|
||||
unsigned int image_size = fd->w * fd->h * 4;
|
||||
msg->images.requested_size +=
|
||||
(image_size * eina_list_count(id->base.references));
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOAD_TIME
|
||||
// accounting image entries load time
|
||||
|
@ -2047,15 +2184,17 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id,
|
|||
Reference *ref;
|
||||
File_Watch *fw;
|
||||
char buf[4906];
|
||||
File_Entry *fentry;
|
||||
int idx;
|
||||
|
||||
// look for this file on client references
|
||||
ref = eina_hash_find(client->files.referencing, &client_file_id);
|
||||
if (ref)
|
||||
{
|
||||
fd = (File_Data *)ref->entry;
|
||||
_entry_load_reused(ref->entry);
|
||||
|
||||
if (fd->invalid)
|
||||
fd = _file_data_find(ref->entry->id);
|
||||
if (!fd || fd->invalid)
|
||||
{
|
||||
cserve2_client_error_send(client, rid, CSERVE2_FILE_CHANGED);
|
||||
return -1;
|
||||
|
@ -2065,8 +2204,8 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id,
|
|||
ref->count++;
|
||||
|
||||
// File already being loaded, just add the request to be replied
|
||||
if (fd->base.request)
|
||||
cserve2_request_waiter_add(fd->base.request, rid, client);
|
||||
if (ref->entry->request)
|
||||
cserve2_request_waiter_add(ref->entry->request, rid, client);
|
||||
else
|
||||
_image_opened_send(client, fd, rid);
|
||||
return 0;
|
||||
|
@ -2079,8 +2218,8 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id,
|
|||
{
|
||||
DBG("found file_id %u for client file id %d",
|
||||
file_id, client_file_id);
|
||||
fd = eina_hash_find(file_entries, &file_id);
|
||||
if (!fd)
|
||||
fentry = _file_entry_find(file_id);
|
||||
if (!fentry)
|
||||
{
|
||||
ERR("file \"%s\" is in file_ids hash but not in entries hash.",
|
||||
buf);
|
||||
|
@ -2088,30 +2227,43 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id,
|
|||
// FIXME: Maybe we should remove the entry from file_ids then?
|
||||
return -1;
|
||||
}
|
||||
ref = _entry_reference_add((Entry *)fd, client, client_file_id);
|
||||
ref = _entry_reference_add(ASENTRY(fentry), client, client_file_id);
|
||||
_entry_load_reused(ref->entry);
|
||||
eina_hash_add(client->files.referencing, &client_file_id, ref);
|
||||
if (fd->base.request)
|
||||
cserve2_request_waiter_add(fd->base.request, rid, client);
|
||||
if (ref->entry->request)
|
||||
cserve2_request_waiter_add(ref->entry->request, rid, client);
|
||||
else // File already loaded, otherwise there would be a request
|
||||
{
|
||||
fd = _file_data_find(file_id);
|
||||
_image_opened_send(client, fd, rid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_id = ++_entry_id;
|
||||
while ((file_id == 0) || (eina_hash_find(file_entries, &file_id)))
|
||||
while (eina_hash_find(file_entries, &file_id))
|
||||
file_id = ++_entry_id;
|
||||
|
||||
DBG("Creating new entry with file_id: %u for file \"%s:%s\"",
|
||||
file_id, path, key);
|
||||
fd = calloc(1, sizeof(*fd));
|
||||
fd->base.type = CSERVE2_IMAGE_FILE;
|
||||
idx = cserve2_shared_array_item_new(_file_data_array);
|
||||
fd = cserve2_shared_array_item_data_get(_file_data_array, idx);
|
||||
DBG("Creating new entry with file_id: %u for file \"%s:%s\". Index %d at %p",
|
||||
file_id, path, key, idx, fd);
|
||||
if (!fd)
|
||||
{
|
||||
ERR("Could not create new file entry!");
|
||||
return -1;
|
||||
}
|
||||
fd->id = file_id; // FIXME: write last (?)
|
||||
fd->refcount = 1;
|
||||
fd->path = cserve2_shared_string_add(path);
|
||||
fd->key = cserve2_shared_string_add(key);
|
||||
fd->base.id = file_id;
|
||||
eina_hash_add(file_entries, &file_id, fd);
|
||||
|
||||
fentry = calloc(1, sizeof(File_Entry));
|
||||
ASENTRY(fentry)->type = CSERVE2_IMAGE_FILE;
|
||||
ASENTRY(fentry)->id = file_id;
|
||||
eina_hash_add(file_entries, &file_id, fentry);
|
||||
eina_hash_add(file_ids, buf, (void*)(intptr_t)file_id);
|
||||
ref = _entry_reference_add((Entry *)fd, client, client_file_id);
|
||||
ref = _entry_reference_add(ASENTRY(fentry), client, client_file_id);
|
||||
eina_hash_add(client->files.referencing, &client_file_id, ref);
|
||||
|
||||
fw = eina_hash_find(file_watch, cserve2_shared_string_get(fd->path));
|
||||
|
@ -2122,14 +2274,12 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id,
|
|||
cserve2_file_change_watch_add(fw->path, _file_changed_cb, fw);
|
||||
eina_hash_direct_add(file_watch, fw->path, fw);
|
||||
}
|
||||
fw->entries = eina_list_append(fw->entries, fd);
|
||||
fd->watcher = fw;
|
||||
fw->entries = eina_list_append(fw->entries, fentry);
|
||||
fentry->watcher = fw;
|
||||
|
||||
fd->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_OPEN,
|
||||
rid, client, NULL, &_open_funcs,
|
||||
fd);
|
||||
|
||||
// _open_image_default_set(fd);
|
||||
ASENTRY(fentry)->request = cserve2_request_add(CSERVE2_REQ_IMAGE_OPEN,
|
||||
rid, client, NULL,
|
||||
&_open_funcs, fentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2163,9 +2313,9 @@ _cserve2_cache_fast_scaling_check(Client *client, Image_Data *entry)
|
|||
int scaled_count = 0;
|
||||
int dst_w, dst_h;
|
||||
Eina_Bool first_attempt = EINA_TRUE;
|
||||
File_Entry *fentry;
|
||||
|
||||
if (!entry) return -1;
|
||||
if (!entry->file) return -1;
|
||||
|
||||
dst_w = entry->opts.scale_load.dst_w;
|
||||
dst_h = entry->opts.scale_load.dst_h;
|
||||
|
@ -2206,7 +2356,9 @@ try_again:
|
|||
goto try_again;
|
||||
}
|
||||
|
||||
iter = eina_list_iterator_new(entry->file->images);
|
||||
fentry = _file_entry_find(entry->file_id);
|
||||
iter = eina_list_iterator_new(fentry->images);
|
||||
//iter = eina_list_iterator_new(entry->file->images);
|
||||
EINA_ITERATOR_FOREACH(iter, i)
|
||||
{
|
||||
if (i == entry) continue;
|
||||
|
@ -2228,16 +2380,13 @@ try_again:
|
|||
|
||||
if (!original)
|
||||
{
|
||||
DBG("Found %d scaled images for %s:%s but none matches",
|
||||
scaled_count, cserve2_shared_string_get(entry->file->path),
|
||||
cserve2_shared_string_get(entry->file->key));
|
||||
DBG("Found %d scaled images for image %u but none matches",
|
||||
scaled_count, entry->base.id);
|
||||
|
||||
if (scaled_count >= 4)
|
||||
{
|
||||
DBG("Forcing load of original image now!");
|
||||
|
||||
File_Data *fd;
|
||||
|
||||
original = _image_entry_new(client, 0, entry->file_id,
|
||||
0, &unscaled);
|
||||
if (!original) return -1;
|
||||
|
@ -2252,8 +2401,8 @@ try_again:
|
|||
eina_hash_add(image_ids, buf, (void *)(intptr_t)image_id);
|
||||
_entry_unused_push(original);
|
||||
|
||||
fd = original->file;
|
||||
fd->images = eina_list_append(fd->images, original);
|
||||
fentry = _file_entry_find(original->file_id);
|
||||
fentry->images = eina_list_append(fentry->images, original);
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
@ -2299,8 +2448,8 @@ cserve2_cache_image_entry_create(Client *client, int rid,
|
|||
Evas_Image_Load_Opts *opts)
|
||||
{
|
||||
Image_Data *entry;
|
||||
File_Data *fd = NULL;
|
||||
Reference *ref, *oldref;
|
||||
File_Entry *fentry;
|
||||
unsigned int image_id;
|
||||
char buf[4096];
|
||||
|
||||
|
@ -2360,8 +2509,8 @@ cserve2_cache_image_entry_create(Client *client, int rid,
|
|||
eina_hash_del_by_key(client->images.referencing, &client_image_id);
|
||||
eina_hash_add(client->images.referencing, &client_image_id, ref);
|
||||
|
||||
fd = entry->file;
|
||||
fd->images = eina_list_append(fd->images, entry);
|
||||
fentry = _file_entry_find(entry->file_id);
|
||||
fentry->images = eina_list_append(fentry->images, entry);
|
||||
|
||||
if (opts && opts->scale_load.dst_w && opts->scale_load.dst_h)
|
||||
{
|
||||
|
@ -2369,8 +2518,8 @@ cserve2_cache_image_entry_create(Client *client, int rid,
|
|||
return 0;
|
||||
}
|
||||
|
||||
entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD,
|
||||
0, NULL, fd->base.request,
|
||||
ASENTRY(entry)->request = cserve2_request_add(CSERVE2_REQ_IMAGE_SPEC_LOAD,
|
||||
0, NULL, ASENTRY(fentry)->request,
|
||||
&_load_funcs, entry);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2380,6 +2529,7 @@ cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned
|
|||
{
|
||||
Image_Data *entry;
|
||||
Reference *ref;
|
||||
File_Data *fd;
|
||||
|
||||
ref = eina_hash_find(client->images.referencing, &client_image_id);
|
||||
if (!ref)
|
||||
|
@ -2389,9 +2539,9 @@ cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned
|
|||
return;
|
||||
}
|
||||
|
||||
entry = (Image_Data *)ref->entry;
|
||||
|
||||
if (entry->file->invalid)
|
||||
entry = (Image_Data *) ref->entry;
|
||||
fd = _file_data_find(entry->file_id);
|
||||
if (!fd || fd->invalid)
|
||||
{
|
||||
cserve2_client_error_send(client, rid, CSERVE2_FILE_CHANGED);
|
||||
return;
|
||||
|
@ -2409,11 +2559,14 @@ cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned
|
|||
else if (entry->shm)
|
||||
_image_loaded_send(client, entry, rid);
|
||||
else
|
||||
entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
|
||||
{
|
||||
File_Entry *fentry = _file_entry_find(entry->file_id);
|
||||
ASENTRY(entry)->request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
|
||||
rid, client,
|
||||
entry->file->base.request,
|
||||
ASENTRY(fentry)->request,
|
||||
&_load_funcs,
|
||||
entry);
|
||||
}
|
||||
|
||||
entry->doload = EINA_TRUE;
|
||||
}
|
||||
|
@ -2423,6 +2576,7 @@ cserve2_cache_image_preload(Client *client, unsigned int client_image_id, unsign
|
|||
{
|
||||
Image_Data *entry;
|
||||
Reference *ref;
|
||||
File_Data *fd;
|
||||
|
||||
ref = eina_hash_find(client->images.referencing, &client_image_id);
|
||||
if (!ref)
|
||||
|
@ -2432,9 +2586,9 @@ cserve2_cache_image_preload(Client *client, unsigned int client_image_id, unsign
|
|||
return;
|
||||
}
|
||||
|
||||
entry = (Image_Data *)ref->entry;
|
||||
|
||||
if (entry->file->invalid)
|
||||
entry = (Image_Data *) ref->entry;
|
||||
fd = _file_data_find(entry->file_id);
|
||||
if (!fd || fd->invalid)
|
||||
{
|
||||
cserve2_client_error_send(client, rid, CSERVE2_FILE_CHANGED);
|
||||
return;
|
||||
|
@ -2452,11 +2606,14 @@ cserve2_cache_image_preload(Client *client, unsigned int client_image_id, unsign
|
|||
else if (entry->shm)
|
||||
_image_loaded_send(client, entry, rid);
|
||||
else
|
||||
entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
|
||||
{
|
||||
File_Entry *fentry = _file_entry_find(entry->file_id);
|
||||
ASENTRY(entry)->request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
|
||||
rid, client,
|
||||
entry->file->base.request,
|
||||
ASENTRY(fentry)->request,
|
||||
&_load_funcs,
|
||||
entry);
|
||||
}
|
||||
|
||||
entry->doload = EINA_TRUE;
|
||||
}
|
||||
|
|
|
@ -462,7 +462,7 @@ cserve2_shared_array_item_find(Shared_Array *sa, void *data,
|
|||
|
||||
// TODO: Fast search in the sorted zone
|
||||
|
||||
ptr = sa->ds->data;
|
||||
ptr = sa->ds->data + sizeof(Shared_Array_Header);
|
||||
|
||||
// Linear search O(n)
|
||||
for (k = 0; k < sa->header->emptyidx; k++)
|
||||
|
@ -482,7 +482,8 @@ cserve2_shared_array_item_data_find(Shared_Array *sa, void *data,
|
|||
int elemid;
|
||||
|
||||
elemid = cserve2_shared_array_item_find(sa, data, cmp);
|
||||
if (elemid < 0) return NULL;
|
||||
if (elemid < 0)
|
||||
return NULL;
|
||||
|
||||
return cserve2_shared_array_item_data_get(sa, elemid);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue