#include "evas_cserve2.h"
#include "evas_cs2_utils.h"
-typedef struct _Request_Funcs Request_Funcs;
-typedef struct _Request Request;
-
typedef struct _Entry Entry;
typedef struct _Reference Reference;
-typedef struct _Waiter Waiter;
typedef struct _File_Data File_Data;
typedef struct _Image_Data Image_Data;
typedef struct _File_Watch File_Watch;
typedef struct _Font_Entry Font_Entry;
typedef struct _Font_Cache Font_Cache;
-typedef void *(*Request_Msg_Create)(Entry *e, int *size);
-typedef void (*Request_Response)(Entry *e, void *resp);
-typedef void (*Request_Error)(Entry *e, Error_Type error);
-
-struct _Request_Funcs {
- Request_Msg_Create msg_create;
- Request_Response response;
- Request_Error error;
-};
-
-struct _Request {
- Entry *entry;
- Eina_List *waiters;
- Eina_Bool processing;
- Request_Funcs *funcs;
-};
-
typedef enum {
CSERVE2_IMAGE_FILE,
CSERVE2_IMAGE_DATA,
struct _Entry {
unsigned int id;
Eina_List *references;
- Request *request;
+ Font_Request *request;
Entry_Type type;
#ifdef DEBUG_LOAD_TIME
struct timeval load_start;
int count;
};
-struct _Waiter {
- Reference *ref;
- unsigned int rid;
- Message_Type type;
-};
-
struct _File_Watch {
const char *path;
Eina_List *entries;
};
-static Eina_List *open_requests = NULL;
-static Eina_List *load_requests = NULL;
-static Eina_List *spload_requests = NULL; // speculative preload requests
-
static unsigned int _file_id = 0; // id unique number
static unsigned int _image_id = 0; // id unique number
static Eina_Hash *file_ids = NULL; // maps path + key --> file_id
#endif
}
+static Msg_Opened *
+_image_opened_msg_create(File_Data *entry, int *size)
+{
+ Msg_Opened *msg;
+
+ msg = calloc(1, sizeof(*msg));
+ msg->base.type = CSERVE2_OPENED;
+ msg->image.w = entry->w;
+ msg->image.h = entry->h;
+ msg->image.frame_count = entry->frame_count;
+ msg->image.loop_count = entry->loop_count;
+ msg->image.loop_hint = entry->loop_hint;
+ msg->image.alpha = entry->alpha;
+
+ *size = sizeof(*msg);
+
+ return msg;
+}
+
static void
_image_opened_send(Client *client, File_Data *entry, unsigned int rid)
{
int size;
- Msg_Opened msg;
+ Msg_Opened *msg;
DBG("Sending OPENED reply for entry: %d and RID: %d.", entry->base.id, rid);
// clear the struct with possible paddings, since it is not aligned.
- memset(&msg, 0, sizeof(msg));
- msg.base.rid = rid;
- msg.base.type = CSERVE2_OPENED;
- msg.image.w = entry->w;
- msg.image.h = entry->h;
- msg.image.frame_count = entry->frame_count;
- msg.image.loop_count = entry->loop_count;
- msg.image.loop_hint = entry->loop_hint;
- msg.image.alpha = entry->alpha;
-
- size = sizeof(msg);
+
+ msg = _image_opened_msg_create(entry, &size);
+ msg->base.rid = rid;
+
cserve2_client_send(client, &size, sizeof(size));
- cserve2_client_send(client, &msg, sizeof(msg));
- // _cserve2_cache_load_requests_process();
+ cserve2_client_send(client, msg, size);
+
+ free(msg);
}
-static void
-_image_loaded_send(Client *client, Image_Data *entry, unsigned int rid)
+static Msg_Loaded *
+_image_loaded_msg_create(Image_Data *entry, int *size)
{
- int size;
+ Msg_Loaded *msg;
const char *shmpath = cserve2_shm_name_get(entry->shm);
- Msg_Loaded msg;
int path_len;
char *buf;
- DBG("Sending LOADED reply for entry %d and RID: %d.", entry->base.id, rid);
path_len = strlen(shmpath) + 1;
- memset(&msg, 0, sizeof(msg));
- msg.base.rid = rid;
- msg.base.type = CSERVE2_LOADED;
+ *size = sizeof(*msg) + path_len;
+ msg = calloc(1, *size);
+ msg->base.type = CSERVE2_LOADED;
- msg.shm.mmap_offset = cserve2_shm_map_offset_get(entry->shm);
- msg.shm.use_offset = cserve2_shm_offset_get(entry->shm);
- msg.shm.mmap_size = cserve2_shm_map_size_get(entry->shm);
- msg.shm.image_size = cserve2_shm_size_get(entry->shm);
- msg.alpha_sparse = entry->alpha_sparse;
+ msg->shm.mmap_offset = cserve2_shm_map_offset_get(entry->shm);
+ msg->shm.use_offset = cserve2_shm_offset_get(entry->shm);
+ msg->shm.mmap_size = cserve2_shm_map_size_get(entry->shm);
+ msg->shm.image_size = cserve2_shm_size_get(entry->shm);
+ msg->alpha_sparse = entry->alpha_sparse;
- buf = malloc(sizeof(msg) + path_len);
-
- memcpy(buf, &msg, sizeof(msg));
- memcpy(buf + sizeof(msg), shmpath, path_len);
-
- size = sizeof(msg) + path_len;
-
- cserve2_client_send(client, &size, sizeof(size));
- cserve2_client_send(client, buf, size);
+ buf = (char *)msg + sizeof(*msg);
+ memcpy(buf, shmpath, path_len);
- free(buf);
+ return msg;
}
static void
-_image_preloaded_send(Client *client, unsigned int rid)
+_image_loaded_send(Client *client, Image_Data *entry, unsigned int rid)
{
int size;
- Msg_Preloaded msg;
+ Msg_Loaded *msg;
- DBG("Sending PRELOADED reply for RID: %d.", rid);
- memset(&msg, 0, sizeof(msg));
- msg.base.rid = rid;
- msg.base.type = CSERVE2_PRELOADED;
+ DBG("Sending LOADED reply for entry %d and RID: %d.", entry->base.id, rid);
+
+ msg = _image_loaded_msg_create(entry, &size);
+ msg->base.rid = rid;
- size = sizeof(msg);
cserve2_client_send(client, &size, sizeof(size));
- cserve2_client_send(client, &msg, size);
+ cserve2_client_send(client, msg, size);
+
+ free(msg);
}
static void
}
static void
-_request_failed(Entry *e, Error_Type type)
+_request_free(void *msg, void *data __UNUSED__)
{
- Waiter *w;
- Eina_List *l;
- Reference *ref;
-
- DBG("Request for entry %p failed with error %d", e, type);
- EINA_LIST_FREE(e->request->waiters, w)
- {
- cserve2_client_error_send(w->ref->client, w->rid, type);
-
- w->ref->count--;
- free(w);
- }
-
- EINA_LIST_FOREACH(e->references, l, ref)
- {
- Eina_Hash *hash = NULL;
- if (e->type == CSERVE2_IMAGE_FILE)
- hash = ref->client->files.referencing;
- else if (e->type == CSERVE2_IMAGE_DATA)
- hash = ref->client->images.referencing;
- else
- continue;
-
- eina_hash_del_by_key(hash, &(ref->client_entry_id));
- }
+ free(msg);
}
-static void
-_open_request_response(File_Data *e, Slave_Msg_Image_Opened *resp)
+static Msg_Opened *
+_open_request_response(File_Data *e, Slave_Msg_Image_Opened *resp, int *size)
{
- Waiter *w;
-
_entry_load_finish(&e->base);
+
+ e->base.request = NULL;
+
e->w = resp->w;
e->h = resp->h;
e->frame_count = resp->frame_count;
e->loader_data = eina_stringshare_add(ldata);
}
- DBG("Finished opening file %d. Notifying %d waiters.", e->base.id,
- e->base.request->waiters ? eina_list_count(e->base.request->waiters) : 0);
- EINA_LIST_FREE(e->base.request->waiters, w)
+ return _image_opened_msg_create(e, size);
+}
+
+static void
+_request_failed(Entry *e, Error_Type type __UNUSED__)
+{
+ Eina_List *l;
+ Reference *ref;
+
+ e->request = NULL;
+
+ EINA_LIST_FOREACH(e->references, l, ref)
{
- _image_opened_send(w->ref->client, e, w->rid);
- free(w);
+ Eina_Hash *hash = NULL;
+ if (e->type == CSERVE2_IMAGE_FILE)
+ hash = ref->client->files.referencing;
+ else if (e->type == CSERVE2_IMAGE_DATA)
+ hash = ref->client->images.referencing;
+ else
+ continue;
+
+ eina_hash_del_by_key(hash, &(ref->client_entry_id));
}
}
-static Request_Funcs _open_funcs = {
- .msg_create = (Request_Msg_Create)_open_request_build,
- .response = (Request_Response)_open_request_response,
- .error = (Request_Error)_request_failed
+static Font_Request_Funcs _open_funcs = {
+ .msg_create = (Font_Request_Msg_Create)_open_request_build,
+ .msg_free = _request_free,
+ .response = (Font_Request_Response)_open_request_response,
+ .error = (Font_Request_Error)_request_failed
};
static void *
return buf;
}
-static void
-_load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp)
+static Msg_Loaded *
+_load_request_response(Image_Data *e, Slave_Msg_Image_Loaded *resp, int *size)
{
- Waiter *w;
-
_entry_load_finish(&e->base);
+ e->base.request = NULL;
+
e->alpha_sparse = resp->alpha_sparse;
if (!e->doload)
DBG("Entry %d loaded by speculative preload.", e->base.id);
- DBG("Finished loading image %d. Notifying %d waiters.", e->base.id,
- e->base.request->waiters ? eina_list_count(e->base.request->waiters) : 0);
- EINA_LIST_FREE(e->base.request->waiters, w)
- {
- if (w->type == CSERVE2_LOAD)
- _image_loaded_send(w->ref->client, e, w->rid);
- else if (w->type == CSERVE2_PRELOAD)
- _image_preloaded_send(w->ref->client, w->rid);
- // else w->type == CSERVE2_SETOPTS --> do nothing
-
- free(w);
- }
+ return _image_loaded_msg_create(e, size);
}
-static Request_Funcs _load_funcs = {
- .msg_create = (Request_Msg_Create)_load_request_build,
- .response = (Request_Response)_load_request_response,
- .error = (Request_Error)_request_failed
+static Font_Request_Funcs _load_funcs = {
+ .msg_create = (Font_Request_Msg_Create)_load_request_build,
+ .msg_free = _request_free,
+ .response = (Font_Request_Response)_load_request_response,
+ .error = (Font_Request_Error)_request_failed
};
static unsigned int
File_Data *fentry = entry->file;
if (entry->base.request)
- {
- if (entry->base.request->processing)
- entry->base.request->entry = NULL;
- else if (!entry->base.request->waiters)
- {
- if (entry->doload)
- load_requests = eina_list_remove(load_requests,
- entry->base.request);
- else
- spload_requests = eina_list_remove(spload_requests,
- entry->base.request);
- }
- }
+ cserve2_request_cancel_all(entry->base.request, CSERVE2_REQUEST_CANCEL);
if (entry->unused)
{
}
if (entry->base.request)
- {
- if (entry->base.request->processing)
- entry->base.request->entry = NULL;
- else if (!entry->base.request->waiters)
- {
- open_requests = eina_list_remove(open_requests,
- entry->base.request);
- free(entry->base.request);
- }
- }
+ cserve2_request_cancel_all(entry->base.request, CSERVE2_REQUEST_CANCEL);
if ((fw = entry->watcher))
{
eina_hash_free(font_sources);
}
-static void
-_request_answer_del(Eina_List **requests, Request *req, Client *client, Error_Type err)
-{
- Eina_List *l, *l_next;
- Waiter *it;
-
- DBG("Removing answer requests from entry: %d, client: %d",
- req->entry->id, client->id);
-
- EINA_LIST_FOREACH_SAFE(req->waiters, l, l_next, it)
- {
- if (it->ref->client->id == client->id)
- {
- cserve2_client_error_send(client, it->rid, err);
- req->waiters = eina_list_remove_list(req->waiters, l);
- free(it);
- }
- }
-
- // FIXME: Should this be really here? I guess that it should be in the
- // entry_free_cb function, or entry_reference_del, when there are no more
- // references
- if (!req->entry && !req->waiters)
- {
- *requests = eina_list_remove(*requests, req);
- free(req);
- }
-}
-
-static void
-_request_answer_all_del(Eina_List **requests, Request *req, Error_Type err)
-{
- Waiter *it;
-
- DBG("Removing all answer requests from entry: %d", req->entry->id);
-
- EINA_LIST_FREE(req->waiters, it)
- {
- cserve2_client_error_send(it->ref->client, it->rid, err);
- free(it);
- }
-
- *requests = eina_list_remove(*requests, req);
- free(req);
-}
-
-static void
-_request_answer_add(Request *req, Reference *ref, unsigned int rid, Message_Type type)
-{
- Waiter *w = malloc(sizeof(*w));
-
- w->ref = ref;
- w->rid = rid;
- w->type = type;
-
- DBG("Add answer request for entry id: %d, client: %d, rid: %d",
- req->entry->id, ref->client->id, rid);
- req->waiters = eina_list_append(req->waiters, w);
-}
-
-static void
-_request_add(Eina_List **requests, Entry *entry, Reference *ref, unsigned int rid, Message_Type type)
-{
- Request *req;
-
- // add the request if it doesn't exist yet
- if (!entry->request)
- {
- req = malloc(sizeof(*req));
- req->entry = entry;
- req->waiters = NULL;
- req->processing = EINA_FALSE;
- entry->request = req;
- if (type == CSERVE2_OPEN)
- req->funcs = &_open_funcs;
- else
- req->funcs = &_load_funcs;
- *requests = eina_list_append(*requests, req);
- DBG("Add request for entry id: %d, client: %d, rid: %d",
- req->entry->id, ref->client->id, rid);
- }
- else
- req = entry->request;
-
- if (type != CSERVE2_SETOPTS)
- _request_answer_add(req, ref, rid, type);
- else
- DBG("Adding entry for speculative preload: id=%d", req->entry->id);
-}
-
static Reference *
_entry_reference_add(Entry *entry, Client *client, unsigned int client_entry_id)
{
return ref;
}
-static int
-_cserve2_cache_open_requests_process(int nloaders)
-{
- Request *req;
- char *slave_cmd_data;
- int slave_cmd_size;
-
- while ((nloaders > 0) && (open_requests))
- {
- // remove the first element from the list and process this element
- req = eina_list_data_get(open_requests);
- open_requests = eina_list_remove_list(open_requests, open_requests);
-
- DBG("Processing OPEN request for file entry: %d", req->entry->id);
-
- slave_cmd_data = req->funcs->msg_create(req->entry, &slave_cmd_size);
-
- cserve2_slave_cmd_dispatch(req, IMAGE_OPEN, slave_cmd_data,
- slave_cmd_size);
-
- free(slave_cmd_data);
-
- req->processing = EINA_TRUE;
- nloaders--;
- }
-
- return nloaders;
-}
-
-static int
-_cserve2_cache_load_requests_list_process(Eina_List **queue, int nloaders)
-{
- Eina_List *skipped = NULL;
- Request *req;
-
- while ((nloaders > 0) && (*queue))
- {
- Image_Data *ientry;
- char *buf;
- int size;
-
- // remove the first element from the list and process this element
- req = eina_list_data_get(*queue);
- *queue = eina_list_remove_list(*queue, *queue);
-
- ientry = (Image_Data *)req->entry;
- if (!ientry->file)
- {
- ERR("File entry doesn't exist for entry id %d", req->entry->id);
- _request_failed(req->entry, CSERVE2_INVALID_CACHE);
- continue;
- }
-
- if (ientry->file->base.request)
- {
- /* OPEN still pending, skip this request */
- skipped = eina_list_append(skipped, req);
- continue;
- }
-
- DBG("Processing LOAD request for image entry: %d", req->entry->id);
-
- buf = req->funcs->msg_create(req->entry, &size);
-
- cserve2_slave_cmd_dispatch(req, IMAGE_LOAD, buf, size);
-
- free(buf);
-
- req->processing = EINA_TRUE;
-
- nloaders--;
- }
-
- EINA_LIST_FREE(skipped, req)
- *queue = eina_list_append(*queue, req);
-
- return nloaders;
-}
-
-static void
-_cserve2_cache_load_requests_process(int nloaders)
-{
- nloaders = _cserve2_cache_load_requests_list_process(&load_requests,
- nloaders);
- _cserve2_cache_load_requests_list_process(&spload_requests, nloaders - 1);
-}
-
-
-void
-cserve2_cache_requests_process(void)
-{
- int avail_loaders;
-
- avail_loaders = cserve2_slave_available_get();
- avail_loaders = _cserve2_cache_open_requests_process(avail_loaders);
- _cserve2_cache_load_requests_process(avail_loaders);
-}
-
static void
_entry_unused_push(Image_Data *e)
{
entry = ref->entry;
- if (entry->request && !entry->request->processing)
+ /* XXX: handle the case of requests being processed gracefully */
+ if (entry->request /*&& !entry->request->processing*/)
{
if (entry->type == CSERVE2_IMAGE_FILE)
- _request_answer_del(&open_requests, entry->request, ref->client,
- CSERVE2_REQUEST_CANCEL);
+ cserve2_request_cancel(entry->request, ref->client,
+ CSERVE2_REQUEST_CANCEL);
else if (entry->type == CSERVE2_IMAGE_DATA)
- {
- if (((Image_Data *)entry)->doload)
- _request_answer_del(&load_requests, entry->request,
- ref->client, CSERVE2_REQUEST_CANCEL);
- else
- _request_answer_del(&spload_requests, entry->request,
- ref->client, CSERVE2_REQUEST_CANCEL);
- }
+ cserve2_request_cancel(entry->request, ref->client,
+ CSERVE2_REQUEST_CANCEL);
}
_entry_reference_del(entry, ref);
{
_image_id_free(ie);
eina_hash_set(image_entries, &ie->base.id, NULL);
- if (ie->base.request && !ie->base.request->processing)
- {
- if (ie->doload)
- _request_answer_all_del(&load_requests, ie->base.request,
- CSERVE2_FILE_CHANGED);
- else
- _request_answer_all_del(&spload_requests, ie->base.request,
- CSERVE2_FILE_CHANGED);
- }
+ if (ie->base.request /*&& !ie->base.request->processing*/)
+ cserve2_request_cancel_all(ie->base.request,
+ CSERVE2_FILE_CHANGED);
ie->base.request = NULL;
if (ie->unused)
_image_entry_free(ie);
_file_id_free(e);
eina_hash_set(file_entries, &e->base.id, NULL);
- if (e->base.request && !e->base.request->processing)
- _request_answer_all_del(&open_requests, e->base.request,
- CSERVE2_FILE_CHANGED);
+ if (e->base.request /*&& !e->base.request->processing*/)
+ cserve2_request_cancel_all(e->base.request, CSERVE2_FILE_CHANGED);
e->base.request = NULL;
if (!e->images && !e->base.references)
_file_entry_free(e);
msg->images.files_size += sizeof(File_Data) +
eina_list_count(fd->images) * sizeof(Eina_List *) +
eina_list_count(fd->base.references) *
- (sizeof(Request) + sizeof(Eina_List *));
+ (sizeof(Font_Request *) + sizeof(Eina_List *));
#ifdef DEBUG_LOAD_TIME
// accounting file entries load time
// File already being loaded, just add the request to be replied
if (entry->base.request)
- _request_answer_add(entry->base.request, ref, rid, CSERVE2_OPEN);
+ cserve2_request_waiter_add(entry->base.request, rid, client);
else
_image_opened_send(client, entry, rid);
return 0;
_entry_load_reused(ref->entry);
eina_hash_add(client->files.referencing, &client_file_id, ref);
if (entry->base.request)
- _request_answer_add(entry->base.request, ref, rid, CSERVE2_OPEN);
+ cserve2_request_waiter_add(entry->base.request, rid, client);
else // File already loaded, otherwise there would be a request
_image_opened_send(client, entry, rid);
return 0;
fw->entries = eina_list_append(fw->entries, entry);
entry->watcher = fw;
- _request_add(&open_requests, (Entry *)entry, ref, rid, CSERVE2_OPEN);
+ entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_OPEN,
+ rid, client, NULL, &_open_funcs,
+ entry);
// _open_image_default_set(entry);
fentry = entry->file;
fentry->images = eina_list_append(fentry->images, entry);
- _request_add(&spload_requests, (Entry *)entry, ref, msg->base.rid,
- CSERVE2_SETOPTS);
+ entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
+ 0, NULL, fentry->base.request,
+ &_load_funcs, entry);
return 0;
}
// File already being loaded, just add the request to be replied
if (entry->base.request)
{
- _request_answer_add(entry->base.request, ref, rid, CSERVE2_LOAD);
+ cserve2_request_waiter_add(entry->base.request, rid, client);
+ /* do this in *_requests.c. somehow
if ((!entry->base.request->processing) && (!entry->doload))
{
DBG("Removing entry %d from speculative preload and adding "
load_requests = eina_list_append(load_requests,
entry->base.request);
}
+ */
}
else if (entry->shm)
_image_loaded_send(client, entry, rid);
else
- _request_add(&load_requests, (Entry *)entry, ref, rid, CSERVE2_LOAD);
+ entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
+ rid, client,
+ entry->file->base.request,
+ &_load_funcs,
+ entry);
entry->doload = EINA_TRUE;
}
// File already being loaded, just add the request to be replied
if (entry->base.request)
{
- _request_answer_add(entry->base.request, ref, rid, CSERVE2_PRELOAD);
+ cserve2_request_waiter_add(entry->base.request, rid, client);
+ /* do this in *_requests.c. somehow
if ((!entry->base.request->processing) && (!entry->doload))
{
DBG("Removing entry %d from speculative preload and adding "
- "to normal (pre)load queue.", entry->base.id);
+ "to normal load queue.", entry->base.id);
spload_requests = eina_list_remove(spload_requests,
entry->base.request);
load_requests = eina_list_append(load_requests,
entry->base.request);
}
+ */
}
else if (entry->shm)
- _image_preloaded_send(client, rid);
+ _image_loaded_send(client, entry, rid);
else
- _request_add(&load_requests, (Entry *)entry, ref, rid, CSERVE2_PRELOAD);
+ entry->base.request = cserve2_request_add(CSERVE2_REQ_IMAGE_LOAD,
+ rid, client,
+ entry->file->base.request,
+ &_load_funcs,
+ entry);
entry->doload = EINA_TRUE;
}
}
void
-cserve2_cache_requests_response(Slave_Command type, void *msg, void *data)
-{
- Request *req = data;
-
- if (!req->entry)
- {
- Waiter *w;
- DBG("Request finished but it has no entry anymore.");
- EINA_LIST_FREE(req->waiters, w)
- {
- cserve2_client_error_send(w->ref->client, w->rid,
- CSERVE2_REQUEST_CANCEL);
-
- w->ref->count--;
- free(w);
- }
- }
- else if (type == ERROR)
- {
- Error_Type *error = msg;
- req->funcs->error(req->entry, *error);
- }
- else
- req->funcs->response(req->entry, msg);
-
- if (req->entry)
- req->entry->request = NULL;
- free(req);
-}
-
-void
cserve2_cache_stats_get(Client *client, unsigned int rid)
{
Msg_Stats msg;
#endif
#define CSERVE2_BIN_DEFAULT_COLOR EINA_COLOR_BLUE
-#define MAX_SLAVES 3
-
-struct _Slave_Worker {
- EINA_INLIST;
- void *data;
- Slave *slave;
- Eina_Binbuf *ret;
- int ret_size;
- Eina_Bool done;
- Eina_Bool delete_me;
-};
-
-typedef struct _Slave_Worker Slave_Worker;
-
int _evas_cserve2_bin_log_dom = -1;
static unsigned int _client_id = 0;
static Eina_Hash *client_list = NULL;
-static Eina_Inlist *slaves_idle = NULL;
-static Eina_Inlist *slaves_working = NULL;
void
cserve2_client_error_send(Client *client, unsigned int rid, int error_code)
}
static void
-_slave_dead_cb(Slave *s __UNUSED__, void *data)
-{
- Slave_Worker *sw = data;
-
- if (sw->delete_me)
- {
- DBG("Slave killed by cserve2. Restart routine.");
- free(sw);
- return;
- }
-
- if (!sw->data)
- {
- WRN("Slave died with no pending job, but not requested.");
- slaves_idle = eina_inlist_remove(slaves_idle, EINA_INLIST_GET(sw));
- free(sw);
- return;
- }
-
- slaves_working = eina_inlist_remove(slaves_working, EINA_INLIST_GET(sw));
- if (!sw->done)
- cserve2_cache_requests_response(ERROR, (Error_Type[]){ CSERVE2_LOADER_DIED }, sw->data);
- if (sw->ret)
- eina_binbuf_free(sw->ret);
- free(sw);
-}
-
-static void
-_slave_read_cb(Slave *s __UNUSED__, Slave_Command cmd, void *msg, void *data)
-{
- Slave_Worker *sw = data;
-
- DBG("Received reply command '%d' from slave '%p'", cmd, sw->slave);
- switch (cmd)
- {
- case IMAGE_OPEN:
- case IMAGE_LOAD:
- sw->done = EINA_TRUE;
- break;
- case ERROR:
- break;
- default:
- ERR("Unrecognized command received from slave: %d", cmd);
- }
- cserve2_cache_requests_response(cmd, msg, sw->data);
- free(msg);
-
- // slave finishes its work, put it back to idle list
- sw->data = NULL;
- slaves_working = eina_inlist_remove(slaves_working, EINA_INLIST_GET(sw));
-
- if (!sw->delete_me) // if it is being deleted, it shouldn't be in any list
- slaves_idle = eina_inlist_append(slaves_idle, EINA_INLIST_GET(sw));
-
- cserve2_cache_requests_process();
-}
-
-int
-cserve2_slave_available_get(void)
-{
- return MAX_SLAVES - eina_inlist_count(slaves_working);
-}
-
-Eina_Bool
-cserve2_slave_cmd_dispatch(void *data, Slave_Command cmd, const void *msg, int size)
-{
- Slave_Worker *sw;
- char *exe;
-
- DBG("Dispatching command to slave. %d idle slaves, %d working slaves.",
- eina_inlist_count(slaves_idle), eina_inlist_count(slaves_working));
-
- // first check if there's an available slave
- if (slaves_idle)
- {
- sw = EINA_INLIST_CONTAINER_GET(slaves_idle, Slave_Worker);
- slaves_idle = eina_inlist_remove(slaves_idle, slaves_idle);
- slaves_working = eina_inlist_append(slaves_working,
- EINA_INLIST_GET(sw));
-
- sw->data = data;
- sw->done = EINA_FALSE;
- DBG("Dispatching command '%d' to slave '%p'", cmd, sw->slave);
- cserve2_slave_send(sw->slave, cmd, msg, size);
- return EINA_TRUE;
- }
-
- // no available slave, start a new one
- sw = calloc(1, sizeof(Slave_Worker));
- if (!sw) return EINA_FALSE;
-
- sw->data = data;
- exe = getenv("EVAS_CSERVE2_SLAVE");
- if (!exe) exe = "evas_cserve2_slave";
- sw->slave = cserve2_slave_run(exe, _slave_read_cb, _slave_dead_cb, sw);
- if (!sw->slave)
- {
- ERR("Could not launch slave process");
- cserve2_cache_requests_response(ERROR, (Error_Type[]){ CSERVE2_LOADER_EXEC_ERR }, sw->data);
- free(sw);
- return EINA_FALSE;
- }
- DBG("Dispatching command '%d' to slave '%p'", cmd, sw->slave);
- cserve2_slave_send(sw->slave, cmd, msg, size);
-
- slaves_working = eina_inlist_append(slaves_working, EINA_INLIST_GET(sw));
-
- return EINA_TRUE;
-}
-
-static void
_cserve2_client_close(Client *client)
{
Msg_Close *msg = (Msg_Close *)client->msg.buf;
INF("Image_ID: %d\n", msg->image_id);
cserve2_cache_image_preload(client, msg->image_id, msg->base.rid);
- cserve2_cache_requests_process();
}
static void
INF("Image_ID: %d\n", msg->image_id);
cserve2_cache_image_load(client, msg->image_id, msg->base.rid);
- cserve2_cache_requests_process();
}
static void
msg->file_id, path, key);
cserve2_cache_file_open(client, msg->file_id, path, key, msg->base.rid);
- cserve2_cache_requests_process();
}
static void
}
}
-static void
-_slave_quit_send(Slave_Worker *sw)
-{
- cserve2_slave_send(sw->slave, SLAVE_QUIT, NULL, 0);
-}
-
-static void
-_slaves_restart(void)
-{
- Slave_Worker *list, *sw;
-
- while (slaves_idle) // remove idle workers from idle list
- {
- sw = EINA_INLIST_CONTAINER_GET(slaves_idle, Slave_Worker);
- slaves_idle = eina_inlist_remove(slaves_idle, slaves_idle);
- sw->delete_me = EINA_TRUE;
- _slave_quit_send(sw);
- }
-
- // working workers will be removed from the working list when they
- // finish processing their jobs
- list = EINA_INLIST_CONTAINER_GET(slaves_working, Slave_Worker);
- EINA_INLIST_FOREACH(list, sw)
- {
- sw->delete_me = EINA_TRUE;
- _slave_quit_send(sw);
- }
-}
-
-static void
-_timeout_cb(void)
-{
- static unsigned int slaves_restart = 0;
-
- slaves_restart++;
-
- if (slaves_restart == 10)
- {
- DBG("kill slaves");
- _slaves_restart();
- slaves_restart = 0;
- }
-
- cserve2_timeout_cb_set(3000, _timeout_cb);
-}
-
void
cserve2_client_accept(int fd)
{
_clients_setup();
- cserve2_timeout_cb_set(3000, _timeout_cb);
-
cserve2_main_loop_run();
_clients_finish();
cserve2_requests_shutdown();
- _slaves_restart();
cserve2_slaves_shutdown();
cserve2_main_loop_finish();