#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 },
};
struct _Client_Request {
- Message_Type type;
- unsigned int rid;
+ Msg_Base *msg;
+ int msg_size;
Op_Callback cb;
void *data;
};
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
}
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;
{
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;
}
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;
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;
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);
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;
{
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);
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;
* 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;
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;
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
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)
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;
if (!ie->data2)
{
ERR("No data2 for preloaded file");
- return;
+ return EINA_TRUE;
}
if (answer->type != CSERVE2_PRELOAD &&
if (dentry->preloaded_cb)
dentry->preloaded_cb(data, EINA_FALSE);
dentry->preloaded_cb = NULL;
- return;
+ return EINA_TRUE;
}
_loaded_handle(ie, msg_received, size);
dentry->preloaded_cb(data, EINA_TRUE);
dentry->preloaded_cb = NULL;
}
+
+ return EINA_TRUE;
}
static int
&& (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
}
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;
Msg_Open msg_open;
File_Entry *fentry;
Data_Entry *dentry;
+ const char *file, *key;
+ Evas_Image_Load_Opts *opts = NULL;
if (cserve2_init == 0)
{
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)
{
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;
_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;
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;
}
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;
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;
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;
free(fe);
}
-static void
+static Eina_Bool
_font_loaded_cb(void *data, const void *msg, int size)
{
const Msg_Base *m = msg;
if ((size < (int) sizeof(*m))
|| (m->type == CSERVE2_ERROR))
fe->failed = EINA_TRUE;
+
+ return EINA_TRUE;
}
static unsigned int
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;
}
{
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))
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)
{
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;
}
return cnt;
}
-static void
+static Eina_Bool
_glyph_request_cb(void *data, const void *msg, int size)
{
const Msg_Font_Glyphs_Loaded *resp = msg;
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;
{
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
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;
}
#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
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);