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:
Jean-Philippe Andre 2013-07-29 13:08:36 +09:00
parent c0bb73c775
commit 47be3a2b81
7 changed files with 267 additions and 53 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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);