forked from enlightenment/efl
evas/cserve2: Prepare shared indexes in clients
- Move required struct definitions to common evas_cs2.h - Open/close shm and map arrays to memory Pretty stupid for now as it will close & reopen the shm files even when unchanged. - Check shm size and array header consistency - Implement message send - Send messages from server when calling repack()
This commit is contained in:
parent
c0bb73c775
commit
47be3a2b81
|
@ -233,6 +233,7 @@ void cserve2_client_del(Client *client);
|
|||
void cserve2_client_deliver(Client *client);
|
||||
void cserve2_client_error_send(Client *client, unsigned int rid, int error_code);
|
||||
ssize_t cserve2_client_send(Client *client, const void *data, size_t size);
|
||||
void cserve2_index_list_send(const char *files_index_path, const char *images_index_path, const char *fonts_index_path);
|
||||
|
||||
Eina_Bool cserve2_fd_watch_add(int fd, Fd_Flags flags, Fd_Watch_Cb cb, const void *data);
|
||||
Eina_Bool cserve2_fd_watch_del(int fd);
|
||||
|
|
|
@ -14,19 +14,14 @@
|
|||
|
||||
#include <Evas_Loader.h>
|
||||
|
||||
typedef int string_t;
|
||||
#define ENTRY Entry base
|
||||
#define ASENTRY(a) (&(a->base))
|
||||
#define ENTRYID(a) ((a)->base.id)
|
||||
#define SHMOBJECT unsigned int id; unsigned int refcount
|
||||
|
||||
typedef struct _Entry Entry;
|
||||
typedef struct _Shm_Object Shm_Object;
|
||||
typedef struct _Reference Reference;
|
||||
typedef struct _File_Entry File_Entry;
|
||||
typedef struct _File_Data File_Data;
|
||||
typedef struct _Image_Entry Image_Entry;
|
||||
typedef struct _Image_Data Image_Data;
|
||||
typedef struct _File_Watch File_Watch;
|
||||
|
||||
typedef struct _Font_Source Font_Source;
|
||||
|
@ -52,46 +47,17 @@ struct _Entry {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct _Shm_Object
|
||||
{
|
||||
SHMOBJECT;
|
||||
};
|
||||
|
||||
struct _File_Entry {
|
||||
ENTRY;
|
||||
File_Watch *watcher;
|
||||
Eina_List *images;
|
||||
};
|
||||
|
||||
struct _File_Data {
|
||||
SHMOBJECT;
|
||||
string_t path;
|
||||
string_t key;
|
||||
string_t loader_data;
|
||||
int w, h;
|
||||
int frame_count;
|
||||
int loop_count;
|
||||
int loop_hint;
|
||||
Eina_Bool alpha : 1;
|
||||
Eina_Bool invalid : 1;
|
||||
};
|
||||
|
||||
|
||||
struct _Image_Entry {
|
||||
ENTRY;
|
||||
Shm_Handle *shm;
|
||||
};
|
||||
|
||||
struct _Image_Data {
|
||||
SHMOBJECT;
|
||||
unsigned int file_id;
|
||||
string_t shm_id;
|
||||
Evas_Image_Load_Opts opts;
|
||||
Eina_Bool alpha_sparse : 1;
|
||||
Eina_Bool unused : 1;
|
||||
Eina_Bool doload : 1;
|
||||
};
|
||||
|
||||
struct _Font_Source {
|
||||
string_t key;
|
||||
string_t name;
|
||||
|
@ -350,12 +316,11 @@ _repack()
|
|||
Shared_Array *sa;
|
||||
int count;
|
||||
|
||||
count = cserve2_shared_array_size_get(_file_data_array);
|
||||
if (count <= 0) return;
|
||||
|
||||
// Repack when we have 10% fragmentation over the whole shm buffer
|
||||
if (_freed_entry_count > 100 ||
|
||||
((_freed_entry_count * 100) / count >= 10))
|
||||
|
||||
count = cserve2_shared_array_size_get(_file_data_array);
|
||||
if ((count > 0) && (_freed_entry_count > 100 ||
|
||||
((_freed_entry_count * 100) / count >= 10)))
|
||||
{
|
||||
DBG("Repacking file data array: %s",
|
||||
cserve2_shared_array_name_get(_file_data_array));
|
||||
|
@ -373,6 +338,12 @@ _repack()
|
|||
_freed_entry_count = 0;
|
||||
_file_data_array = sa;
|
||||
}
|
||||
|
||||
// FIXME TODO: Repack image data array as well
|
||||
|
||||
cserve2_index_list_send(cserve2_shared_array_name_get(_file_data_array),
|
||||
cserve2_shared_array_name_get(_image_data_array),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
typedef struct _Data_Shm Data_Shm;
|
||||
typedef struct _Index_Entry Index_Entry;
|
||||
typedef struct _Block Block;
|
||||
typedef struct _Shared_Array_Header Shared_Array_Header;
|
||||
typedef struct _Shared_Index Shared_Index;
|
||||
|
||||
static int _instances = 0;
|
||||
|
@ -31,18 +30,6 @@ struct _Data_Shm
|
|||
char *data;
|
||||
};
|
||||
|
||||
struct _Shared_Array_Header
|
||||
{
|
||||
int32_t tag;
|
||||
int32_t elemsize;
|
||||
int32_t count;
|
||||
int32_t generation_id;
|
||||
int32_t emptyidx;
|
||||
int32_t sortedidx;
|
||||
int32_t _reserved1;
|
||||
int32_t _reserved2;
|
||||
};
|
||||
|
||||
struct _Shared_Array
|
||||
{
|
||||
Data_Shm *ds;
|
||||
|
|
|
@ -35,6 +35,35 @@ cserve2_client_error_send(Client *client, unsigned int rid, int error_code)
|
|||
cserve2_client_send(client, &msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void
|
||||
cserve2_index_list_send(const char *files_index_path,
|
||||
const char *images_index_path,
|
||||
const char *fonts_index_path)
|
||||
{
|
||||
Eina_Iterator *iter;
|
||||
Client *client;
|
||||
Msg_Index_List msg;
|
||||
const int size = sizeof(msg);
|
||||
|
||||
memset(&msg, 0, size);
|
||||
msg.base.type = CSERVE2_INDEX_LIST;
|
||||
if (files_index_path)
|
||||
eina_strlcpy(msg.files_index_path, files_index_path, 64);
|
||||
if (images_index_path)
|
||||
eina_strlcpy(msg.images_index_path, images_index_path, 64);
|
||||
if (fonts_index_path)
|
||||
eina_strlcpy(msg.fonts_index_path, fonts_index_path, 64);
|
||||
|
||||
iter = eina_hash_iterator_data_new(client_list);
|
||||
EINA_ITERATOR_FOREACH(iter, client)
|
||||
{
|
||||
DBG("Sending updated list of indexes to client %d", client->id);
|
||||
cserve2_client_send(client, &size, sizeof(size));
|
||||
cserve2_client_send(client, &msg, sizeof(msg));
|
||||
}
|
||||
eina_iterator_free(iter);
|
||||
}
|
||||
|
||||
static void
|
||||
_cserve2_client_close(Client *client)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ typedef enum {
|
|||
CSERVE2_FONT_GLYPHS_USED,
|
||||
CSERVE2_STATS,
|
||||
CSERVE2_FONT_DEBUG,
|
||||
CSERVE2_INDEX_LIST,
|
||||
CSERVE2_ERROR
|
||||
} Message_Type;
|
||||
|
||||
|
@ -224,7 +225,7 @@ struct _Msg_Stats {
|
|||
} images;
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* @struct _Msg_Font_Debug
|
||||
*
|
||||
* Message from server containing all font cache info.
|
||||
|
@ -262,6 +263,70 @@ struct _Msg_Font_Debug {
|
|||
Msg_Base base;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The Msg_Index_List struct
|
||||
*
|
||||
* Message sent from the server, without request from the client,
|
||||
* to inform all clients of the shared index files. Contains the paths
|
||||
* to the latest File, Image and Font index shm.
|
||||
*
|
||||
* The paths contain only the filename used in the call to shm_open.
|
||||
* All strings must be null-terminated.
|
||||
*/
|
||||
struct _Msg_Index_List {
|
||||
Msg_Base base;
|
||||
char files_index_path[64];
|
||||
char images_index_path[64];
|
||||
char fonts_index_path[64];
|
||||
};
|
||||
|
||||
typedef struct _Shm_Object Shm_Object;
|
||||
typedef struct _File_Data File_Data;
|
||||
typedef struct _Image_Data Image_Data;
|
||||
typedef struct _Shared_Array_Header Shared_Array_Header;
|
||||
typedef int string_t;
|
||||
#define SHMOBJECT unsigned int id; unsigned int refcount
|
||||
|
||||
struct _Shared_Array_Header
|
||||
{
|
||||
int32_t tag;
|
||||
int32_t elemsize;
|
||||
int32_t count;
|
||||
int32_t generation_id;
|
||||
int32_t emptyidx;
|
||||
int32_t sortedidx;
|
||||
int32_t _reserved1;
|
||||
int32_t _reserved2;
|
||||
};
|
||||
|
||||
struct _Shm_Object
|
||||
{
|
||||
SHMOBJECT;
|
||||
};
|
||||
|
||||
struct _File_Data {
|
||||
SHMOBJECT;
|
||||
string_t path;
|
||||
string_t key;
|
||||
string_t loader_data;
|
||||
int w, h;
|
||||
int frame_count;
|
||||
int loop_count;
|
||||
int loop_hint;
|
||||
Eina_Bool alpha : 1;
|
||||
Eina_Bool invalid : 1;
|
||||
};
|
||||
|
||||
struct _Image_Data {
|
||||
SHMOBJECT;
|
||||
unsigned int file_id;
|
||||
string_t shm_id;
|
||||
Evas_Image_Load_Opts opts;
|
||||
Eina_Bool alpha_sparse : 1;
|
||||
Eina_Bool unused : 1;
|
||||
Eina_Bool doload : 1;
|
||||
};
|
||||
|
||||
struct _Msg_Error {
|
||||
Msg_Base base;
|
||||
int error;
|
||||
|
@ -282,6 +347,7 @@ typedef struct _Msg_Font_Glyphs_Loaded Msg_Font_Glyphs_Loaded;
|
|||
typedef struct _Msg_Stats Msg_Stats;
|
||||
typedef struct _Msg_Font_Debug Msg_Font_Debug;
|
||||
typedef struct _Msg_Error Msg_Error;
|
||||
typedef struct _Msg_Index_List Msg_Index_List;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -42,6 +42,10 @@ static unsigned int _data_id = 0;
|
|||
|
||||
static Eina_List *_requests = NULL;
|
||||
|
||||
// Shared index table
|
||||
static Index_Table _index;
|
||||
static int _server_index_list_set(Msg_Base *data, int size);
|
||||
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX sizeof(((struct sockaddr_un *)NULL)->sun_path)
|
||||
#endif
|
||||
|
@ -279,6 +283,8 @@ evas_cserve2_init(void)
|
|||
if (cserve2_init++)
|
||||
return cserve2_init;
|
||||
|
||||
memset(&_index, 0, sizeof(_index));
|
||||
|
||||
DBG("Connecting to cserve2.");
|
||||
if (!_server_connect())
|
||||
{
|
||||
|
@ -292,10 +298,13 @@ evas_cserve2_init(void)
|
|||
int
|
||||
evas_cserve2_shutdown(void)
|
||||
{
|
||||
const char zeros[sizeof(Msg_Index_List)] = {0};
|
||||
|
||||
if ((--cserve2_init) > 0)
|
||||
return cserve2_init;
|
||||
|
||||
DBG("Disconnecting from cserve2.");
|
||||
_server_index_list_set((Msg_Base *) zeros, sizeof(Msg_Index_List));
|
||||
_server_disconnect();
|
||||
|
||||
return cserve2_init;
|
||||
|
@ -316,6 +325,123 @@ _next_rid(void)
|
|||
return _rid_count++;
|
||||
}
|
||||
|
||||
// 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;
|
||||
unsigned sz;
|
||||
int ret = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Reset index table
|
||||
if (_index.files.f)
|
||||
{
|
||||
if (_index.files.header)
|
||||
eina_file_map_free(_index.files.f, (void *) _index.files.header);
|
||||
eina_file_close(_index.files.f);
|
||||
}
|
||||
if (_index.images.f)
|
||||
{
|
||||
if (_index.images.header)
|
||||
eina_file_map_free(_index.images.f, (void *) _index.images.header);
|
||||
eina_file_close(_index.images.f);
|
||||
}
|
||||
if (_index.fonts.f)
|
||||
{
|
||||
if (_index.fonts.header)
|
||||
eina_file_map_free(_index.fonts.f, (void *) _index.fonts.header);
|
||||
eina_file_close(_index.fonts.f);
|
||||
}
|
||||
memset(&_index, 0, sizeof(_index));
|
||||
|
||||
// Open new indexes
|
||||
eina_strlcpy(_index.files.path, msg->files_index_path, 64);
|
||||
eina_strlcpy(_index.images.path, msg->images_index_path, 64);
|
||||
eina_strlcpy(_index.fonts.path, msg->fonts_index_path, 64);
|
||||
|
||||
if (_index.files.path[0])
|
||||
{
|
||||
_index.files.f = eina_file_open(_index.files.path, EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.files.f);
|
||||
if (sz < sizeof(Shared_Array_Header))
|
||||
{
|
||||
ERR("Shared index for files is too small: %u", sz);
|
||||
eina_file_close(_index.files.f);
|
||||
_index.files.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.files.header = eina_file_map_all(_index.files.f,
|
||||
EINA_FILE_WILLNEED);
|
||||
if (sz < (_index.files.header->count * sizeof(File_Data)
|
||||
+ sizeof(Shared_Array_Header)))
|
||||
{
|
||||
ERR("Shared index size does not match array size: %u / %u",
|
||||
sz, _index.files.header->count);
|
||||
eina_file_map_free(_index.files.f,
|
||||
(void *) _index.files.header);
|
||||
eina_file_close(_index.files.f);
|
||||
_index.files.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.files.entries = (File_Data *) &(_index.files.header[1]);
|
||||
DBG("Mapped files shared index '%s' at %p: %u entries max",
|
||||
_index.files.path, _index.files.header,
|
||||
_index.files.header->count);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_index.images.path[0])
|
||||
{
|
||||
_index.images.f = eina_file_open(_index.images.path, EINA_TRUE);
|
||||
sz = eina_file_size_get(_index.images.f);
|
||||
if (sz < sizeof(Shared_Array_Header))
|
||||
{
|
||||
ERR("Shared index for images is too small: %u", sz);
|
||||
eina_file_close(_index.images.f);
|
||||
_index.images.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.images.header = eina_file_map_all(_index.images.f,
|
||||
EINA_FILE_WILLNEED);
|
||||
if (sz < (_index.images.header->count * sizeof(Image_Data)
|
||||
+ sizeof(Shared_Array_Header)))
|
||||
{
|
||||
ERR("Shared index size does not match array size: %u / %u",
|
||||
sz, _index.images.header->count);
|
||||
eina_file_map_free(_index.images.f,
|
||||
(void *) _index.images.header);
|
||||
eina_file_close(_index.images.f);
|
||||
_index.images.f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
_index.images.entries = (Image_Data *) &(_index.images.header[1]);
|
||||
DBG("Mapped images shared index '%s' at %p: %u entries max",
|
||||
_index.images.path, _index.images.header,
|
||||
_index.images.header->count);
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_index.fonts.path[0])
|
||||
ERR("Not implemented yet: fonts shared index");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
_server_dispatch(Eina_Bool *failed)
|
||||
{
|
||||
|
@ -333,6 +459,17 @@ _server_dispatch(Eina_Bool *failed)
|
|||
}
|
||||
*failed = EINA_FALSE;
|
||||
|
||||
// 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
|
||||
EINA_LIST_FOREACH_SAFE(_requests, l, l_next, cr)
|
||||
{
|
||||
if (cr->rid != msg->rid) // dispatch this answer
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define EVAS_CS2_PRIVATE_H 1
|
||||
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_cs2.h"
|
||||
|
||||
struct _Data_Entry {
|
||||
unsigned int image_id;
|
||||
|
@ -17,8 +18,30 @@ struct _Data_Entry {
|
|||
} shm;
|
||||
};
|
||||
|
||||
struct _Index_Table {
|
||||
struct {
|
||||
char path[64];
|
||||
Eina_File *f;
|
||||
const Shared_Array_Header *header;
|
||||
const File_Data *entries;
|
||||
} files;
|
||||
struct {
|
||||
char path[64];
|
||||
Eina_File *f;
|
||||
const Shared_Array_Header *header;
|
||||
const Image_Data *entries;
|
||||
} images;
|
||||
struct {
|
||||
char path[64];
|
||||
Eina_File *f;
|
||||
const Shared_Array_Header *header;
|
||||
const void *entries; // FIXME
|
||||
} fonts;
|
||||
};
|
||||
|
||||
typedef struct _Data_Entry Data_Entry;
|
||||
typedef struct _Font_Entry Font_Entry;
|
||||
typedef struct _Index_Table Index_Table;
|
||||
|
||||
int evas_cserve2_init(void);
|
||||
int evas_cserve2_shutdown(void);
|
||||
|
|
Loading…
Reference in New Issue