From e74cac57e412bcd71f2cc58ba46d326aef0996c4 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Wed, 2 Oct 2013 20:23:14 +0900 Subject: [PATCH] evas/cserve2: Reconnect to cserve2 in case of server crash Try to reconnect to cserve2 if the socket connection was lost. Resend some messages if necessary. Images reload seems to be working. Actually, the images don't change over time, so the clients just keep the previous references to their images. FONT RELOAD IS NOT WORKING: - Crashes - Invalid glyph data - Infinite loop in _glyph_map_remap_check() Root cause: When new glyphs are requested from the server, they are added to the mempool. So it is necessary to remap the font. Unfortunately, in case of server reboot, we did not keep the mempool so the old glyphs that were not requested again will not be valid. --- src/bin/evas/evas_cserve2_cache.c | 10 +- src/lib/evas/cache2/evas_cache2.c | 4 +- src/lib/evas/common/evas_font_draw.c | 7 +- src/lib/evas/common/evas_font_main.c | 10 +- src/lib/evas/cserve2/evas_cs2.h | 1 + src/lib/evas/cserve2/evas_cs2_client.c | 454 +++++++++++++++++++++++++------- src/lib/evas/cserve2/evas_cs2_private.h | 1 - 7 files changed, 379 insertions(+), 108 deletions(-) diff --git a/src/bin/evas/evas_cserve2_cache.c b/src/bin/evas/evas_cserve2_cache.c index 8b4e565..5ec597b 100644 --- a/src/bin/evas/evas_cserve2_cache.c +++ b/src/bin/evas/evas_cserve2_cache.c @@ -2769,6 +2769,7 @@ try_again: 0, &unscaled, buf, sizeof(buf)); if (!orig_entry) return -1; + image_id = orig_entry->base.id; orig_data = _image_data_find(ENTRYID(orig_entry)); orig_data->unused = EINA_TRUE; fentry = _file_entry_find(orig_data->file_id); @@ -2914,12 +2915,17 @@ cserve2_cache_image_load(Client *client, unsigned int client_image_id, unsigned { ERR("Can't load: client %d has no image id %d", client->id, client_image_id); + cserve2_client_error_send(client, rid, CSERVE2_NOT_LOADED); return; } ientry = (Image_Entry *) ref->entry; idata = _image_data_find(ENTRYID(ientry)); - if (!idata) return; + if (!idata) + { + cserve2_client_error_send(client, rid, CSERVE2_INVALID_CACHE); + return; + } fd = _file_data_find(idata->file_id); if (!fd || fd->invalid) @@ -3120,6 +3126,7 @@ cserve2_cache_font_glyphs_load(Client *client, const char *source, if (!req) { free(glyphs); + cserve2_client_error_send(client, rid, CSERVE2_NOT_LOADED); return -1; } @@ -3153,6 +3160,7 @@ cserve2_cache_font_glyphs_used(Client *client, const char *source, if (!req) { free(glyphs); + cserve2_client_error_send(client, rid, CSERVE2_NOT_LOADED); return 0; } diff --git a/src/lib/evas/cache2/evas_cache2.c b/src/lib/evas/cache2/evas_cache2.c index a9ed8ca..e1a9d01 100644 --- a/src/lib/evas/cache2/evas_cache2.c +++ b/src/lib/evas/cache2/evas_cache2.c @@ -997,10 +997,10 @@ evas_cache2_image_load_data(Image_Entry *ie) error = evas_cserve2_image_load_data_wait(ie); RGBA_Image *im = (RGBA_Image *)ie; - DBG("try cserve2 image data '%s' '%s' loaded!", - ie->file, ie->key ? ie->key : ""); if ((error == CSERVE2_NONE) && im->image.data) { + DBG("try cserve2 image data '%s' '%s' loaded!", + ie->file, ie->key ? ie->key : ""); error = EVAS_LOAD_ERROR_NONE; } else diff --git a/src/lib/evas/common/evas_font_draw.c b/src/lib/evas/common/evas_font_draw.c index 5b8423d..2b82035 100644 --- a/src/lib/evas/common/evas_font_draw.c +++ b/src/lib/evas/common/evas_font_draw.c @@ -304,7 +304,12 @@ evas_common_font_draw_prepare(Evas_Text_Props *text_props) fg = evas_common_font_int_cache_glyph_get(fi, idx); if (!fg) continue; - if (!fg->glyph_out) evas_common_font_int_cache_glyph_render(fg); + if (!fg->glyph_out) + if (!evas_common_font_int_cache_glyph_render(fg)) + { + fg = NULL; + goto error; + } glyph = eina_inarray_grow(glyphs, 1); if (!glyph) goto error; diff --git a/src/lib/evas/common/evas_font_main.c b/src/lib/evas/common/evas_font_main.c index 32c7e37..769114a 100644 --- a/src/lib/evas/common/evas_font_main.c +++ b/src/lib/evas/common/evas_font_main.c @@ -548,8 +548,14 @@ evas_common_font_int_cache_glyph_render(RGBA_Font_Glyph *fg) fg->glyph_out = evas_cserve2_font_glyph_bitmap_get(fi->cs2_handler, fg->index, fg->fi->hinting); - if (fg->glyph_out) - return EINA_TRUE; + if (!fg->glyph_out) + { + if (!fi->fash) fi->fash = _fash_gl_new(); + if (fi->fash) _fash_gl_add(fi->fash, fg->index, (void *)(-1)); + free(fg); + return EINA_FALSE; + } + return EINA_TRUE; } #endif diff --git a/src/lib/evas/cserve2/evas_cs2.h b/src/lib/evas/cserve2/evas_cs2.h index 7dcd441..35a0a31 100644 --- a/src/lib/evas/cserve2/evas_cs2.h +++ b/src/lib/evas/cserve2/evas_cs2.h @@ -39,6 +39,7 @@ typedef enum { CSERVE2_LOADER_DIED, CSERVE2_LOADER_EXEC_ERR, CSERVE2_INVALID_CACHE, // invalid cserve cache entry + CSERVE2_NOT_LOADED, CSERVE2_FILE_CHANGED, CSERVE2_REQUEST_CANCEL } Error_Type; diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c index cf3e1b7..a1ca4d3 100644 --- a/src/lib/evas/cserve2/evas_cs2_client.c +++ b/src/lib/evas/cserve2/evas_cs2_client.c @@ -21,7 +21,9 @@ #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); +#define SPECIAL_RID_INDEX_LIST ((unsigned int) 0xFFFFFF42) + +typedef Eina_Bool (*Op_Callback)(void *data, const void *msg, int size); static const Evas_Image_Load_Opts empty_lo = { { 0, 0, 0, 0 }, @@ -47,8 +49,8 @@ struct _File_Entry { }; struct _Client_Request { - Message_Type type; - unsigned int rid; + Msg_Base *msg; + int msg_size; Op_Callback cb; void *data; }; @@ -77,6 +79,11 @@ static const Image_Data *_shared_image_entry_image_data_find(Image_Entry *ie); static const Font_Data *_shared_font_entry_data_find(Font_Entry *fe); static Eina_Bool _shared_index_remap_check(Shared_Index *si, int elemsize); +static Eina_Bool _server_dispatch_until(unsigned int rid); +unsigned int _image_load_server_send(Image_Entry *ie); +static unsigned int _image_open_server_send(Image_Entry *ie); +static unsigned int _glyph_request_server_send(Font_Entry *fe, Font_Hint_Flags hints, Eina_Bool used); + #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path) #endif @@ -213,12 +220,12 @@ _server_disconnect(void) } static void -_request_answer_add(Message_Type type, unsigned int rid, Op_Callback cb, void *data) +_request_answer_add(Msg_Base *msg, int size, Op_Callback cb, void *data) { Client_Request *cr = calloc(1, sizeof(*cr)); - cr->type = type; - cr->rid = rid; + cr->msg = msg; + cr->msg_size = size; cr->cb = cb; cr->data = data; @@ -239,7 +246,7 @@ _server_safe_send(int fd, const void *data, int size) { if ((errno == EAGAIN) || (errno == EINTR)) continue; - DBG("send() failed with error [%d] %s", errno, strerror(errno)); + ERR("send() failed with error %d %m", errno); return EINA_FALSE; } sent += ret; @@ -249,18 +256,114 @@ _server_safe_send(int fd, const void *data, int size) } static Eina_Bool -_server_send(const void *buf, int size, Op_Callback cb, void *data) +_request_resend(unsigned int rid) { - const Msg_Base *msg; + Eina_List *l; + Client_Request *cr; + Eina_Bool found = EINA_FALSE; + + EINA_LIST_FOREACH(_requests, l, cr) + { + if (rid) + { + if (cr->msg->rid != rid) + continue; + found = EINA_TRUE; + } + + DBG("Sending request %d again: type %d", cr->msg->rid, cr->msg->type); + + if (!_server_safe_send(socketfd, &cr->msg_size, sizeof(cr->msg_size))) + return EINA_FALSE; + if (!_server_safe_send(socketfd, cr->msg, cr->msg_size)) + return EINA_FALSE; + + if (found) break; + } + + if (rid) + return found; + + return EINA_TRUE; +} + +static void +_shared_index_close(Shared_Index *si) +{ + if (!si) return; + + if (si->f) + { + if (si->data) + eina_file_map_free(si->f, si->data); + eina_file_close(si->f); + } + if (si->entries_by_hkey) + eina_hash_free(si->entries_by_hkey); + si->f = NULL; + si->data = NULL; + memset(si, 0, sizeof(Shared_Index)); +} + +static void +_shared_index_close_all() +{ + DBG("Closing all index files"); + if (_index.strings_entries.f) + { + if (_index.strings_entries.data) + eina_file_map_free(_index.strings_entries.f, _index.strings_entries.data); + eina_file_close(_index.strings_entries.f); + _index.strings_entries.data = NULL; + _index.strings_entries.f = NULL; + } + _shared_index_close(&_index.strings_index); + _shared_index_close(&_index.files); + _shared_index_close(&_index.images); + _shared_index_close(&_index.fonts); + _index.generation_id = 0; +} + +static Eina_Bool +_server_reconnect() +{ + _shared_index_close_all(); + + errno = 0; + _server_disconnect(); + if (!_server_connect()) + goto on_error; + + if (!_server_dispatch_until(SPECIAL_RID_INDEX_LIST)) + goto on_error; + +#warning TODO: Reopen all files, images, fonts... + + DBG("Re-sending %d requests...", eina_list_count(_requests)); + if (!_request_resend(0)) + goto on_error; + + INF("Successfully reconnected to cserve2"); + return EINA_TRUE; + +on_error: + ERR("Unable to reconnect to server: %d %m", errno); + return EINA_FALSE; +} + +static Eina_Bool +_server_send(void *buf, int size, Op_Callback cb, void *data) +{ + Msg_Base *msg; if (!_server_safe_send(socketfd, &size, sizeof(size))) { ERR("Couldn't send message size to server."); - return EINA_FALSE; + goto on_error; } if (!_server_safe_send(socketfd, buf, size)) { ERR("Couldn't send message body to server."); - return EINA_FALSE; + goto on_error; } msg = buf; @@ -271,13 +374,40 @@ _server_send(const void *buf, int size, Op_Callback cb, void *data) case CSERVE2_PRELOAD: case CSERVE2_FONT_LOAD: case CSERVE2_FONT_GLYPHS_LOAD: - _request_answer_add(msg->type, msg->rid, cb, data); - break; + _request_answer_add(msg, size, cb, data); + break; + case CSERVE2_CLOSE: + case CSERVE2_UNLOAD: + case CSERVE2_FONT_UNLOAD: + case CSERVE2_FONT_GLYPHS_USED: + free(msg); + break; default: - break; + ERR("Invalid message type %d", msg->type); + free(msg); + return EINA_FALSE; } return EINA_TRUE; + +on_error: + ERR("Socket error: %d %m", errno); + switch (errno) + { + case EPIPE: + case EBADF: + WRN("Trying to reconnect to server..."); + if (!_server_reconnect()) + { + free(buf); + return EINA_FALSE; + } + return _server_send(buf, size, cb, data); + default: + ERR("Can not recover from this error!"); + free(buf); + return EINA_FALSE; + } } static int sr_size = 0; @@ -290,12 +420,21 @@ _server_read(int *size) int n; void *ret; + if (socketfd < 0) + return NULL; + if (sr_size) goto get_data; n = recv(socketfd, &sr_size, sizeof(sr_size), 0); if (n < 0) return NULL; + if (n == 0) + { + DBG("Socket connection closed by server."); + _server_disconnect(); + return NULL; + } sr_buf = malloc(sr_size); @@ -400,20 +539,27 @@ _server_dispatch(Eina_Bool *failed) case CSERVE2_INDEX_LIST: _server_index_list_set(msg, size); free(msg); - return 0; - default: break; + return SPECIAL_RID_INDEX_LIST; + default: + break; } // Normal client to server requests EINA_LIST_FOREACH_SAFE(_requests, l, l_next, cr) { - if (cr->rid != msg->rid) // dispatch this answer + Eina_Bool remove = EINA_TRUE; + + if (cr->msg->rid != msg->rid) // dispatch this answer continue; - _requests = eina_list_remove_list(_requests, l); if (cr->cb) - cr->cb(cr->data, msg, size); - free(cr); + remove = cr->cb(cr->data, msg, size); + if (remove) + { + _requests = eina_list_remove_list(_requests, l); + free(cr->msg); + free(cr); + } } rid = msg->rid; @@ -439,6 +585,16 @@ _server_dispatch_until(unsigned int rid) { int sel; + if (socketfd == -1) + { + DBG("Reconnecting to server..."); + if (!_server_connect()) + { + ERR("Could not reconnect to cserve2!"); + return EINA_FALSE; + } + } + //DBG("Waiting for request %d...", rid); FD_ZERO(&rfds); FD_SET(socketfd, &rfds); @@ -470,7 +626,7 @@ _server_dispatch_until(unsigned int rid) return EINA_TRUE; } -static void +static Eina_Bool _image_opened_cb(void *data, const void *msg_received, int size) { const Msg_Base *answer = msg_received; @@ -481,15 +637,15 @@ _image_opened_cb(void *data, const void *msg_received, int size) * and so we would have to check that open_rid is equal to answer->rid. * -- jpeg */ - //DBG("Received OPENED for RID: %d [open_rid: %d]", answer->rid, ie->open_rid); + DBG("Received OPENED for RID: %d [open_rid: %d]", answer->rid, ie->open_rid); if (ie->server_id && !ie->open_rid) - return; + return EINA_TRUE; if (answer->rid != ie->open_rid) { WRN("Message rid (%d) differs from expected rid (open_rid: %d)", answer->rid, ie->open_rid); - return; + return EINA_TRUE; } ie->open_rid = 0; @@ -505,14 +661,14 @@ _image_opened_cb(void *data, const void *msg_received, int size) ERR("Invalid message type received: %d (%s)", answer->type, __FUNCTION__); free(ie->data1); ie->data1 = NULL; - return; + return EINA_TRUE; } else if (size < (int) sizeof(*msg)) { ERR("Received message is too small"); free(ie->data1); ie->data1 = NULL; - return; + return EINA_TRUE; } ie->w = msg->image.w; @@ -522,6 +678,8 @@ _image_opened_cb(void *data, const void *msg_received, int size) ie->animated.loop_count = msg->image.loop_count; ie->animated.frame_count = msg->image.frame_count; ie->animated.animated = msg->image.animated; + + return EINA_TRUE; } static void @@ -575,29 +733,29 @@ fail: ie->data2 = NULL; } -static void +static Eina_Bool _image_loaded_cb(void *data, const void *msg_received, int size) { const Msg_Base *answer = msg_received; const Msg_Loaded *msg = msg_received; Image_Entry *ie = data; - //DBG("Received LOADED for RID: %d [load_rid: %d]", answer->rid, ie->load_rid); + DBG("Received LOADED for RID: %d [load_rid: %d]", answer->rid, ie->load_rid); if (!ie->load_rid) - return; + return EINA_TRUE; if (answer->rid != ie->load_rid) { WRN("Message rid (%d) differs from expected rid (load_rid: %d)", answer->rid, ie->load_rid); - return; + return EINA_TRUE; } ie->load_rid = 0; if (!ie->data2) { ERR("No data2 for loaded file"); - return; + return EINA_TRUE; } if (answer->type != CSERVE2_LOADED) @@ -607,18 +765,29 @@ _image_loaded_cb(void *data, const void *msg_received, int size) const Msg_Error *msg_error = msg_received; ERR("Couldn't load image: '%s':'%s'; error: %d", ie->file, ie->key, msg_error->error); + + if (msg_error->error == CSERVE2_NOT_LOADED) + { +#warning Code path to check + DBG("Trying to reopen the image"); + ie->open_rid = _image_open_server_send(ie); + if (_server_dispatch_until(ie->open_rid)) + if (_request_resend(answer->rid)) + return EINA_TRUE; + } } else ERR("Invalid message type received: %d (%s)", answer->type, __FUNCTION__); free(ie->data2); ie->data2 = NULL; - return; + return EINA_TRUE; } _loaded_handle(ie, msg, size); + return EINA_TRUE; } -static void +static Eina_Bool _image_preloaded_cb(void *data, const void *msg_received, int size) { const Msg_Base *answer = msg_received; @@ -633,7 +802,7 @@ _image_preloaded_cb(void *data, const void *msg_received, int size) if (!ie->data2) { ERR("No data2 for preloaded file"); - return; + return EINA_TRUE; } if (answer->type != CSERVE2_PRELOAD && @@ -650,7 +819,7 @@ _image_preloaded_cb(void *data, const void *msg_received, int size) if (dentry->preloaded_cb) dentry->preloaded_cb(data, EINA_FALSE); dentry->preloaded_cb = NULL; - return; + return EINA_TRUE; } _loaded_handle(ie, msg_received, size); @@ -661,6 +830,8 @@ _image_preloaded_cb(void *data, const void *msg_received, int size) dentry->preloaded_cb(data, EINA_TRUE); dentry->preloaded_cb = NULL; } + + return EINA_TRUE; } static int @@ -716,7 +887,11 @@ _evas_image_load_opts_empty(Evas_Image_Load_Opts *lo) && (lo->w == 0) && (lo->h == 0) && (lo->region.x == 0) && (lo->region.y == 0) && (lo->region.w == 0) && (lo->region.h == 0) - && (lo->orientation == 0)); + && (lo->orientation == 0) + && (lo->scale_load.src_x == 0) && (lo->scale_load.src_y == 0) + && (lo->scale_load.src_w == 0) && (lo->scale_load.src_h == 0) + && (lo->scale_load.dst_w == 0) && (lo->scale_load.dst_h == 0) + && (lo->scale_load.scale_hint == 0)); // Skip smooth } static void @@ -747,8 +922,7 @@ _file_hkey_get(char *buf, size_t sz, const char *path, const char *key, } static unsigned int -_image_open_server_send(Image_Entry *ie, const char *file, const char *key, - Evas_Image_Load_Opts *opts) +_image_open_server_send(Image_Entry *ie) { int flen, klen; int size, hkey_len; @@ -758,6 +932,8 @@ _image_open_server_send(Image_Entry *ie, const char *file, const char *key, Msg_Open msg_open; File_Entry *fentry; Data_Entry *dentry; + const char *file, *key; + Evas_Image_Load_Opts *opts = NULL; if (cserve2_init == 0) { @@ -765,9 +941,15 @@ _image_open_server_send(Image_Entry *ie, const char *file, const char *key, return 0; } + if (!_evas_image_load_opts_empty(&ie->load_opts)) + opts = &ie->load_opts; + ie->data1 = NULL; ie->data2 = NULL; + file = ie->file; + key = ie->key; + flen = _build_absolute_path(file, filebuf, sizeof(filebuf)); if (!flen) { @@ -833,16 +1015,13 @@ _image_open_server_send(Image_Entry *ie, const char *file, const char *key, if (!_server_send(buf, size, _image_opened_cb, ie)) { ERR("Couldn't send message to server."); - free(buf); free(dentry); if (!(--fentry->refcount)) eina_hash_del(_file_entries, fentry->hkey, fentry); return 0; } - free(buf); ie->data1 = fentry; - dentry->image_id = msg_open.image_id; ie->data2 = dentry; @@ -853,7 +1032,8 @@ unsigned int _image_load_server_send(Image_Entry *ie) { Data_Entry *dentry; - Msg_Load msg; + Msg_Load *msg; + unsigned int rid; if (cserve2_init == 0) return 0; @@ -871,23 +1051,24 @@ _image_load_server_send(Image_Entry *ie) return 0; } - memset(&msg, 0, sizeof(msg)); - - msg.base.rid = _next_rid(); - msg.base.type = CSERVE2_LOAD; - msg.image_id = dentry->image_id; + msg = calloc(1, sizeof(Msg_Load)); + msg->base.rid = _next_rid(); + msg->base.type = CSERVE2_LOAD; + msg->image_id = dentry->image_id; - if (!_server_send(&msg, sizeof(msg), _image_loaded_cb, ie)) + rid = msg->base.rid; + if (!_server_send(msg, sizeof(Msg_Load), _image_loaded_cb, ie)) return 0; - return msg.base.rid; + return rid; } unsigned int _image_preload_server_send(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_Bool success)) { Data_Entry *dentry; - Msg_Preload msg; + Msg_Preload *msg; + unsigned int rid; if (cserve2_init == 0) return 0; @@ -900,23 +1081,24 @@ _image_preload_server_send(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_ } dentry->preloaded_cb = preloaded_cb; - memset(&msg, 0, sizeof(msg)); - - msg.base.rid = _next_rid(); - msg.base.type = CSERVE2_PRELOAD; - msg.image_id = dentry->image_id; + msg = calloc(1, sizeof(Msg_Preload)); + msg->base.rid = _next_rid(); + msg->base.type = CSERVE2_PRELOAD; + msg->image_id = dentry->image_id; - if (!_server_send(&msg, sizeof(msg), _image_preloaded_cb, ie)) + rid = msg->base.rid; + if (!_server_send(msg, sizeof(Msg_Preload), _image_preloaded_cb, ie)) return 0; - return msg.base.rid; + return rid; } unsigned int _image_close_server_send(Image_Entry *ie) { - Msg_Close msg; + Msg_Close *msg; File_Entry *fentry; + unsigned int rid; if (cserve2_init == 0) return 0; @@ -937,26 +1119,28 @@ _image_close_server_send(Image_Entry *ie) ie->data2 = NULL; } - memset(&msg, 0, sizeof(msg)); - msg.base.rid = _next_rid(); - msg.base.type = CSERVE2_CLOSE; - msg.file_id = fentry->file_id; + msg = calloc(1, sizeof(Msg_Close)); + msg->base.rid = _next_rid(); + msg->base.type = CSERVE2_CLOSE; + msg->file_id = fentry->file_id; if (!(--fentry->refcount)) eina_hash_del(_file_entries, fentry->hkey, fentry); ie->data1 = NULL; - if (!_server_send(&msg, sizeof(msg), NULL, NULL)) + rid = msg->base.rid; + if (!_server_send(msg, sizeof(Msg_Close), NULL, NULL)) return 0; - return msg.base.rid; + return rid; } unsigned int _image_unload_server_send(Image_Entry *ie) { - Msg_Unload msg; + Msg_Unload *msg; Data_Entry *dentry; + unsigned int rid; if (cserve2_init == 0) return 0; @@ -971,37 +1155,30 @@ _image_unload_server_send(Image_Entry *ie) if (dentry->shm.f) eina_file_close(dentry->shm.f); - // if (dentry->shm.path) - // free(dentry->shm.path); - memset(&msg, 0, sizeof(msg)); - msg.base.rid = _next_rid(); - msg.base.type = CSERVE2_UNLOAD; - msg.image_id = dentry->image_id; + msg = calloc(1, sizeof(Msg_Unload)); + msg->base.rid = _next_rid(); + msg->base.type = CSERVE2_UNLOAD; + msg->image_id = dentry->image_id; free(dentry); ie->data2 = NULL; - if (!_server_send(&msg, sizeof(msg), NULL, NULL)) + rid = msg->base.rid; + if (!_server_send(msg, sizeof(Msg_Unload), NULL, NULL)) return 0; - return msg.base.rid; + return rid; } Eina_Bool evas_cserve2_image_load(Image_Entry *ie) { unsigned int rid; - const char *file, *key; - Evas_Image_Load_Opts *opts = NULL; if (!ie) return EINA_FALSE; - file = ie->file; - key = ie->key; - if (!_memory_zero_cmp(&ie->load_opts, sizeof(ie->load_opts))) - opts = &ie->load_opts; - rid = _image_open_server_send(ie, file, key, opts); + rid = _image_open_server_send(ie); if (!rid) return EINA_FALSE; @@ -1282,7 +1459,7 @@ _font_entry_free(Font_Entry *fe) free(fe); } -static void +static Eina_Bool _font_loaded_cb(void *data, const void *msg, int size) { const Msg_Base *m = msg; @@ -1293,6 +1470,8 @@ _font_loaded_cb(void *data, const void *msg, int size) if ((size < (int) sizeof(*m)) || (m->type == CSERVE2_ERROR)) fe->failed = EINA_TRUE; + + return EINA_TRUE; } static unsigned int @@ -1330,10 +1509,9 @@ _font_load_server_send(Font_Entry *fe, Message_Type type) if (type == CSERVE2_FONT_LOAD) cb = _font_loaded_cb; - if (_server_send(msg, size, cb, fe)) - ret = msg->base.rid; - - free(msg); + ret = msg->base.rid; + if (!_server_send(msg, size, cb, fe)) + return 0; return ret; } @@ -1465,6 +1643,23 @@ _glyph_map_remap_check(Glyph_Map *map) { Eina_Bool changed = EINA_FALSE; int oldcount; + const void *oldmap = map->mempool.data; + + if (!map->mempool.f) + { + WRN("The glyph mempool has been closed."); + if (!map->mempool.path) + return EINA_FALSE; + + DBG("Remapping from %s", map->mempool.path); + map->mempool.f = eina_file_open(map->mempool.path, EINA_TRUE); + if (!map->mempool.f) + { + ERR("Could not open shm file: %d %m", errno); + return EINA_FALSE; + } + map->mempool.size = 0; + } if (eina_file_refresh(map->mempool.f) || (eina_file_size_get(map->mempool.f) != (size_t) map->mempool.size)) @@ -1481,6 +1676,7 @@ _glyph_map_remap_check(Glyph_Map *map) changed = EINA_TRUE; // Remap loaded glyphs +#warning Infinite loop again here. FONT RELOAD IS STILL BROKEN. EINA_CLIST_FOR_EACH_ENTRY(gl, &map->fe->map->glyphs, CS_Glyph_Out, map_entry) { @@ -1496,6 +1692,7 @@ _glyph_map_remap_check(Glyph_Map *map) oldcount = map->index.count; _shared_index_remap_check(&map->index, sizeof(Glyph_Data)); changed |= (oldcount != map->index.count); + changed |= (oldmap != map->mempool.data); return changed; } @@ -1571,7 +1768,7 @@ _font_entry_glyph_map_rebuild_check(Font_Entry *fe, Font_Hint_Flags hints) return cnt; } -static void +static Eina_Bool _glyph_request_cb(void *data, const void *msg, int size) { const Msg_Font_Glyphs_Loaded *resp = msg; @@ -1583,11 +1780,56 @@ _glyph_request_cb(void *data, const void *msg, int size) const char *name; int pos; - if (resp->base.type == CSERVE2_ERROR) + if (!fe || !fe->fash[grd->hints]) goto end; - if (!fe->fash[grd->hints]) - goto end; + if (resp->base.type == CSERVE2_ERROR) + { + const Msg_Error *err = msg; + ERR("We got an error message when waiting for glyphs: %d", err->error); + + if (err->error == CSERVE2_NOT_LOADED) + { + DBG("Reloading the font: %s from %s", fe->name, fe->source); + + // This will crash for sure. + /* + for (i = 0; i < 3; i++) + { + if (fe->fash[i]) + fash_gl_free(fe->fash[i]); + fe->fash[i] = NULL; + } + _glyphs_map_free(fe->map); + fe->map = NULL; + */ + + if (!(fe->rid = _font_load_server_send(fe, CSERVE2_FONT_LOAD))) + { + ERR("Failed to send font load message"); + free(data); + return EINA_TRUE; + } + +#warning Code path to check + + if (fe->glyphs_queue_count) + _glyph_request_server_send(fe, grd->hints, EINA_FALSE); + + if (fe->glyphs_used_count) + _glyph_request_server_send(fe, grd->hints, EINA_TRUE); + + DBG("Resending glyph load message now..."); + if (!_request_resend(err->base.rid)) + { + free(data); + return EINA_TRUE; + } + return EINA_FALSE; + } + free(data); + return EINA_TRUE; + } if (size <= (int) sizeof(*resp)) goto end; @@ -1686,15 +1928,23 @@ _glyph_request_cb(void *data, const void *msg, int size) { ERR("Failed to remap glyph mempool!"); gl->base.bitmap.buffer = NULL; + //gl->base.bitmap.rows = 0; + //gl->base.bitmap.width = 0; } } - eina_clist_add_head(&fe->map->glyphs, &gl->map_entry); + if (!eina_clist_element_is_linked(&gl->map_entry)) + eina_clist_add_head(&fe->map->glyphs, &gl->map_entry); } } + free(grd); + return EINA_TRUE; + end: + ERR("An unknown error occured when waiting for glyph data!"); free(grd); + return EINA_TRUE; } static unsigned int @@ -1782,12 +2032,12 @@ _glyph_request_server_send(Font_Entry *fe, Font_Hint_Flags hints, Eina_Bool used else cb = NULL; - if (_server_send(msg, size, cb, grd)) - ret = msg->base.rid; - else - free(grd); - - free(msg); + ret = msg->base.rid; + if (!_server_send(msg, size, cb, grd)) + { + free(grd); + return 0; + } return ret; } @@ -1916,7 +2166,12 @@ evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx, #endif if (out->rid) - _server_dispatch_until(out->rid); + if (!_server_dispatch_until(out->rid)) + { + ERR("failed to load the requested glyphs"); + //fe->failed = EINA_TRUE; + //return NULL; + } // promote shm and font entry in lru or something @@ -2050,10 +2305,7 @@ _server_index_list_set(Msg_Base *data, int size) SHARED_BUFFER_PATH_MAX) != 0) { 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; + _shared_index_close(&_index.strings_index); } eina_strlcpy(_index.strings_entries.path, msg->strings_entries_path, SHARED_BUFFER_PATH_MAX); diff --git a/src/lib/evas/cserve2/evas_cs2_private.h b/src/lib/evas/cserve2/evas_cs2_private.h index c0ed575..39cc829c 100644 --- a/src/lib/evas/cserve2/evas_cs2_private.h +++ b/src/lib/evas/cserve2/evas_cs2_private.h @@ -17,7 +17,6 @@ struct _Data_Entry unsigned int hit_count; void (*preloaded_cb)(void *, Eina_Bool); struct { - const char *path; int mmap_offset; int use_offset; int mmap_size; -- 2.7.4