2012-05-03 14:01:31 -07:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/stat.h>
|
2012-12-07 03:01:41 -08:00
|
|
|
#include <unistd.h>
|
2012-05-03 14:01:31 -07:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
|
|
|
|
#include "evas_cs2.h"
|
|
|
|
#include "evas_cs2_private.h"
|
2012-06-22 13:31:31 -07:00
|
|
|
#include "evas_cs2_utils.h"
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
#ifdef EVAS_CSERVE2
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
#define USE_SHARED_INDEX 1
|
|
|
|
#define SHARED_INDEX_ADD_TO_HASH 1
|
|
|
|
#define HKEY_LOAD_OPTS_STR_LEN 215
|
2013-06-04 03:40:36 -07:00
|
|
|
typedef void (*Op_Callback)(void *data, const void *msg, int size);
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
struct _File_Entry {
|
|
|
|
unsigned int file_id;
|
2013-07-28 23:41:23 -07:00
|
|
|
unsigned int server_file_id;
|
2012-05-03 14:01:31 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _Client_Request {
|
|
|
|
Message_Type type;
|
|
|
|
unsigned int rid;
|
|
|
|
Op_Callback cb;
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _File_Entry File_Entry;
|
|
|
|
typedef struct _Client_Request Client_Request;
|
|
|
|
|
|
|
|
static int cserve2_init = 0;
|
|
|
|
static int socketfd = -1;
|
|
|
|
|
|
|
|
static unsigned int _rid_count = 0;
|
|
|
|
static unsigned int _file_id = 0;
|
|
|
|
static unsigned int _data_id = 0;
|
|
|
|
|
|
|
|
static Eina_List *_requests = NULL;
|
|
|
|
|
2013-07-28 21:08:36 -07:00
|
|
|
// Shared index table
|
|
|
|
static Index_Table _index;
|
2013-07-28 23:41:23 -07:00
|
|
|
static const char *_shared_string_get(int id);
|
2013-07-28 21:08:36 -07:00
|
|
|
static int _server_index_list_set(Msg_Base *data, int size);
|
2013-07-31 04:29:41 -07:00
|
|
|
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);
|
2013-07-28 23:41:23 -07:00
|
|
|
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);
|
2013-08-19 21:09:02 -07:00
|
|
|
static const Font_Data *_shared_font_entry_data_find(Font_Entry *fe);
|
2013-08-25 23:31:52 -07:00
|
|
|
static Eina_Bool _shared_index_remap_check(Shared_Index *si, int elemsize);
|
2013-07-28 21:08:36 -07:00
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
#ifndef UNIX_PATH_MAX
|
2013-03-21 06:22:35 -07:00
|
|
|
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path)
|
2012-05-03 14:01:31 -07:00
|
|
|
#endif
|
|
|
|
|
2013-06-26 01:47:41 -07:00
|
|
|
static inline Eina_Bool
|
|
|
|
_memory_zero_cmp(void *data, size_t len)
|
|
|
|
{
|
|
|
|
const int *idata = data;
|
|
|
|
const char *cdata;
|
|
|
|
int remain;
|
|
|
|
|
|
|
|
if (!data || !len) return EINA_TRUE;
|
|
|
|
|
|
|
|
for (remain = len / sizeof(idata); remain > 0; --remain)
|
|
|
|
if (*idata++ != 0) return EINA_FALSE;
|
|
|
|
|
|
|
|
cdata = (const char*) idata;
|
|
|
|
for (remain = ((const char*) data + len) - cdata; remain > 0; --remain)
|
|
|
|
if (*cdata++ != 0) return EINA_FALSE;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
static void
|
|
|
|
_socket_path_set(char *path)
|
|
|
|
{
|
|
|
|
char *env;
|
|
|
|
char buf[UNIX_PATH_MAX];
|
|
|
|
|
|
|
|
env = getenv("EVAS_CSERVE2_SOCKET");
|
|
|
|
if (env && env[0])
|
|
|
|
{
|
2013-01-28 11:12:50 -08:00
|
|
|
eina_strlcpy(path, env, UNIX_PATH_MAX);
|
2012-05-03 14:01:31 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-21 01:44:55 -07:00
|
|
|
snprintf(buf, sizeof(buf), "/tmp/.evas-cserve2-%x.socket", (int)getuid());
|
|
|
|
/* FIXME: check we can actually create this socket */
|
|
|
|
strcpy(path, buf);
|
|
|
|
#if 0
|
2012-05-03 14:01:31 -07:00
|
|
|
env = getenv("XDG_RUNTIME_DIR");
|
|
|
|
if (!env || !env[0])
|
|
|
|
{
|
|
|
|
env = getenv("HOME");
|
|
|
|
if (!env || !env[0])
|
|
|
|
{
|
|
|
|
env = getenv("TMPDIR");
|
|
|
|
if (!env || !env[0])
|
|
|
|
env = "/tmp";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/evas-cserve2-%x.socket", env, getuid());
|
|
|
|
/* FIXME: check we can actually create this socket */
|
|
|
|
strcpy(path, buf);
|
2012-05-21 01:44:55 -07:00
|
|
|
#endif
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_server_connect(void)
|
|
|
|
{
|
|
|
|
int s, len;
|
|
|
|
struct sockaddr_un remote;
|
2013-03-10 07:09:45 -07:00
|
|
|
#ifdef HAVE_FCNTL
|
2012-12-07 03:01:41 -08:00
|
|
|
int flags;
|
|
|
|
#endif
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
ERR("cserve2 socket creation failed with error [%d] %s", errno, strerror(errno));
|
2012-05-03 14:01:31 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-03-10 07:09:45 -07:00
|
|
|
#ifdef HAVE_FCNTL
|
2012-12-07 03:01:41 -08:00
|
|
|
flags = fcntl(s, F_GETFD);
|
|
|
|
flags |= FD_CLOEXEC;
|
|
|
|
fcntl(s, F_SETFD, flags);
|
|
|
|
#endif
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
remote.sun_family = AF_UNIX;
|
|
|
|
_socket_path_set(remote.sun_path);
|
|
|
|
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
|
2013-02-13 03:35:46 -08:00
|
|
|
for (;;)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
2013-06-18 04:50:17 -07:00
|
|
|
errno = 0;
|
2013-02-13 03:35:46 -08:00
|
|
|
if (connect(s, (struct sockaddr *)&remote, len) != -1) break;
|
2013-06-18 04:50:17 -07:00
|
|
|
if (errno == EACCES)
|
|
|
|
{
|
|
|
|
ERR("not authorized to connect to cserve2!");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
ERR("cserve2 connect failed: [%d] %s. Retrying...", errno, strerror(errno));
|
|
|
|
|
2013-06-18 04:50:17 -07:00
|
|
|
errno = 0;
|
|
|
|
usleep(10000);
|
|
|
|
if (errno == EINTR)
|
|
|
|
{
|
|
|
|
WRN("received interruption while trying to connect to cserve2!");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
|
|
|
|
/* FIXME: Here we should identify the error, maybe signal the daemon manager
|
|
|
|
* that we need cserve2 to [re]start or just quit and return false.
|
|
|
|
* There probably should be a timeout of some sort also...
|
|
|
|
* -- jpeg
|
|
|
|
*/
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
2013-08-05 02:13:57 -07:00
|
|
|
#ifdef HAVE_FCNTL
|
2012-05-03 14:01:31 -07:00
|
|
|
fcntl(s, F_SETFL, O_NONBLOCK);
|
2013-08-05 02:13:57 -07:00
|
|
|
#endif
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
socketfd = s;
|
|
|
|
|
|
|
|
DBG("connected to cserve2 server.");
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_server_disconnect(void)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (socketfd != -1)
|
|
|
|
close(socketfd);
|
2012-05-03 14:01:31 -07:00
|
|
|
socketfd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_request_answer_add(Message_Type type, unsigned int rid, Op_Callback cb, void *data)
|
|
|
|
{
|
|
|
|
Client_Request *cr = calloc(1, sizeof(*cr));
|
|
|
|
|
|
|
|
cr->type = type;
|
|
|
|
cr->rid = rid;
|
|
|
|
cr->cb = cb;
|
|
|
|
cr->data = data;
|
|
|
|
|
|
|
|
_requests = eina_list_append(_requests, cr);
|
|
|
|
}
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_server_safe_send(int fd, const void *data, int size)
|
|
|
|
{
|
|
|
|
int sent = 0;
|
|
|
|
ssize_t ret;
|
|
|
|
const char *msg = data;
|
|
|
|
|
|
|
|
while (sent < size)
|
|
|
|
{
|
|
|
|
ret = send(fd, msg + sent, size - sent, MSG_NOSIGNAL);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
if ((errno == EAGAIN) || (errno == EINTR))
|
|
|
|
continue;
|
2013-06-04 03:40:36 -07:00
|
|
|
DBG("send() failed with error [%d] %s", errno, strerror(errno));
|
2012-06-22 13:31:31 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
sent += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_server_send(const void *buf, int size, Op_Callback cb, void *data)
|
|
|
|
{
|
|
|
|
const Msg_Base *msg;
|
2012-06-22 14:54:26 -07:00
|
|
|
if (!_server_safe_send(socketfd, &size, sizeof(size)))
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't send message size to server.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2012-06-22 14:54:26 -07:00
|
|
|
if (!_server_safe_send(socketfd, buf, size))
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
ERR("Couldn't send message body to server.");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg = buf;
|
|
|
|
switch (msg->type)
|
|
|
|
{
|
|
|
|
case CSERVE2_OPEN:
|
|
|
|
case CSERVE2_LOAD:
|
|
|
|
case CSERVE2_PRELOAD:
|
2012-06-22 13:31:31 -07:00
|
|
|
case CSERVE2_FONT_LOAD:
|
|
|
|
case CSERVE2_FONT_GLYPHS_LOAD:
|
2012-05-03 14:01:31 -07:00
|
|
|
_request_answer_add(msg->type, msg->rid, cb, data);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sr_size = 0;
|
|
|
|
static int sr_got = 0;
|
|
|
|
static char *sr_buf = NULL;
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_server_read(int *size)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
if (sr_size)
|
|
|
|
goto get_data;
|
|
|
|
|
|
|
|
n = recv(socketfd, &sr_size, sizeof(sr_size), 0);
|
|
|
|
if (n < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sr_buf = malloc(sr_size);
|
|
|
|
|
|
|
|
get_data:
|
|
|
|
n = recv(socketfd, sr_buf + sr_got, sr_size - sr_got, 0);
|
|
|
|
if (n < 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sr_got += n;
|
|
|
|
if (sr_got < sr_size)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*size = sr_size;
|
|
|
|
sr_size = 0;
|
|
|
|
sr_got = 0;
|
|
|
|
ret = sr_buf;
|
|
|
|
sr_buf = NULL;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
evas_cserve2_init(void)
|
|
|
|
{
|
|
|
|
if (cserve2_init++)
|
|
|
|
return cserve2_init;
|
|
|
|
|
2013-07-28 21:08:36 -07:00
|
|
|
memset(&_index, 0, sizeof(_index));
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
DBG("Connecting to cserve2.");
|
|
|
|
if (!_server_connect())
|
|
|
|
{
|
|
|
|
cserve2_init = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cserve2_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
evas_cserve2_shutdown(void)
|
|
|
|
{
|
2013-07-28 21:08:36 -07:00
|
|
|
const char zeros[sizeof(Msg_Index_List)] = {0};
|
2013-08-01 02:39:38 -07:00
|
|
|
Msg_Index_List *empty = (Msg_Index_List *) zeros;
|
2013-07-28 21:08:36 -07:00
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
if ((--cserve2_init) > 0)
|
|
|
|
return cserve2_init;
|
|
|
|
|
|
|
|
DBG("Disconnecting from cserve2.");
|
2013-08-01 02:39:38 -07:00
|
|
|
empty->base.type = CSERVE2_INDEX_LIST;
|
|
|
|
_server_index_list_set((Msg_Base *) empty, sizeof(Msg_Index_List));
|
2012-05-03 14:01:31 -07:00
|
|
|
_server_disconnect();
|
|
|
|
|
|
|
|
return cserve2_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
evas_cserve2_use_get(void)
|
|
|
|
{
|
|
|
|
return cserve2_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
_next_rid(void)
|
|
|
|
{
|
|
|
|
if (!_rid_count)
|
|
|
|
_rid_count++;
|
|
|
|
|
|
|
|
return _rid_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
2013-06-04 03:40:36 -07:00
|
|
|
_server_dispatch(Eina_Bool *failed)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
int size;
|
|
|
|
unsigned int rid;
|
|
|
|
Eina_List *l, *l_next;
|
|
|
|
Client_Request *cr;
|
|
|
|
Msg_Base *msg;
|
|
|
|
|
|
|
|
msg = _server_read(&size);
|
|
|
|
if (!msg)
|
2013-06-04 03:40:36 -07:00
|
|
|
{
|
|
|
|
*failed = EINA_TRUE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*failed = EINA_FALSE;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2013-07-28 21:08:36 -07:00
|
|
|
// Special messages (no request)
|
|
|
|
switch (msg->type)
|
|
|
|
{
|
|
|
|
case CSERVE2_INDEX_LIST:
|
|
|
|
_server_index_list_set(msg, size);
|
|
|
|
free(msg);
|
|
|
|
return 0;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Normal client to server requests
|
2012-05-03 14:01:31 -07:00
|
|
|
EINA_LIST_FOREACH_SAFE(_requests, l, l_next, cr)
|
|
|
|
{
|
|
|
|
if (cr->rid != msg->rid) // dispatch this answer
|
|
|
|
continue;
|
|
|
|
|
|
|
|
_requests = eina_list_remove_list(_requests, l);
|
|
|
|
if (cr->cb)
|
2013-06-04 03:40:36 -07:00
|
|
|
cr->cb(cr->data, msg, size);
|
2012-05-03 14:01:31 -07:00
|
|
|
free(cr);
|
|
|
|
}
|
|
|
|
|
|
|
|
rid = msg->rid;
|
|
|
|
free(msg);
|
|
|
|
|
|
|
|
return rid;
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
static Eina_Bool
|
2012-05-03 14:01:31 -07:00
|
|
|
_server_dispatch_until(unsigned int rid)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
Eina_Bool failed;
|
|
|
|
fd_set rfds;
|
|
|
|
unsigned int rrid;
|
|
|
|
struct timeval tv;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
while (1)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
rrid = _server_dispatch(&failed);
|
|
|
|
if (rrid == rid) break;
|
|
|
|
else if (failed)
|
|
|
|
{
|
|
|
|
int sel;
|
|
|
|
|
|
|
|
//DBG("Waiting for request %d...", rid);
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_SET(socketfd, &rfds);
|
|
|
|
tv.tv_sec = 1;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
sel = select(socketfd + 1, &rfds, NULL, NULL, &tv);
|
|
|
|
if (sel == -1)
|
|
|
|
{
|
|
|
|
ERR("select() failed: [%d] %s", errno, strerror(errno));
|
|
|
|
/* FIXME: Depending on the error, we should probably try to reconnect to the server.
|
|
|
|
* Or even ask to [re]start the daemon.
|
|
|
|
* Or maybe just return EINA_FALSE after some timeout?
|
|
|
|
* -- jpeg
|
|
|
|
*/
|
2013-06-19 22:11:32 -07:00
|
|
|
if (errno == EINTR)
|
|
|
|
{
|
|
|
|
DBG("giving up on request %d after interrupt", rid);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
}
|
2013-06-30 18:55:46 -07:00
|
|
|
else if (!sel)
|
|
|
|
{
|
|
|
|
WRN("select() timed out. giving up on request %d", rid);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
return EINA_TRUE;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_image_opened_cb(void *data, const void *msg_received, int size)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
const Msg_Base *answer = msg_received;
|
|
|
|
const Msg_Opened *msg = msg_received;
|
|
|
|
Image_Entry *ie = data;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
/* FIXME: Maybe we could have more asynchronous loading in the server side
|
|
|
|
* 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);
|
2013-08-22 23:10:03 -07:00
|
|
|
|
|
|
|
if (ie->server_id && !ie->open_rid)
|
|
|
|
return;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->rid != ie->open_rid)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
|
|
|
WRN("Message rid (%d) differs from expected rid (open_rid: %d)", answer->rid, ie->open_rid);
|
|
|
|
return;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
ie->open_rid = 0;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->type != CSERVE2_OPENED)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->type == CSERVE2_ERROR)
|
|
|
|
{
|
|
|
|
const Msg_Error *msg_error = msg_received;
|
|
|
|
ERR("Couldn't open image: '%s':'%s'; error: %d",
|
|
|
|
ie->file, ie->key, msg_error->error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ERR("Invalid message type received: %d (%s)", answer->type, __FUNCTION__);
|
|
|
|
free(ie->data1);
|
|
|
|
ie->data1 = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (size < (int) sizeof(*msg))
|
|
|
|
{
|
|
|
|
ERR("Received message is too small");
|
2012-05-03 14:01:31 -07:00
|
|
|
free(ie->data1);
|
|
|
|
ie->data1 = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ie->w = msg->image.w;
|
|
|
|
ie->h = msg->image.h;
|
|
|
|
ie->flags.alpha = msg->image.alpha;
|
2013-04-24 23:05:18 -07:00
|
|
|
ie->animated.loop_hint = msg->image.loop_hint;
|
|
|
|
ie->animated.loop_count = msg->image.loop_count;
|
|
|
|
ie->animated.frame_count = msg->image.frame_count;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_loaded_handle(Image_Entry *ie, const Msg_Loaded *msg, int size)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
Data_Entry *dentry = ie->data2;
|
2013-06-04 03:40:36 -07:00
|
|
|
RGBA_Image *im = (RGBA_Image *)ie;
|
2012-05-03 14:01:31 -07:00
|
|
|
const char *shmpath;
|
|
|
|
|
|
|
|
shmpath = ((const char *)msg) + sizeof(*msg);
|
2013-06-04 03:40:36 -07:00
|
|
|
if ((size < (int) sizeof(*msg) + 1)
|
|
|
|
|| (strnlen(shmpath, size - sizeof(*msg)) >= (size - sizeof(*msg))))
|
2013-07-01 22:29:47 -07:00
|
|
|
{
|
|
|
|
DBG("invalid message size");
|
|
|
|
goto fail;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
// dentry->shm.path = strdup(shmpath);
|
|
|
|
dentry->shm.mmap_offset = msg->shm.mmap_offset;
|
|
|
|
dentry->shm.use_offset = msg->shm.use_offset;
|
|
|
|
dentry->shm.mmap_size = msg->shm.mmap_size;
|
|
|
|
dentry->shm.image_size = msg->shm.image_size;
|
|
|
|
|
2012-05-11 13:12:56 -07:00
|
|
|
dentry->shm.f = eina_file_open(shmpath, EINA_TRUE);
|
|
|
|
if (!dentry->shm.f)
|
2013-07-01 22:29:47 -07:00
|
|
|
{
|
|
|
|
DBG("could not open the shm file: %d %m", errno);
|
|
|
|
goto fail;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2012-05-11 13:12:56 -07:00
|
|
|
dentry->shm.data = eina_file_map_new(dentry->shm.f, EINA_FILE_WILLNEED,
|
|
|
|
dentry->shm.mmap_offset,
|
|
|
|
dentry->shm.mmap_size);
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2012-05-11 13:12:56 -07:00
|
|
|
if (!dentry->shm.data)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
2013-07-01 22:29:47 -07:00
|
|
|
DBG("could not mmap the shm file: %d %m", errno);
|
2012-05-11 13:12:56 -07:00
|
|
|
eina_file_close(dentry->shm.f);
|
2013-06-04 03:40:36 -07:00
|
|
|
goto fail;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
im->image.data = evas_cserve2_image_data_get(ie);
|
|
|
|
ie->flags.alpha_sparse = msg->alpha_sparse;
|
|
|
|
ie->flags.loaded = EINA_TRUE;
|
|
|
|
im->image.no_free = 1;
|
|
|
|
return;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
ERR("Failed in %s", __FUNCTION__);
|
|
|
|
free(ie->data2);
|
|
|
|
ie->data2 = NULL;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
2012-07-17 07:23:09 -07:00
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_image_loaded_cb(void *data, const void *msg_received, int size)
|
2012-07-17 07:23:09 -07:00
|
|
|
{
|
|
|
|
const Msg_Base *answer = msg_received;
|
|
|
|
const Msg_Loaded *msg = msg_received;
|
|
|
|
Image_Entry *ie = data;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
//DBG("Received LOADED for RID: %d [load_rid: %d]", answer->rid, ie->load_rid);
|
2013-08-22 23:10:03 -07:00
|
|
|
|
|
|
|
if (!ie->load_rid)
|
|
|
|
return;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->rid != ie->load_rid)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
|
|
|
WRN("Message rid (%d) differs from expected rid (load_rid: %d)", answer->rid, ie->load_rid);
|
|
|
|
return;
|
|
|
|
}
|
2012-07-17 07:23:09 -07:00
|
|
|
ie->load_rid = 0;
|
|
|
|
|
|
|
|
if (!ie->data2)
|
2013-06-04 03:40:36 -07:00
|
|
|
{
|
|
|
|
ERR("No data2 for loaded file");
|
|
|
|
return;
|
|
|
|
}
|
2012-07-17 07:23:09 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->type != CSERVE2_LOADED)
|
2012-07-17 07:23:09 -07:00
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->type == CSERVE2_ERROR)
|
|
|
|
{
|
|
|
|
const Msg_Error *msg_error = msg_received;
|
|
|
|
ERR("Couldn't load image: '%s':'%s'; error: %d",
|
|
|
|
ie->file, ie->key, msg_error->error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ERR("Invalid message type received: %d (%s)", answer->type, __FUNCTION__);
|
2012-07-17 07:23:09 -07:00
|
|
|
free(ie->data2);
|
|
|
|
ie->data2 = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
_loaded_handle(ie, msg, size);
|
2012-07-17 07:23:09 -07:00
|
|
|
}
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_image_preloaded_cb(void *data, const void *msg_received, int size)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
const Msg_Base *answer = msg_received;
|
|
|
|
Image_Entry *ie = data;
|
|
|
|
Data_Entry *dentry = ie->data2;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
//DBG("Received PRELOADED for RID: %d [preload_rid: %d]", answer->rid, ie->preload_rid);
|
|
|
|
if (answer->rid != ie->preload_rid)
|
|
|
|
WRN("Message rid (%d) differs from expected rid (preload_rid: %d)", answer->rid, ie->preload_rid);
|
2012-05-03 14:01:31 -07:00
|
|
|
ie->preload_rid = 0;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie->data2)
|
|
|
|
{
|
|
|
|
ERR("No data2 for preloaded file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (answer->type != CSERVE2_PRELOAD &&
|
|
|
|
answer->type != CSERVE2_LOADED)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (answer->type == CSERVE2_ERROR)
|
|
|
|
{
|
|
|
|
const Msg_Error *msg_error = msg_received;
|
|
|
|
ERR("Couldn't preload image: '%s':'%s'; error: %d",
|
|
|
|
ie->file, ie->key, msg_error->error);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ERR("Invalid message type received: %d (%s)", answer->type, __FUNCTION__);
|
|
|
|
if (dentry->preloaded_cb)
|
|
|
|
dentry->preloaded_cb(data, EINA_FALSE);
|
2012-05-03 14:01:31 -07:00
|
|
|
dentry->preloaded_cb = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
_loaded_handle(ie, msg_received, size);
|
2012-07-17 07:23:09 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
dentry = ie->data2;
|
2012-05-03 14:01:31 -07:00
|
|
|
if (dentry && (dentry->preloaded_cb))
|
|
|
|
{
|
|
|
|
dentry->preloaded_cb(data, EINA_TRUE);
|
|
|
|
dentry->preloaded_cb = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
static int
|
2012-05-03 14:01:31 -07:00
|
|
|
_build_absolute_path(const char *path, char buf[], int size)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!path)
|
2013-06-04 03:40:36 -07:00
|
|
|
return 0;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
p = buf;
|
|
|
|
|
|
|
|
if (path[0] == '/')
|
2013-06-04 03:40:36 -07:00
|
|
|
len = eina_strlcpy(p, path, size);
|
2012-05-03 14:01:31 -07:00
|
|
|
else if (path[0] == '~')
|
|
|
|
{
|
|
|
|
const char *home = getenv("HOME");
|
|
|
|
if (!home)
|
2013-06-04 03:40:36 -07:00
|
|
|
return 0;
|
|
|
|
len = eina_strlcpy(p, home, size);
|
2012-05-03 14:01:31 -07:00
|
|
|
size -= len + 1;
|
|
|
|
p += len;
|
|
|
|
p[0] = '/';
|
|
|
|
p++;
|
2013-06-04 03:40:36 -07:00
|
|
|
len++;
|
|
|
|
len += eina_strlcpy(p, path + 2, size);
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!getcwd(p, size))
|
2013-06-04 03:40:36 -07:00
|
|
|
return 0;
|
2012-05-03 14:01:31 -07:00
|
|
|
len = strlen(p);
|
|
|
|
size -= len + 1;
|
|
|
|
p += len;
|
|
|
|
p[0] = '/';
|
|
|
|
p++;
|
2013-06-04 03:40:36 -07:00
|
|
|
len++;
|
|
|
|
len += eina_strlcpy(p, path, size);
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
return len;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
2013-07-02 23:49:59 -07:00
|
|
|
_image_open_server_send(Image_Entry *ie, const char *file, const char *key,
|
|
|
|
Evas_Image_Load_Opts *opts)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
int flen, klen;
|
|
|
|
int size;
|
|
|
|
char *buf;
|
|
|
|
char filebuf[PATH_MAX];
|
|
|
|
Msg_Open msg_open;
|
|
|
|
File_Entry *fentry;
|
2013-06-26 01:47:41 -07:00
|
|
|
Data_Entry *dentry;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
if (cserve2_init == 0)
|
|
|
|
{
|
|
|
|
ERR("Server not initialized.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-26 01:47:41 -07:00
|
|
|
ie->data1 = NULL;
|
|
|
|
ie->data2 = NULL;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
flen = _build_absolute_path(file, filebuf, sizeof(filebuf));
|
|
|
|
if (!flen)
|
|
|
|
{
|
|
|
|
ERR("Could not find absolute path for %s", file);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
flen++;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!key) key = "";
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
fentry = calloc(1, sizeof(*fentry));
|
2013-06-26 01:47:41 -07:00
|
|
|
if (!fentry)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
dentry = calloc(1, sizeof(*dentry));
|
|
|
|
if (!dentry)
|
|
|
|
{
|
|
|
|
free(fentry);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
memset(&msg_open, 0, sizeof(msg_open));
|
|
|
|
|
|
|
|
fentry->file_id = ++_file_id;
|
|
|
|
klen = strlen(key) + 1;
|
|
|
|
|
|
|
|
msg_open.base.rid = _next_rid();
|
|
|
|
msg_open.base.type = CSERVE2_OPEN;
|
|
|
|
msg_open.file_id = fentry->file_id;
|
|
|
|
msg_open.path_offset = 0;
|
|
|
|
msg_open.key_offset = flen;
|
2013-07-02 23:49:59 -07:00
|
|
|
msg_open.has_load_opts = (opts != NULL);
|
2013-06-26 01:47:41 -07:00
|
|
|
msg_open.image_id = ++_data_id;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
size = sizeof(msg_open) + flen + klen;
|
2013-07-02 23:49:59 -07:00
|
|
|
if (opts)
|
|
|
|
size += sizeof(*opts);
|
2012-05-03 14:01:31 -07:00
|
|
|
buf = malloc(size);
|
2013-06-26 01:47:41 -07:00
|
|
|
if (!buf)
|
|
|
|
{
|
|
|
|
free(fentry);
|
|
|
|
free(dentry);
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
memcpy(buf, &msg_open, sizeof(msg_open));
|
|
|
|
memcpy(buf + sizeof(msg_open), filebuf, flen);
|
|
|
|
memcpy(buf + sizeof(msg_open) + flen, key, klen);
|
2013-07-02 23:49:59 -07:00
|
|
|
if (opts)
|
|
|
|
memcpy(buf + sizeof(msg_open) + flen + klen, opts, sizeof(*opts));
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
if (!_server_send(buf, size, _image_opened_cb, ie))
|
|
|
|
{
|
|
|
|
ERR("Couldn't send message to server.");
|
|
|
|
free(buf);
|
2013-06-25 19:23:35 -07:00
|
|
|
free(fentry);
|
2013-06-26 01:47:41 -07:00
|
|
|
free(dentry);
|
2012-05-03 14:01:31 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
ie->data1 = fentry;
|
|
|
|
|
2013-06-26 01:47:41 -07:00
|
|
|
dentry->image_id = msg_open.image_id;
|
|
|
|
ie->data2 = dentry;
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
return msg_open.base.rid;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
_image_load_server_send(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
Data_Entry *dentry;
|
|
|
|
Msg_Load msg;
|
|
|
|
|
|
|
|
if (cserve2_init == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!ie->data1)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
ERR("No data1 for opened file.");
|
2012-05-03 14:01:31 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dentry = ie->data2;
|
2013-02-13 19:26:21 -08:00
|
|
|
if (!dentry)
|
|
|
|
{
|
|
|
|
ERR("No data2 for opened file.");
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
|
|
|
|
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))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return msg.base.rid;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
_image_preload_server_send(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_Bool success))
|
|
|
|
{
|
|
|
|
Data_Entry *dentry;
|
|
|
|
Msg_Preload msg;
|
|
|
|
|
|
|
|
if (cserve2_init == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
dentry = ie->data2;
|
2013-02-13 19:26:21 -08:00
|
|
|
if (!dentry)
|
|
|
|
{
|
|
|
|
ERR("No data2 for opened file.");
|
|
|
|
return 0;
|
|
|
|
}
|
2012-05-03 14:01:31 -07:00
|
|
|
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;
|
|
|
|
|
|
|
|
if (!_server_send(&msg, sizeof(msg), _image_preloaded_cb, ie))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return msg.base.rid;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
_image_close_server_send(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
Msg_Close msg;
|
|
|
|
File_Entry *fentry;
|
|
|
|
|
|
|
|
if (cserve2_init == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!ie->data1)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fentry = ie->data1;
|
|
|
|
|
|
|
|
if (ie->data2)
|
|
|
|
{
|
2012-05-11 13:12:56 -07:00
|
|
|
Data_Entry *dentry = ie->data2;
|
|
|
|
if (dentry->shm.data)
|
|
|
|
eina_file_map_free(dentry->shm.f, dentry->shm.data);
|
|
|
|
if (dentry->shm.f)
|
|
|
|
eina_file_close(dentry->shm.f);
|
2012-05-03 14:01:31 -07:00
|
|
|
free(ie->data2);
|
|
|
|
ie->data2 = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
|
msg.base.rid = _next_rid();
|
|
|
|
msg.base.type = CSERVE2_CLOSE;
|
|
|
|
msg.file_id = fentry->file_id;
|
|
|
|
|
|
|
|
free(fentry);
|
|
|
|
ie->data1 = NULL;
|
|
|
|
|
|
|
|
if (!_server_send(&msg, sizeof(msg), NULL, NULL))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return msg.base.rid;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int
|
|
|
|
_image_unload_server_send(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
Msg_Unload msg;
|
|
|
|
Data_Entry *dentry;
|
|
|
|
|
|
|
|
if (cserve2_init == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!ie->data2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
dentry = ie->data2;
|
|
|
|
|
2012-05-11 13:12:56 -07:00
|
|
|
if (dentry->shm.data)
|
|
|
|
eina_file_map_free(dentry->shm.f, dentry->shm.data);
|
|
|
|
if (dentry->shm.f)
|
|
|
|
eina_file_close(dentry->shm.f);
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
// 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;
|
|
|
|
|
|
|
|
free(dentry);
|
|
|
|
ie->data2 = NULL;
|
|
|
|
|
|
|
|
if (!_server_send(&msg, sizeof(msg), NULL, NULL))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return msg.base.rid;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
2013-07-02 23:49:59 -07:00
|
|
|
evas_cserve2_image_load(Image_Entry *ie)
|
2012-05-03 14:01:31 -07:00
|
|
|
{
|
|
|
|
unsigned int rid;
|
2013-07-02 23:49:59 -07:00
|
|
|
const char *file, *key;
|
|
|
|
Evas_Image_Load_Opts *opts = NULL;
|
2012-05-03 14:01:31 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2013-07-02 23:49:59 -07:00
|
|
|
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);
|
2012-05-03 14:01:31 -07:00
|
|
|
if (!rid)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
ie->open_rid = rid;
|
|
|
|
|
|
|
|
if (ie->data1)
|
|
|
|
return EINA_TRUE;
|
|
|
|
else
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
evas_cserve2_image_load_wait(Image_Entry *ie)
|
|
|
|
{
|
2013-07-28 23:41:23 -07:00
|
|
|
const File_Data *fd;
|
2013-07-31 04:29:41 -07:00
|
|
|
Eina_Bool failed;
|
|
|
|
unsigned int rrid, rid;
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie)
|
|
|
|
return CSERVE2_GENERIC;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
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
|
2013-07-28 23:41:23 -07:00
|
|
|
fd = _shared_image_entry_file_data_find(ie);
|
2013-08-22 23:10:03 -07:00
|
|
|
if (fd && fd->valid)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
|
|
|
INF("Bypassing socket wait (open_rid %d)", ie->open_rid);
|
|
|
|
ie->w = fd->w;
|
|
|
|
ie->h = fd->h;
|
|
|
|
ie->flags.alpha = fd->alpha;
|
|
|
|
ie->animated.loop_hint = fd->loop_hint;
|
|
|
|
ie->animated.loop_count = fd->loop_count;
|
|
|
|
ie->animated.frame_count = fd->frame_count;
|
2013-08-22 23:10:03 -07:00
|
|
|
ie->server_id = fd->id;
|
2013-07-28 23:41:23 -07:00
|
|
|
ie->open_rid = 0;
|
|
|
|
return CSERVE2_NONE;
|
|
|
|
}
|
2013-07-31 04:29:41 -07:00
|
|
|
#endif
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
if (ie->open_rid)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!_server_dispatch_until(ie->open_rid))
|
|
|
|
return CSERVE2_GENERIC;
|
2012-05-03 14:01:31 -07:00
|
|
|
if (!ie->data1)
|
|
|
|
return CSERVE2_GENERIC;
|
|
|
|
}
|
2013-06-04 03:40:36 -07:00
|
|
|
|
|
|
|
return CSERVE2_NONE;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evas_cserve2_image_data_load(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
unsigned int rid;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
rid = _image_load_server_send(ie);
|
|
|
|
if (!rid)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
ie->load_rid = rid;
|
|
|
|
|
|
|
|
if (ie->data2)
|
|
|
|
return EINA_TRUE;
|
|
|
|
else
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
int
|
2012-05-03 14:01:31 -07:00
|
|
|
evas_cserve2_image_load_data_wait(Image_Entry *ie)
|
|
|
|
{
|
2013-07-28 23:41:23 -07:00
|
|
|
const Image_Data *idata;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie)
|
|
|
|
return CSERVE2_GENERIC;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
#if USE_SHARED_INDEX
|
2013-07-28 23:41:23 -07:00
|
|
|
idata = _shared_image_entry_image_data_find(ie);
|
2013-08-22 23:10:03 -07:00
|
|
|
if (idata && idata->valid)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
|
|
|
// FIXME: Ugly copy & paste from _loaded_handle
|
|
|
|
Data_Entry *dentry = ie->data2;
|
|
|
|
RGBA_Image *im = (RGBA_Image *)ie;
|
|
|
|
const char *shmpath;
|
|
|
|
|
|
|
|
shmpath = _shared_string_get(idata->shm_id);
|
|
|
|
if (!shmpath) goto load_wait;
|
|
|
|
INF("Bypassing image load socket wait. Image found: %d in %s",
|
|
|
|
idata->id, shmpath);
|
|
|
|
|
|
|
|
dentry->shm.mmap_offset = 0;
|
|
|
|
dentry->shm.use_offset = 0;
|
|
|
|
dentry->shm.f = eina_file_open(shmpath, EINA_TRUE);
|
|
|
|
dentry->shm.mmap_size = eina_file_size_get(dentry->shm.f);
|
|
|
|
dentry->shm.image_size = dentry->shm.mmap_size;
|
|
|
|
|
|
|
|
dentry->shm.data = eina_file_map_new(dentry->shm.f, EINA_FILE_WILLNEED,
|
|
|
|
dentry->shm.mmap_offset,
|
|
|
|
dentry->shm.mmap_size);
|
|
|
|
if (!dentry->shm.data)
|
|
|
|
{
|
|
|
|
DBG("could not mmap the shm file: %d %m", errno);
|
|
|
|
eina_file_close(dentry->shm.f);
|
|
|
|
dentry->shm.f = NULL;
|
|
|
|
goto load_wait;
|
|
|
|
}
|
|
|
|
|
|
|
|
im->image.data = dentry->shm.data;
|
|
|
|
ie->flags.alpha_sparse = idata->alpha_sparse;
|
|
|
|
ie->flags.loaded = EINA_TRUE;
|
|
|
|
im->image.no_free = 1;
|
|
|
|
|
|
|
|
ie->load_rid = 0;
|
|
|
|
return CSERVE2_NONE;
|
|
|
|
}
|
2013-07-31 04:29:41 -07:00
|
|
|
#endif
|
2013-07-28 23:41:23 -07:00
|
|
|
|
|
|
|
load_wait:
|
2012-05-03 14:01:31 -07:00
|
|
|
if (ie->load_rid)
|
2013-06-04 03:40:36 -07:00
|
|
|
{
|
|
|
|
if (!_server_dispatch_until(ie->load_rid))
|
|
|
|
return CSERVE2_GENERIC;
|
|
|
|
if (!ie->data2)
|
|
|
|
return CSERVE2_GENERIC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CSERVE2_NONE;
|
2012-05-03 14:01:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evas_cserve2_image_preload(Image_Entry *ie, void (*preloaded_cb)(void *im, Eina_Bool success))
|
|
|
|
{
|
|
|
|
unsigned int rid;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie || !ie->data1)
|
2012-05-03 14:01:31 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
rid = _image_preload_server_send(ie, preloaded_cb);
|
|
|
|
if (!rid)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
ie->preload_rid = rid;
|
|
|
|
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_cserve2_image_free(Image_Entry *ie)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie || !ie->data1)
|
2012-05-03 14:01:31 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!_image_close_server_send(ie))
|
|
|
|
WRN("Couldn't send close message to cserve2.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_cserve2_image_unload(Image_Entry *ie)
|
|
|
|
{
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!ie || !ie->data2)
|
2012-05-03 14:01:31 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!_image_unload_server_send(ie))
|
|
|
|
WRN("Couldn't send unload message to cserve2.");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evas_cserve2_dispatch(void)
|
|
|
|
{
|
|
|
|
_server_dispatch_until(0);
|
|
|
|
}
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
typedef struct _Glyph_Map Glyph_Map;
|
|
|
|
typedef struct _CS_Glyph_Out CS_Glyph_Out;
|
|
|
|
|
|
|
|
struct _Font_Entry
|
|
|
|
{
|
|
|
|
const char *source;
|
|
|
|
const char *name;
|
|
|
|
unsigned int size;
|
|
|
|
unsigned int dpi;
|
|
|
|
Font_Rend_Flags wanted_rend;
|
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
char *hkey;
|
|
|
|
int font_data_id;
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
unsigned int rid; // open
|
|
|
|
|
2013-08-25 23:31:52 -07:00
|
|
|
Glyph_Map *map;
|
2012-06-22 13:56:53 -07:00
|
|
|
Fash_Glyph2 *fash[3]; // one per hinting value
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
Eina_Clist glyphs_queue;
|
|
|
|
int glyphs_queue_count;
|
|
|
|
Eina_Clist glyphs_used;
|
|
|
|
int glyphs_used_count;
|
|
|
|
|
|
|
|
Eina_Bool failed : 1;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _Glyph_Map
|
|
|
|
{
|
|
|
|
Font_Entry *fe;
|
2013-08-25 23:31:52 -07:00
|
|
|
Shared_Index index;
|
|
|
|
Shared_Buffer mempool;
|
2012-06-22 13:31:31 -07:00
|
|
|
Eina_Clist glyphs;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _CS_Glyph_Out
|
|
|
|
{
|
|
|
|
RGBA_Font_Glyph_Out base;
|
|
|
|
Eina_Clist map_entry;
|
|
|
|
Eina_Clist used_list;
|
|
|
|
unsigned int idx;
|
|
|
|
unsigned int rid;
|
|
|
|
Glyph_Map *map;
|
|
|
|
unsigned int offset;
|
|
|
|
unsigned int size;
|
|
|
|
Eina_Bool used;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
2013-08-25 23:31:52 -07:00
|
|
|
_glyphs_map_free(Glyph_Map *map)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
2013-08-25 23:31:52 -07:00
|
|
|
if (!map) return;
|
|
|
|
eina_file_map_free(map->mempool.f, map->mempool.data);
|
|
|
|
eina_file_close(map->mempool.f);
|
|
|
|
eina_file_map_free(map->index.f, map->index.data);
|
|
|
|
eina_file_close(map->index.f);
|
2013-08-25 23:40:54 -07:00
|
|
|
eina_hash_free(map->index.entries_by_hkey);
|
2013-08-25 23:31:52 -07:00
|
|
|
map->fe->map = NULL;
|
|
|
|
free(map);
|
2012-06-22 13:31:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_glyph_out_free(void *gl)
|
|
|
|
{
|
|
|
|
CS_Glyph_Out *glout = gl;
|
|
|
|
|
|
|
|
if (glout->map)
|
|
|
|
{
|
|
|
|
eina_clist_remove(&glout->map_entry);
|
|
|
|
if (eina_clist_empty(&glout->map->glyphs))
|
2013-08-25 23:31:52 -07:00
|
|
|
_glyphs_map_free(glout->map);
|
2012-06-22 13:31:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
free(glout);
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
static void
|
|
|
|
_font_entry_free(Font_Entry *fe)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
if (fe->fash[i])
|
|
|
|
fash_gl_free(fe->fash[i]);
|
|
|
|
|
2013-08-19 21:09:02 -07:00
|
|
|
eina_hash_del_by_key(_index.fonts.entries_by_hkey, fe->hkey);
|
|
|
|
free(fe->hkey);
|
2013-06-04 03:40:36 -07:00
|
|
|
eina_stringshare_del(fe->source);
|
|
|
|
eina_stringshare_del(fe->name);
|
2013-08-25 23:31:52 -07:00
|
|
|
_glyphs_map_free(fe->map);
|
2013-06-04 03:40:36 -07:00
|
|
|
free(fe);
|
|
|
|
}
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_font_loaded_cb(void *data, const void *msg, int size)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
|
|
|
const Msg_Base *m = msg;
|
|
|
|
Font_Entry *fe = data;
|
|
|
|
|
|
|
|
fe->rid = 0;
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if ((size < (int) sizeof(*m))
|
|
|
|
|| (m->type == CSERVE2_ERROR))
|
2012-06-22 13:31:31 -07:00
|
|
|
fe->failed = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
_font_load_server_send(Font_Entry *fe, Message_Type type)
|
|
|
|
{
|
|
|
|
Msg_Font_Load *msg;
|
|
|
|
int source_len, path_len, size;
|
|
|
|
char *buf;
|
|
|
|
unsigned int ret = 0;
|
2013-06-04 03:40:36 -07:00
|
|
|
Op_Callback cb = NULL;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
if (!cserve2_init)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
source_len = fe->source ? eina_stringshare_strlen(fe->source) + 1 : 0;
|
|
|
|
path_len = eina_stringshare_strlen(fe->name) + 1;
|
|
|
|
|
|
|
|
size = sizeof(*msg) + path_len + source_len;
|
|
|
|
msg = calloc(1, size);
|
|
|
|
|
|
|
|
msg->base.rid = _next_rid();
|
|
|
|
msg->base.type = type;
|
|
|
|
|
|
|
|
msg->sourcelen = source_len;
|
|
|
|
msg->pathlen = path_len;
|
|
|
|
msg->rend_flags = fe->wanted_rend;
|
|
|
|
msg->size = fe->size;
|
|
|
|
msg->dpi = fe->dpi;
|
|
|
|
|
|
|
|
buf = ((char *)msg) + sizeof(*msg);
|
2013-07-16 01:18:59 -07:00
|
|
|
if (source_len > 0) memcpy(buf, fe->source, source_len);
|
2012-06-22 13:31:31 -07:00
|
|
|
buf += source_len;
|
|
|
|
memcpy(buf, fe->name, path_len);
|
|
|
|
|
|
|
|
if (type == CSERVE2_FONT_LOAD)
|
|
|
|
cb = _font_loaded_cb;
|
|
|
|
|
|
|
|
if (_server_send(msg, size, cb, fe))
|
|
|
|
ret = msg->base.rid;
|
|
|
|
|
|
|
|
free(msg);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Font_Entry *
|
2013-08-19 21:09:02 -07:00
|
|
|
evas_cserve2_font_load(const char *source, const char *name, int size, int dpi,
|
|
|
|
Font_Rend_Flags wanted_rend)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
|
|
|
Font_Entry *fe;
|
|
|
|
|
|
|
|
fe = calloc(1, sizeof(Font_Entry));
|
|
|
|
if (!fe) return NULL;
|
|
|
|
|
|
|
|
fe->source = source ? eina_stringshare_add(source) : NULL;
|
|
|
|
fe->name = eina_stringshare_add(name);
|
|
|
|
fe->size = size;
|
|
|
|
fe->dpi = dpi;
|
|
|
|
fe->wanted_rend = wanted_rend;
|
|
|
|
|
|
|
|
if (!(fe->rid = _font_load_server_send(fe, CSERVE2_FONT_LOAD)))
|
|
|
|
{
|
|
|
|
eina_stringshare_del(fe->source);
|
|
|
|
eina_stringshare_del(fe->name);
|
|
|
|
free(fe);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
eina_clist_init(&fe->glyphs_queue);
|
|
|
|
eina_clist_init(&fe->glyphs_used);
|
|
|
|
|
2013-08-19 21:09:02 -07:00
|
|
|
if (asprintf(&fe->hkey, "%s:%s/%u:%u:%u", fe->name, fe->source,
|
|
|
|
fe->size, fe->dpi, (unsigned int) fe->wanted_rend) == -1)
|
|
|
|
fe->hkey = NULL;
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
return fe;
|
|
|
|
}
|
|
|
|
|
2013-01-09 13:37:34 -08:00
|
|
|
int
|
|
|
|
evas_cserve2_font_load_wait(Font_Entry *fe)
|
2012-12-21 13:11:23 -08:00
|
|
|
{
|
2013-08-19 21:09:02 -07:00
|
|
|
#if USE_SHARED_INDEX
|
|
|
|
const Font_Data *fd;
|
|
|
|
Eina_Bool failed;
|
|
|
|
unsigned int rid, rrid;
|
|
|
|
|
|
|
|
rid = fe->rid;
|
|
|
|
rrid = _server_dispatch(&failed);
|
|
|
|
if ((rid == rrid) && !fe->failed)
|
|
|
|
return CSERVE2_NONE;
|
|
|
|
|
|
|
|
fd = _shared_font_entry_data_find(fe);
|
|
|
|
if (fd)
|
|
|
|
{
|
|
|
|
INF("Bypassing socket wait (rid %d)", fe->rid);
|
|
|
|
fe->failed = EINA_FALSE;
|
|
|
|
fe->rid = 0;
|
|
|
|
return CSERVE2_NONE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (!_server_dispatch_until(fe->rid))
|
|
|
|
return CSERVE2_GENERIC;
|
2012-12-21 13:11:23 -08:00
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
if (fe->failed)
|
|
|
|
return CSERVE2_GENERIC;
|
2012-12-21 13:11:23 -08:00
|
|
|
|
|
|
|
return CSERVE2_NONE;
|
|
|
|
}
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
void
|
|
|
|
evas_cserve2_font_free(Font_Entry *fe)
|
|
|
|
{
|
2012-12-21 13:11:23 -08:00
|
|
|
int ret;
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
if (!fe) return;
|
|
|
|
|
2013-01-09 13:37:34 -08:00
|
|
|
ret = evas_cserve2_font_load_wait(fe);
|
2013-06-04 03:40:36 -07:00
|
|
|
if (ret != CSERVE2_NONE)
|
2012-12-21 13:11:23 -08:00
|
|
|
{
|
|
|
|
ERR("Failed to wait loading font '%s'.", fe->name);
|
2013-06-19 22:38:42 -07:00
|
|
|
_font_entry_free(fe);
|
2012-12-21 13:11:23 -08:00
|
|
|
return;
|
|
|
|
}
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
_font_load_server_send(fe, CSERVE2_FONT_UNLOAD);
|
|
|
|
|
|
|
|
_font_entry_free(fe);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
Font_Entry *fe;
|
|
|
|
Font_Hint_Flags hints;
|
|
|
|
unsigned int rid;
|
|
|
|
} Glyph_Request_Data;
|
|
|
|
|
2013-08-25 23:31:52 -07:00
|
|
|
static Glyph_Map *
|
|
|
|
_glyph_map_open(Font_Entry *fe, const char *indexpath, const char *datapath)
|
|
|
|
{
|
|
|
|
Glyph_Map *map;
|
|
|
|
|
|
|
|
if (!fe) return NULL;
|
|
|
|
if (fe->map) return fe->map;
|
|
|
|
|
|
|
|
map = calloc(1, sizeof(*map));
|
|
|
|
if (!map) return NULL;
|
|
|
|
|
|
|
|
map->fe = fe;
|
|
|
|
eina_clist_init(&map->glyphs);
|
|
|
|
eina_strlcpy(map->mempool.path, datapath, SHARED_BUFFER_PATH_MAX);
|
|
|
|
|
2013-08-25 23:40:54 -07:00
|
|
|
if (indexpath)
|
|
|
|
{
|
|
|
|
eina_strlcpy(map->index.path, indexpath, SHARED_BUFFER_PATH_MAX);
|
|
|
|
map->index.generation_id = _index.generation_id;
|
|
|
|
_shared_index_remap_check(&map->index, sizeof(Glyph_Data));
|
|
|
|
}
|
2013-08-25 23:31:52 -07:00
|
|
|
|
|
|
|
map->mempool.f = eina_file_open(map->mempool.path, EINA_TRUE);
|
|
|
|
map->mempool.size = eina_file_size_get(map->mempool.f);
|
|
|
|
map->mempool.data = eina_file_map_all(map->mempool.f, EINA_FILE_RANDOM);
|
|
|
|
|
|
|
|
fe->map = map;
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
2013-08-26 00:48:49 -07:00
|
|
|
static Eina_Bool
|
2013-08-25 23:40:54 -07:00
|
|
|
_glyph_map_remap_check(Glyph_Map *map)
|
|
|
|
{
|
2013-08-26 00:48:49 -07:00
|
|
|
Eina_Bool changed = EINA_FALSE;
|
|
|
|
int oldcount;
|
|
|
|
|
2013-08-25 23:40:54 -07:00
|
|
|
if (eina_file_refresh(map->mempool.f)
|
|
|
|
|| (eina_file_size_get(map->mempool.f) != (size_t) map->mempool.size))
|
|
|
|
{
|
2013-08-26 01:32:09 -07:00
|
|
|
CS_Glyph_Out *gl;
|
|
|
|
|
2013-08-25 23:40:54 -07:00
|
|
|
WRN("Glyph pool has been resized.");
|
|
|
|
eina_file_map_free(map->mempool.f, map->mempool.data);
|
|
|
|
map->mempool.data = eina_file_map_all(map->mempool.f, EINA_FILE_RANDOM);
|
|
|
|
if (map->mempool.data)
|
|
|
|
map->mempool.size = eina_file_size_get(map->mempool.f);
|
|
|
|
else
|
|
|
|
map->mempool.size = 0;
|
2013-08-26 00:48:49 -07:00
|
|
|
changed = EINA_TRUE;
|
2013-08-26 01:32:09 -07:00
|
|
|
|
|
|
|
// Remap loaded glyphs
|
|
|
|
EINA_CLIST_FOR_EACH_ENTRY(gl, &map->fe->map->glyphs,
|
|
|
|
CS_Glyph_Out, map_entry)
|
|
|
|
{
|
|
|
|
if (map->mempool.data)
|
|
|
|
gl->base.bitmap.buffer = (unsigned char *)
|
|
|
|
map->mempool.data + gl->offset;
|
|
|
|
else
|
|
|
|
gl->base.bitmap.buffer = NULL;
|
|
|
|
}
|
2013-08-26 00:48:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
map->index.generation_id = _index.generation_id;
|
|
|
|
oldcount = map->index.count;
|
|
|
|
_shared_index_remap_check(&map->index, sizeof(Glyph_Data));
|
|
|
|
changed |= (oldcount != map->index.count);
|
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_font_entry_glyph_map_rebuild_check(Font_Entry *fe, Font_Hint_Flags hints)
|
|
|
|
{
|
|
|
|
Eina_Bool changed = EINA_FALSE;
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
if (!fe->map)
|
|
|
|
{
|
|
|
|
const Font_Data *fd;
|
|
|
|
const char *idxpath, *datapath;
|
|
|
|
|
|
|
|
fd = _shared_font_entry_data_find(fe);
|
|
|
|
if (!fd) return -1;
|
|
|
|
|
|
|
|
idxpath = _shared_string_get(fd->glyph_index_shm);
|
|
|
|
datapath = _shared_string_get(fd->mempool_shm);
|
|
|
|
if (!idxpath || !datapath) return -1;
|
|
|
|
|
|
|
|
fe->map =_glyph_map_open(fe, idxpath, datapath);
|
|
|
|
changed = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
changed |= _glyph_map_remap_check(fe->map);
|
|
|
|
if (changed && fe->map && fe->map->index.data && fe->map->mempool.data)
|
|
|
|
{
|
|
|
|
CS_Glyph_Out *gl;
|
|
|
|
const Glyph_Data *gd;
|
|
|
|
int k, tot = 0;
|
|
|
|
|
|
|
|
DBG("Rebuilding font hash based on shared index...");
|
|
|
|
for (k = 0; k < fe->map->index.count; k++)
|
|
|
|
{
|
|
|
|
gd = &(fe->map->index.entries.gldata[k]);
|
|
|
|
if (!gd->id) break;
|
|
|
|
if (!gd->refcount) continue;
|
|
|
|
|
|
|
|
tot++;
|
|
|
|
gl = fash_gl_find(fe->fash[hints], gd->index);
|
|
|
|
if (gl && gl->base.bitmap.buffer) continue;
|
|
|
|
|
|
|
|
if (!gl) gl = calloc(1, sizeof(*gl));
|
|
|
|
gl->map = fe->map;
|
|
|
|
gl->offset = gd->offset;
|
|
|
|
gl->size = gd->size;
|
|
|
|
gl->base.bitmap.rows = gd->rows;
|
|
|
|
gl->base.bitmap.width = gd->width;
|
|
|
|
gl->base.bitmap.pitch = gd->pitch;
|
|
|
|
gl->base.bitmap.buffer = (unsigned char *)
|
|
|
|
fe->map->mempool.data + gl->offset;
|
|
|
|
gl->base.bitmap.num_grays = gd->num_grays;
|
|
|
|
gl->base.bitmap.pixel_mode = gd->pixel_mode;
|
2013-08-26 23:35:22 -07:00
|
|
|
gl->idx = gd->index;
|
2013-08-26 00:48:49 -07:00
|
|
|
gl->rid = 0;
|
|
|
|
|
|
|
|
eina_clist_add_head(&fe->map->glyphs, &gl->map_entry);
|
|
|
|
fash_gl_add(fe->fash[hints], gd->index, gl);
|
|
|
|
cnt++;
|
|
|
|
}
|
2013-08-26 23:35:22 -07:00
|
|
|
if (cnt)
|
|
|
|
DBG("Added %d glyphs to the font hash (out of %d scanned)", cnt, tot);
|
2013-08-25 23:40:54 -07:00
|
|
|
}
|
2013-08-26 00:48:49 -07:00
|
|
|
|
|
|
|
return cnt;
|
2013-08-25 23:40:54 -07:00
|
|
|
}
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
static void
|
2013-06-04 03:40:36 -07:00
|
|
|
_glyph_request_cb(void *data, const void *msg, int size)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
|
|
|
const Msg_Font_Glyphs_Loaded *resp = msg;
|
|
|
|
Glyph_Request_Data *grd = data;
|
|
|
|
Font_Entry *fe = grd->fe;
|
|
|
|
const char *buf;
|
2013-08-18 20:22:19 -07:00
|
|
|
int i, nglyphs;
|
|
|
|
int namelen;
|
|
|
|
const char *name;
|
|
|
|
int pos;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
if (resp->base.type == CSERVE2_ERROR)
|
2013-06-04 03:40:36 -07:00
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (!fe->fash[grd->hints])
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (size <= (int) sizeof(*resp)) goto end;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
buf = (const char *)resp + sizeof(*resp);
|
2013-08-18 20:22:19 -07:00
|
|
|
pos = buf - (const char*) resp;
|
2013-06-04 03:40:36 -07:00
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
pos += sizeof(int);
|
|
|
|
if (pos > size) goto end;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
memcpy(&namelen, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
2012-06-22 13:31:31 -07:00
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
pos += namelen + sizeof(int);
|
|
|
|
if (pos > size) goto end;
|
2013-06-04 03:40:36 -07:00
|
|
|
|
2013-08-25 23:31:52 -07:00
|
|
|
name = buf; //eina_stringshare_add_length(buf, namelen);
|
2013-08-18 20:22:19 -07:00
|
|
|
buf += namelen;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
memcpy(&nglyphs, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
2012-06-22 13:31:31 -07:00
|
|
|
|
2013-08-25 23:31:52 -07:00
|
|
|
if (!fe->map)
|
2013-08-18 20:22:19 -07:00
|
|
|
{
|
2013-08-25 23:31:52 -07:00
|
|
|
const Font_Data *fd;
|
|
|
|
const char *idxpath = NULL, *datapath;
|
|
|
|
|
|
|
|
fd = _shared_font_entry_data_find(fe);
|
|
|
|
if (fd)
|
|
|
|
{
|
|
|
|
idxpath = _shared_string_get(fd->glyph_index_shm);
|
|
|
|
datapath = _shared_string_get(fd->mempool_shm);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
datapath = name;
|
|
|
|
fe->map = _glyph_map_open(fe, idxpath, datapath);
|
2013-08-18 20:22:19 -07:00
|
|
|
}
|
2013-08-25 23:40:54 -07:00
|
|
|
else
|
|
|
|
_glyph_map_remap_check(fe->map);
|
2013-08-18 20:22:19 -07:00
|
|
|
|
|
|
|
for (i = 0; i < nglyphs; i++)
|
|
|
|
{
|
|
|
|
string_t shm_id;
|
|
|
|
unsigned int idx, offset, glsize;
|
|
|
|
int rows, width, pitch, num_grays, pixel_mode;
|
|
|
|
CS_Glyph_Out *gl;
|
|
|
|
|
|
|
|
pos = buf - (const char*) resp;
|
|
|
|
pos += 8 * sizeof(int);
|
|
|
|
if (pos > size) goto end;
|
2012-06-22 13:31:31 -07:00
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
memcpy(&idx, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&shm_id, buf, sizeof(string_t));
|
|
|
|
buf += sizeof(string_t);
|
|
|
|
memcpy(&offset, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&glsize, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&rows, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&width, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&pitch, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&num_grays, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
memcpy(&pixel_mode, buf, sizeof(int));
|
|
|
|
buf += sizeof(int);
|
|
|
|
|
|
|
|
gl = fash_gl_find(fe->fash[grd->hints], idx);
|
|
|
|
if (gl)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
2013-08-25 23:31:52 -07:00
|
|
|
gl->map = fe->map;
|
2013-08-18 20:22:19 -07:00
|
|
|
gl->offset = offset;
|
|
|
|
gl->size = glsize;
|
|
|
|
gl->base.bitmap.rows = rows;
|
|
|
|
gl->base.bitmap.width = width;
|
|
|
|
gl->base.bitmap.pitch = pitch;
|
2013-08-25 23:31:52 -07:00
|
|
|
gl->base.bitmap.buffer = (unsigned char *)
|
|
|
|
fe->map->mempool.data + gl->offset;
|
2013-08-18 20:22:19 -07:00
|
|
|
gl->base.bitmap.num_grays = num_grays;
|
|
|
|
gl->base.bitmap.pixel_mode = pixel_mode;
|
|
|
|
gl->rid = 0;
|
|
|
|
|
2013-08-25 23:40:54 -07:00
|
|
|
if (gl->offset + glsize > (size_t) fe->map->mempool.size)
|
|
|
|
{
|
|
|
|
ERR("Glyph is out of the buffer. Set buffer to NULL.");
|
|
|
|
gl->base.bitmap.buffer = NULL;
|
|
|
|
}
|
|
|
|
|
2013-08-25 23:31:52 -07:00
|
|
|
eina_clist_add_head(&fe->map->glyphs, &gl->map_entry);
|
2012-06-22 13:31:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
end:
|
2012-06-22 13:31:31 -07:00
|
|
|
free(grd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
|
|
|
_glyph_request_server_send(Font_Entry *fe, Font_Hint_Flags hints, Eina_Bool used)
|
|
|
|
{
|
|
|
|
Msg_Font_Glyphs_Request *msg;
|
|
|
|
Glyph_Request_Data *grd = NULL;
|
|
|
|
int source_len, name_len, size, nglyphs;
|
|
|
|
char *buf;
|
|
|
|
unsigned int *glyphs;
|
|
|
|
unsigned int ret = 0;
|
|
|
|
Op_Callback cb;
|
|
|
|
Eina_Clist *queue, *itr, *itr_next;
|
|
|
|
|
|
|
|
|
|
|
|
source_len = fe->source ? eina_stringshare_strlen(fe->source) + 1 : 0;
|
|
|
|
name_len = eina_stringshare_strlen(fe->name) + 1;
|
|
|
|
|
|
|
|
if (!used)
|
|
|
|
{
|
|
|
|
nglyphs = fe->glyphs_queue_count;
|
|
|
|
queue = &fe->glyphs_queue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nglyphs = fe->glyphs_used_count;
|
|
|
|
queue = &fe->glyphs_used;
|
|
|
|
}
|
|
|
|
|
|
|
|
size = sizeof(*msg) + source_len + name_len + (nglyphs * sizeof(int));
|
|
|
|
msg = calloc(1, size);
|
|
|
|
|
|
|
|
msg->base.rid = _next_rid();
|
|
|
|
if (!used)
|
|
|
|
msg->base.type = CSERVE2_FONT_GLYPHS_LOAD;
|
|
|
|
else
|
|
|
|
msg->base.type = CSERVE2_FONT_GLYPHS_USED;
|
|
|
|
|
|
|
|
msg->sourcelen = source_len;
|
|
|
|
msg->pathlen = name_len;
|
|
|
|
msg->rend_flags = fe->wanted_rend;
|
|
|
|
msg->size = fe->size;
|
|
|
|
msg->dpi = fe->dpi;
|
|
|
|
msg->hint = hints;
|
|
|
|
msg->nglyphs = nglyphs;
|
|
|
|
|
|
|
|
buf = ((char *)msg) + sizeof(*msg);
|
2013-07-16 01:18:59 -07:00
|
|
|
if (source_len > 0) memcpy(buf, fe->source, source_len);
|
2012-06-22 13:31:31 -07:00
|
|
|
buf += source_len;
|
|
|
|
memcpy(buf, fe->name, name_len);
|
|
|
|
buf += name_len;
|
|
|
|
glyphs = (unsigned int *)buf;
|
|
|
|
nglyphs = 0;
|
|
|
|
EINA_CLIST_FOR_EACH_SAFE(itr, itr_next, queue)
|
|
|
|
{
|
|
|
|
CS_Glyph_Out *gl;
|
|
|
|
|
|
|
|
if (!used)
|
|
|
|
{
|
|
|
|
gl = EINA_CLIST_ENTRY(itr, CS_Glyph_Out, map_entry);
|
|
|
|
gl->rid = msg->base.rid;
|
|
|
|
eina_clist_remove(&gl->map_entry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gl = EINA_CLIST_ENTRY(itr, CS_Glyph_Out, used_list);
|
|
|
|
gl->used = EINA_FALSE;
|
|
|
|
eina_clist_remove(&gl->used_list);
|
|
|
|
}
|
|
|
|
glyphs[nglyphs++] = gl->idx;
|
|
|
|
}
|
|
|
|
if (!used)
|
|
|
|
fe->glyphs_queue_count = 0;
|
|
|
|
else
|
|
|
|
fe->glyphs_used_count = 0;
|
|
|
|
|
|
|
|
if (!used)
|
|
|
|
{
|
|
|
|
cb = _glyph_request_cb;
|
|
|
|
grd = malloc(sizeof(*grd));
|
|
|
|
grd->fe = fe;
|
|
|
|
grd->rid = msg->base.rid;
|
|
|
|
grd->hints = hints;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
cb = NULL;
|
|
|
|
|
|
|
|
if (_server_send(msg, size, cb, grd))
|
|
|
|
ret = msg->base.rid;
|
|
|
|
else
|
|
|
|
free(grd);
|
|
|
|
|
|
|
|
free(msg);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evas_cserve2_font_glyph_request(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints)
|
|
|
|
{
|
2012-06-22 13:56:53 -07:00
|
|
|
Fash_Glyph2 *fash;
|
2012-06-22 13:31:31 -07:00
|
|
|
CS_Glyph_Out *glyph;
|
|
|
|
|
|
|
|
if (fe->rid)
|
2012-06-29 15:04:13 -07:00
|
|
|
_server_dispatch_until(0); /* dispatch anything pending just to avoid
|
|
|
|
requesting glyphs for a font we may already
|
|
|
|
know it failed loading, but don't block */
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
if (fe->failed)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
fash = fe->fash[hints];
|
|
|
|
if (!fash)
|
|
|
|
{
|
|
|
|
fash = fash_gl_new(_glyph_out_free);
|
|
|
|
fe->fash[hints] = fash;
|
|
|
|
}
|
|
|
|
|
|
|
|
glyph = fash_gl_find(fash, idx);
|
|
|
|
if (!glyph)
|
|
|
|
{
|
|
|
|
glyph = calloc(1, sizeof(*glyph));
|
|
|
|
|
|
|
|
glyph->idx = idx;
|
|
|
|
|
|
|
|
fash_gl_add(fash, idx, glyph);
|
|
|
|
|
|
|
|
eina_clist_add_head(&fe->glyphs_queue, &glyph->map_entry);
|
|
|
|
fe->glyphs_queue_count++;
|
|
|
|
}
|
|
|
|
else if (!glyph->used)
|
|
|
|
{
|
|
|
|
eina_clist_add_head(&fe->glyphs_used, &glyph->used_list);
|
|
|
|
fe->glyphs_used_count++;
|
|
|
|
glyph->used = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2013-06-04 03:40:36 -07:00
|
|
|
/* FIXME crude way to manage a queue, but it will work for now */
|
2012-06-22 13:31:31 -07:00
|
|
|
if (fe->glyphs_queue_count == 50)
|
|
|
|
_glyph_request_server_send(fe, hints, EINA_FALSE);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evas_cserve2_font_glyph_used(Font_Entry *fe, unsigned int idx, Font_Hint_Flags hints)
|
|
|
|
{
|
2012-06-22 13:56:53 -07:00
|
|
|
Fash_Glyph2 *fash;
|
2012-06-22 13:31:31 -07:00
|
|
|
CS_Glyph_Out *glyph;
|
|
|
|
|
|
|
|
if (fe->rid)
|
2012-06-29 15:04:13 -07:00
|
|
|
_server_dispatch_until(0); /* dispatch anything pending just to avoid
|
|
|
|
requesting glyphs for a font we may already
|
|
|
|
know it failed loading, but don't block */
|
2012-06-22 13:31:31 -07:00
|
|
|
|
|
|
|
if (fe->failed)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
fash = fe->fash[hints];
|
|
|
|
if (!fash)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
glyph = fash_gl_find(fash, idx);
|
|
|
|
/* If we found the glyph on client cache, we should also have at least
|
|
|
|
* its request done.
|
|
|
|
*/
|
|
|
|
if (!glyph)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (!glyph->map)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
if (glyph->used)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
eina_clist_add_head(&fe->glyphs_used, &glyph->used_list);
|
|
|
|
fe->glyphs_used_count++;
|
|
|
|
glyph->used = EINA_TRUE;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
RGBA_Font_Glyph_Out *
|
2013-08-26 00:48:49 -07:00
|
|
|
evas_cserve2_font_glyph_bitmap_get(Font_Entry *fe, unsigned int idx,
|
|
|
|
Font_Hint_Flags hints)
|
2012-06-22 13:31:31 -07:00
|
|
|
{
|
2012-06-22 13:56:53 -07:00
|
|
|
Fash_Glyph2 *fash;
|
2012-06-22 13:31:31 -07:00
|
|
|
CS_Glyph_Out *out;
|
|
|
|
|
|
|
|
if (fe->failed)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* quick hack, flush pending queue when we are asked for a bitmap */
|
|
|
|
if (fe->glyphs_queue_count)
|
|
|
|
_glyph_request_server_send(fe, hints, EINA_FALSE);
|
|
|
|
|
|
|
|
if (fe->glyphs_used_count)
|
|
|
|
_glyph_request_server_send(fe, hints, EINA_TRUE);
|
|
|
|
|
|
|
|
fash = fe->fash[hints];
|
|
|
|
if (!fash)
|
|
|
|
{
|
|
|
|
// this should not happen really, so let the user know he fucked up
|
2013-08-26 00:48:49 -07:00
|
|
|
ERR("was called with a hinting value that was not requested!");
|
2012-06-22 13:31:31 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
out = fash_gl_find(fash, idx);
|
|
|
|
if (!out)
|
|
|
|
{
|
|
|
|
// again, if we are asking for a bitmap we were supposed to already
|
|
|
|
// have requested the glyph, it must be there
|
2013-08-26 00:48:49 -07:00
|
|
|
ERR("was called with a glyph index that was not requested!");
|
2012-06-22 13:31:31 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2013-08-26 00:48:49 -07:00
|
|
|
|
|
|
|
#if USE_SHARED_INDEX
|
|
|
|
_font_entry_glyph_map_rebuild_check(fe, hints);
|
|
|
|
#endif
|
|
|
|
|
2012-06-22 13:31:31 -07:00
|
|
|
if (out->rid)
|
|
|
|
_server_dispatch_until(out->rid);
|
|
|
|
|
|
|
|
// promote shm and font entry in lru or something
|
|
|
|
|
|
|
|
return &(out->base);
|
|
|
|
}
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
|
|
|
|
|
|
|
|
// Fast access to shared index tables
|
|
|
|
|
2013-08-22 22:52:11 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_string_index_refresh(void)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-08-22 22:52:11 -07:00
|
|
|
size_t sz;
|
|
|
|
Eina_Bool ret = EINA_FALSE;
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (!_index.strings_entries.data
|
|
|
|
&& _index.strings_entries.path[0]
|
|
|
|
&& _index.strings_index.path[0])
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
_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)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
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;
|
2013-08-22 22:52:11 -07:00
|
|
|
ret = EINA_FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("Mapped string entries from %s", _index.strings_entries.path);
|
|
|
|
ret = EINA_TRUE;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (_index.strings_entries.data &&
|
|
|
|
(!_index.strings_index.data && _index.strings_index.path[0]))
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
_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)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
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;
|
|
|
|
}
|
2013-08-22 22:52:11 -07:00
|
|
|
ret = EINA_TRUE;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
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;
|
2013-08-22 22:52:11 -07:00
|
|
|
ret = EINA_FALSE;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
_shared_index_remap_check(&_index.strings_index, sizeof(Index_Entry));
|
|
|
|
if (_index.strings_entries.data)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-08-22 22:52:11 -07:00
|
|
|
if (eina_file_refresh(_index.strings_entries.f)
|
|
|
|
|| (_index.strings_entries.size != (int) eina_file_size_get(_index.strings_entries.f)))
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
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);
|
2013-08-22 22:52:11 -07:00
|
|
|
return EINA_TRUE;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-22 22:52:11 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the number of correctly opened index arrays
|
|
|
|
static int
|
|
|
|
_server_index_list_set(Msg_Base *data, int size)
|
|
|
|
{
|
|
|
|
Msg_Index_List *msg = (Msg_Index_List *) data;
|
|
|
|
|
|
|
|
// TODO #1: Check populate rule.
|
|
|
|
// TODO #2: Protect memory for read-only access.
|
|
|
|
// TODO #3: Optimize file reopen/remap (esp. strings table)
|
|
|
|
|
|
|
|
if (size != sizeof(*msg) || msg->base.type != CSERVE2_INDEX_LIST)
|
|
|
|
{
|
|
|
|
CRIT("Invalid message! type: %d, size: %d (expected %d)",
|
|
|
|
msg->base.type, size, (int) sizeof(*msg));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_index.generation_id == msg->generation_id)
|
|
|
|
{
|
|
|
|
ERR("New index generation_id is the same as before: %d",
|
|
|
|
_index.generation_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
_index.generation_id = msg->generation_id;
|
|
|
|
|
|
|
|
// 1. Strings (indexes and entries)
|
|
|
|
|
|
|
|
if (_index.strings_entries.data
|
|
|
|
&& strncmp(_index.strings_entries.path, msg->strings_entries_path,
|
|
|
|
SHARED_BUFFER_PATH_MAX) != 0)
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
_string_index_refresh();
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
// 2. File indexes
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
eina_strlcpy(_index.files.path, msg->files_index_path, SHARED_BUFFER_PATH_MAX);
|
|
|
|
_shared_index_remap_check(&_index.files, sizeof(File_Data));
|
2013-07-28 23:41:23 -07:00
|
|
|
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
// 3. Image indexes
|
|
|
|
|
|
|
|
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
|
2013-08-19 21:09:02 -07:00
|
|
|
|
|
|
|
eina_strlcpy(_index.fonts.path, msg->fonts_index_path, SHARED_BUFFER_PATH_MAX);
|
|
|
|
_shared_index_remap_check(&_index.fonts, sizeof(Font_Data));
|
2013-07-31 04:29:41 -07:00
|
|
|
|
|
|
|
return 0;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: (almost) copy & paste from evas_cserve2_cache.c
|
|
|
|
static const char *
|
|
|
|
_shared_string_get(int id)
|
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
Index_Entry *ie;
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-08-22 22:52:11 -07:00
|
|
|
if (!_index.strings_entries.data)
|
|
|
|
{
|
|
|
|
CRIT("Strings table is not valid: no data");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
ie = (Index_Entry *)
|
|
|
|
_shared_index_item_get_by_id(&_index.strings_index, sizeof(*ie), id);
|
2013-07-28 23:41:23 -07:00
|
|
|
if (!ie) return NULL;
|
2013-07-31 04:29:41 -07:00
|
|
|
if (ie->offset < 0) return NULL;
|
2013-07-28 23:41:23 -07:00
|
|
|
if (!ie->refcount) return NULL;
|
2013-08-22 22:52:11 -07:00
|
|
|
if (ie->offset + ie->length > _index.strings_entries.size)
|
|
|
|
{
|
|
|
|
if (eina_file_refresh(_index.strings_entries.f)
|
|
|
|
|| (_index.strings_entries.size != (int) eina_file_size_get(_index.strings_entries.f)))
|
|
|
|
{
|
|
|
|
DBG("String entries size has changed from %d to %d",
|
|
|
|
_index.strings_entries.size, (int) eina_file_size_get(_index.strings_entries.f));
|
|
|
|
if (_string_index_refresh())
|
|
|
|
return _shared_string_get(id);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
return _index.strings_entries.data + ie->offset;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
#define SHARED_INDEX_CHECK(si, typ) \
|
|
|
|
do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \
|
|
|
|
CRIT("Failed to remap index"); return NULL; } } while (0)
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
static const char *
|
|
|
|
_shared_file_data_hkey_get(char *hkey, const char *file, const char *key,
|
|
|
|
size_t hkey_size)
|
|
|
|
{
|
2013-08-22 22:52:11 -07:00
|
|
|
size_t keylen = 0, filelen;
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (key) keylen = strlen(key) + 1;
|
|
|
|
filelen = strlen(file);
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (filelen + keylen + 1 > hkey_size)
|
|
|
|
return NULL;
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
memcpy(hkey, file, filelen);
|
|
|
|
hkey[filelen] = ':';
|
|
|
|
if (key)
|
|
|
|
memcpy(hkey + filelen + 1, key, keylen);
|
|
|
|
else
|
|
|
|
memcpy(hkey + filelen + 1, "(null)", 7);
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
return hkey;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static const File_Data *
|
|
|
|
_shared_image_entry_file_data_find(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
const File_Data *fdata = NULL;
|
|
|
|
File_Entry *fe;
|
2013-07-31 04:29:41 -07:00
|
|
|
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
|
|
|
|
char hkey[PATH_MAX];
|
2013-07-28 23:41:23 -07:00
|
|
|
int k;
|
|
|
|
|
|
|
|
DBG("Trying to find if image '%s:%s' is already opened by cserve2",
|
|
|
|
ie->file, ie->key);
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
SHARED_INDEX_CHECK(_index.files, File_Data);
|
|
|
|
|
|
|
|
if (!_index.strings_index.header || !_index.strings_entries.data)
|
|
|
|
return NULL;
|
|
|
|
|
2013-08-19 21:09:02 -07:00
|
|
|
if (!_index.files.header || !_index.files.entries.filedata)
|
2013-07-28 23:41:23 -07:00
|
|
|
return NULL;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
// Direct access
|
|
|
|
fe = ie->data1;
|
|
|
|
if (fe->server_file_id)
|
|
|
|
{
|
|
|
|
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++)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
const char *file, *key;
|
|
|
|
const File_Data *fd;
|
|
|
|
char fd_hkey[PATH_MAX];
|
|
|
|
|
2013-08-19 21:09:02 -07:00
|
|
|
fd = &(_index.files.entries.filedata[k]);
|
2013-07-31 04:29:41 -07:00
|
|
|
if (!fd->id) break;
|
2013-07-28 23:41:23 -07:00
|
|
|
if (!fd->refcount) continue;
|
|
|
|
|
2013-08-26 01:32:09 -07:00
|
|
|
key = _shared_string_get(fd->key);
|
2013-07-31 04:29:41 -07:00
|
|
|
file = _shared_string_get(fd->path);
|
|
|
|
if (!file)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-08-18 20:22:19 -07:00
|
|
|
ERR("Could not find filename for file %d: path id: %d",
|
|
|
|
fd->id, fd->path);
|
2013-07-31 04:29:41 -07:00
|
|
|
add_to_hash = EINA_FALSE;
|
|
|
|
continue;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
2013-08-26 01:32:09 -07:00
|
|
|
|
|
|
|
// Note: The strings base pointer may change if the index grows
|
|
|
|
if ((key < _index.strings_entries.data) ||
|
|
|
|
(key > _index.strings_entries.data + _index.strings_entries.size))
|
|
|
|
key = _shared_string_get(fd->key);
|
2013-07-31 04:29:41 -07:00
|
|
|
|
|
|
|
_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(hkey, fd_hkey))
|
|
|
|
return fd;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
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)
|
2013-08-23 02:31:30 -07:00
|
|
|
{
|
|
|
|
if (eina_file_refresh(si->f))
|
|
|
|
{
|
|
|
|
WRN("Refreshing indexes.");
|
|
|
|
_string_index_refresh();
|
|
|
|
_shared_index_remap_check(si, elemsize);
|
|
|
|
high = MIN(si->header->emptyidx, si->count);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
high = si->count;
|
|
|
|
}
|
2013-07-31 04:29:41 -07:00
|
|
|
|
|
|
|
base = si->data + sizeof(Shared_Array_Header);
|
|
|
|
|
2013-08-22 00:53:51 -07:00
|
|
|
// Direct access, works for non-repacked arrays
|
|
|
|
if ((int) id < high)
|
|
|
|
{
|
|
|
|
obj = (Shm_Object *) (base + (elemsize * id));
|
|
|
|
if (obj->id == id)
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
// 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);
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Eina_Bool
|
|
|
|
_shared_image_entry_image_data_match(Image_Entry *ie, const Image_Data *id)
|
|
|
|
{
|
|
|
|
int cmp;
|
|
|
|
cmp = memcmp(&ie->load_opts, &id->opts, sizeof(ie->load_opts));
|
|
|
|
if (!cmp)
|
|
|
|
{
|
|
|
|
DBG("Found loaded image entry at %d", id->id);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-07-31 03:31:50 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_shared_index_remap_check(Shared_Index *si, int elemsize)
|
|
|
|
{
|
|
|
|
size_t filesize;
|
|
|
|
Eina_Bool refresh = EINA_FALSE;
|
|
|
|
|
|
|
|
// Note: all checks are unlikely to be true.
|
|
|
|
|
2013-08-01 02:39:38 -07:00
|
|
|
if (!si || elemsize <= 0)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (!si->path[0])
|
|
|
|
{
|
|
|
|
if (si->f)
|
|
|
|
{
|
|
|
|
DBG("Closing index map");
|
|
|
|
eina_file_map_free(si->f, si->data);
|
|
|
|
eina_file_close(si->f);
|
|
|
|
eina_hash_free(si->entries_by_hkey);
|
|
|
|
memset(si, 0, sizeof(*si));
|
|
|
|
}
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-07-31 04:29:41 -07:00
|
|
|
|
2013-07-31 03:31:50 -07:00
|
|
|
if (si->generation_id != _index.generation_id)
|
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
DBG("Generation ID changed from %d to %d.",
|
|
|
|
si->generation_id, _index.generation_id);
|
|
|
|
if (si->f)
|
2013-07-31 03:31:50 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
if (strncmp(si->path, eina_file_filename_get(si->f),
|
|
|
|
SHARED_BUFFER_PATH_MAX) != 0)
|
2013-07-31 03:31:50 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
DBG("Index file changed. Closing and reopening.");
|
2013-07-31 03:31:50 -07:00
|
|
|
eina_file_map_free(si->f, si->data);
|
2013-07-31 04:29:41 -07:00
|
|
|
eina_file_close(si->f);
|
|
|
|
si->f = NULL;
|
2013-07-31 03:31:50 -07:00
|
|
|
si->data = NULL;
|
|
|
|
}
|
2013-07-31 04:29:41 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (si->data)
|
|
|
|
{
|
|
|
|
if (eina_file_refresh(si->f))
|
|
|
|
{
|
|
|
|
DBG("Remapping index.");
|
|
|
|
eina_file_map_free(si->f, si->data);
|
|
|
|
si->data = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_file_close(si->f);
|
|
|
|
si->f = NULL;
|
|
|
|
}
|
|
|
|
}
|
2013-07-31 03:31:50 -07:00
|
|
|
}
|
|
|
|
si->generation_id = _index.generation_id;
|
|
|
|
}
|
|
|
|
if (!si->f)
|
|
|
|
{
|
|
|
|
si->data = NULL; // If that was not NULL, the address was invalid.
|
|
|
|
si->f = eina_file_open(si->path, EINA_TRUE);
|
|
|
|
if (!si->f)
|
|
|
|
{
|
|
|
|
ERR("Could not open index '%s'", si->path);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!si->data)
|
|
|
|
{
|
|
|
|
filesize = eina_file_size_get(si->f);
|
|
|
|
if (filesize < sizeof(Shared_Array_Header))
|
|
|
|
{
|
|
|
|
ERR("Index is invalid. Got file size %d", (int) filesize);
|
|
|
|
eina_file_close(si->f);
|
|
|
|
si->f = NULL;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
si->data = eina_file_map_all(si->f, EINA_FILE_RANDOM);
|
|
|
|
if (!si->data)
|
|
|
|
{
|
|
|
|
ERR("Could not mmap index '%s'", si->path);
|
|
|
|
eina_file_close(si->f);
|
|
|
|
si->f = NULL;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2013-08-22 22:52:11 -07:00
|
|
|
si->count = (filesize - sizeof(Shared_Array_Header)) / elemsize;
|
2013-07-31 03:31:50 -07:00
|
|
|
refresh = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (elemsize != si->header->elemsize)
|
|
|
|
{
|
|
|
|
ERR("Index is invalid. Expected element size %d, got %d.",
|
|
|
|
elemsize, si->header->elemsize);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (si->count != si->header->count)
|
|
|
|
{
|
2013-08-23 02:31:30 -07:00
|
|
|
int oldcount;
|
2013-07-31 03:31:50 -07:00
|
|
|
// generation_id should have been incremented. Maybe we are hitting
|
|
|
|
// a race condition here, when cserve2 grows an index.
|
|
|
|
WRN("Reported index count differs from known count: %d vs %d",
|
|
|
|
si->header->count, si->count);
|
2013-08-23 02:31:30 -07:00
|
|
|
oldcount = si->count;
|
|
|
|
eina_file_refresh(si->f);
|
2013-07-31 03:31:50 -07:00
|
|
|
filesize = eina_file_size_get(si->f);
|
|
|
|
si->count = (filesize - sizeof(Shared_Array_Header)) / elemsize;
|
2013-08-23 02:31:30 -07:00
|
|
|
if (si->count != oldcount)
|
|
|
|
{
|
|
|
|
DBG("Remapping current index");
|
|
|
|
eina_file_map_free(si->f, si->data);
|
|
|
|
si->data = eina_file_map_all(si->f, EINA_FILE_RANDOM);
|
|
|
|
if (!si->data)
|
|
|
|
{
|
|
|
|
ERR("Failed to remap index: %m");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2013-07-31 03:31:50 -07:00
|
|
|
if (si->count > si->header->count)
|
|
|
|
{
|
|
|
|
WRN("Index reports %d elements, but file can contain only %d",
|
|
|
|
si->header->count, si->count);
|
|
|
|
si->count = si->header->count;
|
|
|
|
}
|
|
|
|
refresh = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!si->entries_by_hkey)
|
|
|
|
refresh = EINA_TRUE;
|
|
|
|
|
|
|
|
if (refresh)
|
|
|
|
{
|
|
|
|
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;
|
2013-07-31 04:29:41 -07:00
|
|
|
si->entries.p = si->data + sizeof(Shared_Array_Header);
|
2013-07-31 03:31:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
static const Image_Data *
|
|
|
|
_shared_image_entry_image_data_find(Image_Entry *ie)
|
|
|
|
{
|
|
|
|
const Image_Data *idata = NULL;
|
2013-07-31 04:29:41 -07:00
|
|
|
const char *shmpath;
|
2013-07-28 23:41:23 -07:00
|
|
|
File_Entry *fe;
|
|
|
|
unsigned int file_id = 0;
|
2013-07-31 04:29:41 -07:00
|
|
|
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
|
2013-07-28 23:41:23 -07:00
|
|
|
int k;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
DBG("Trying to find if image '%s:%s' is already loaded by cserve2",
|
|
|
|
ie->file, ie->key);
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (!_index.strings_entries.data || !_index.strings_index.data)
|
|
|
|
return NULL;
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
if (!_index.images.entries.idata || !_index.images.count)
|
|
|
|
return NULL;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
if (!ie->cache_key)
|
|
|
|
{
|
|
|
|
CRIT("Looking for an image in remote cache without hash key?");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
fe = ie->data1;
|
|
|
|
if (fe && fe->server_file_id)
|
|
|
|
file_id = fe->server_file_id;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const File_Data *fdata = _shared_image_entry_file_data_find(ie);
|
|
|
|
if (!fdata)
|
|
|
|
{
|
|
|
|
ERR("File is not opened by cserve2");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
file_id = fdata->id;
|
|
|
|
}
|
|
|
|
|
2013-07-31 03:31:50 -07:00
|
|
|
SHARED_INDEX_CHECK(_index.images, Image_Data);
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
// 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)
|
|
|
|
{
|
2013-08-22 23:10:03 -07:00
|
|
|
DBG("Image found in shared index (by cache_key).");
|
2013-07-31 04:29:41 -07:00
|
|
|
goto found;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Linear search in non-hashed entries. O(n)
|
2013-07-28 23:41:23 -07:00
|
|
|
DBG("Looking for loaded image with file id %d", file_id);
|
2013-07-31 04:29:41 -07:00
|
|
|
for (k = _index.images.last_entry_in_hash; k < _index.images.count; k++)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
const char *file, *key;
|
|
|
|
size_t keylen, filelen;
|
|
|
|
const File_Data *fd;
|
|
|
|
char *hkey;
|
2013-07-28 23:41:23 -07:00
|
|
|
const Image_Data *id = &(_index.images.entries.idata[k]);
|
2013-07-31 04:29:41 -07:00
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
if (!id->id) return NULL;
|
|
|
|
if (!id->refcount) continue;
|
2013-07-31 04:29:41 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2013-08-26 01:32:09 -07:00
|
|
|
|
|
|
|
// Note: The strings base pointer may change if the index grows
|
|
|
|
if ((key < _index.strings_entries.data) ||
|
|
|
|
(key > _index.strings_entries.data + _index.strings_entries.size))
|
|
|
|
key = _shared_string_get(fd->key);
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-07-28 23:41:23 -07:00
|
|
|
if (id->file_id != file_id) continue;
|
|
|
|
|
|
|
|
if (_shared_image_entry_image_data_match(ie, id))
|
|
|
|
{
|
|
|
|
idata = id;
|
2013-07-31 04:29:41 -07:00
|
|
|
goto found;
|
2013-07-28 23:41:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!idata)
|
|
|
|
return NULL;
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
found:
|
2013-08-22 23:10:03 -07:00
|
|
|
if (!idata->valid)
|
|
|
|
{
|
|
|
|
DBG("Found image but it is not ready yet: %d", idata->id);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
shmpath = _shared_string_get(idata->shm_id);
|
|
|
|
if (!shmpath)
|
2013-07-28 23:41:23 -07:00
|
|
|
{
|
2013-07-31 04:29:41 -07:00
|
|
|
ERR("Found image but it is not loaded yet: %d (doload %d)",
|
|
|
|
idata->id, idata->doload);
|
2013-07-28 23:41:23 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:29:41 -07:00
|
|
|
DBG("Found image, loaded, in shm %s", shmpath);
|
2013-07-28 23:41:23 -07:00
|
|
|
return idata;
|
|
|
|
}
|
|
|
|
|
2013-08-18 20:22:19 -07:00
|
|
|
static const Font_Data *
|
|
|
|
_shared_font_entry_data_get_by_id(int id)
|
|
|
|
{
|
|
|
|
return (Font_Data *)
|
|
|
|
_shared_index_item_get_by_id(&_index.fonts, sizeof(Font_Data), id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Font_Data *
|
|
|
|
_shared_font_entry_data_find(Font_Entry *fe)
|
|
|
|
{
|
|
|
|
const Font_Data *fd = NULL;
|
|
|
|
Eina_Bool add_to_hash = SHARED_INDEX_ADD_TO_HASH;
|
|
|
|
char hkey[PATH_MAX];
|
|
|
|
int k;
|
|
|
|
|
|
|
|
if (!_index.strings_entries.data || !_index.strings_index.data)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!fe || !fe->hkey)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (fe->font_data_id)
|
|
|
|
{
|
|
|
|
fd = _shared_font_entry_data_get_by_id(fe->font_data_id);
|
|
|
|
if (fd) return fd;
|
|
|
|
fe->font_data_id = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find in hash
|
|
|
|
fd = eina_hash_find(_index.fonts.entries_by_hkey, fe->hkey);
|
|
|
|
if (fd) return fd;
|
|
|
|
|
|
|
|
// Find in shared index
|
|
|
|
for (k = _index.fonts.last_entry_in_hash;
|
|
|
|
k < _index.fonts.count && k < _index.fonts.header->emptyidx; k++)
|
|
|
|
{
|
|
|
|
const Font_Data *cur;
|
|
|
|
const char *name, *source;
|
|
|
|
|
|
|
|
cur = &(_index.fonts.entries.fontdata[k]);
|
|
|
|
if (!cur->id) return NULL;
|
|
|
|
if (!cur->refcount) continue;
|
|
|
|
|
|
|
|
name = _shared_string_get(cur->name);
|
|
|
|
source = _shared_string_get(cur->file);
|
|
|
|
snprintf(hkey, PATH_MAX, "%s:%s/%u:%u:%u", source, name,
|
|
|
|
cur->size, cur->dpi, cur->rend_flags);
|
|
|
|
|
|
|
|
if (add_to_hash)
|
|
|
|
{
|
|
|
|
eina_hash_add(_index.fonts.entries_by_hkey, hkey, cur);
|
|
|
|
_index.fonts.last_entry_in_hash++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(hkey, fe->hkey))
|
|
|
|
{
|
|
|
|
fe->font_data_id = cur->id;
|
|
|
|
return cur;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
2013-07-28 23:41:23 -07:00
|
|
|
|
2012-05-03 14:01:31 -07:00
|
|
|
#endif
|