Run backing store jobs synchronously in the background.

This commit is contained in:
Chris Young 2014-12-01 21:42:07 +00:00
parent 2f41c1ad11
commit 020e1f8272

View File

@ -24,29 +24,169 @@
#include "content/fs_backing_store.c"
struct ami_backing_store_write {
struct ami_bsm_store {
nsurl *url;
enum backing_store_flags flags;
uint8_t *data;
size_t datalen;
};
struct ami_bsm_fetch {
nsurl *url;
enum backing_store_flags bsflags;
uint8_t **data_out;
size_t *datalen_out;
};
static int32 ami_backing_store_write_process(STRPTR args, int32 length, APTR execbase)
struct ami_bsm_invalidate {
nsurl *url;
};
struct ami_bsm_release {
nsurl *url;
enum backing_store_flags bsflags;
};
struct ami_backing_store {
struct MsgPort *msgport;
struct llcache_store_parameters *parameters;
};
struct ami_backing_store_msg {
struct Message msg;
int type;
nserror error;
void *data;
};
enum {
AMI_BSM_STARTUP = 0,
AMI_BSM_STORE,
AMI_BSM_FETCH,
AMI_BSM_INVALIDATE,
AMI_BSM_RELEASE,
AMI_BSM_FINALISE
};
struct MsgPort *cachemsgport = NULL;
static int32 ami_backing_store_process(STRPTR args, int32 length, APTR execbase)
{
struct Process *proc = (struct Process *)FindTask(NULL);
struct ami_backing_store_write *absw = proc->pr_Task.tc_UserData;
struct ami_backing_store *abs = proc->pr_Task.tc_UserData;
struct MsgPort *nsmsgport = abs->msgport;
struct MsgPort *backingstoremsgport = AllocSysObjectTags(ASOT_PORT, TAG_END);
bool running = true;
filesystem_llcache_table->store(absw->url, absw->flags, absw->data, absw->datalen);
FreeVec(absw);
nserror error = filesystem_llcache_table->initialise(abs->parameters);
/* Send a startup message to the message port we were given when we were created.
* This tells NetSurf where to send disk cache messages to, as well as informing
* that we are running.
*/
struct ami_backing_store_msg *absmsg = AllocSysObjectTags(ASOT_MESSAGE,
ASOMSG_Size, sizeof(struct ami_backing_store_msg),
ASOMSG_ReplyPort, backingstoremsgport,
TAG_END);
absmsg->type = AMI_BSM_STARTUP;
absmsg->error = error;
PutMsg(nsmsgport, (struct Message *)absmsg);
/* Main loop for this process */
while(running) {
WaitPort(backingstoremsgport);
while((absmsg = (struct ami_backing_store_msg *)GetMsg(backingstoremsgport))) {
if(absmsg->msg.mn_Node.ln_Type == NT_REPLYMSG) {
/* if it's a reply, free stuff */
FreeSysObject(ASOT_MESSAGE, absmsg);
} else {
if(running) {
switch(absmsg->type) {
case AMI_BSM_STORE:
{
struct ami_bsm_store *absm = absmsg->data;
absmsg->error = filesystem_llcache_table->store(absm->url, absm->flags, absm->data, absm->datalen);
FreeVec(absm);
FreeSysObject(ASOT_MESSAGE, absmsg); /* don't reply, just free */
}
break;
case AMI_BSM_FETCH:
{
struct ami_bsm_fetch *absm = absmsg->data;
absmsg->error = filesystem_llcache_table->fetch(absm->url, absm->bsflags, absm->data_out, absm->datalen_out);
ReplyMsg((struct Message *)absmsg); /* need to reply to this one */
}
break;
case AMI_BSM_INVALIDATE:
{
struct ami_bsm_invalidate *absm = absmsg->data;
absmsg->error = filesystem_llcache_table->invalidate(absm->url);
FreeVec(absm);
FreeSysObject(ASOT_MESSAGE, absmsg); /* don't reply, just free */
}
break;
case AMI_BSM_RELEASE:
{
struct ami_bsm_release *absm = absmsg->data;
absmsg->error = filesystem_llcache_table->release(absm->url, absm->bsflags);
FreeVec(absm);
FreeSysObject(ASOT_MESSAGE, absmsg); /* don't reply, just free */
}
break;
case AMI_BSM_FINALISE:
running = false;
absmsg->error = filesystem_llcache_table->finalise();
ReplyMsg((struct Message *)absmsg); /* need to reply to this one */
break;
default:
// unknown message
FreeSysObject(ASOT_MESSAGE, absmsg); /* don't reply, just free */
break;
}
}
}
}
}
FreeSysObject(ASOT_PORT, backingstoremsgport);
return RETURN_OK;
}
static nserror ami_backing_store_send_reply(int type, void *data, struct MsgPort *msgport)
{
if(cachemsgport == NULL) return NSERROR_INIT_FAILED;
struct ami_backing_store_msg *absmsg = AllocSysObjectTags(ASOT_MESSAGE,
ASOMSG_Size, sizeof(struct ami_backing_store_msg),
ASOMSG_ReplyPort, msgport,
TAG_END);
absmsg->type = type;
absmsg->data = data;
PutMsg(cachemsgport, (struct Message *)absmsg);
return NSERROR_OK;
}
static nserror ami_backing_store_send(int type, void *data)
{
return ami_backing_store_send_reply(type, data, NULL);
}
/**
* Place an object in the backing store.
* This implementation starts a new process and calls the core routine.
*
* @param url The url is used as the unique primary key for the data.
* @param flags The flags to control how the object is stored.
@ -57,48 +197,197 @@ static int32 ami_backing_store_write_process(STRPTR args, int32 length, APTR exe
static nserror
ami_backing_store_store(nsurl *url,
enum backing_store_flags flags,
const uint8_t *data,
uint8_t *data,
const size_t datalen)
{
struct ami_backing_store_write *absw =
AllocVecTagList(sizeof(struct ami_backing_store_write), NULL);
struct ami_bsm_store *absm =
AllocVecTagList(sizeof(struct ami_bsm_store), NULL);
if(absw == NULL) return NSERROR_NOMEM;
if(absm == NULL) return NSERROR_NOMEM;
absw->url = url;
absw->flags = flags;
absw->data = (uint8_t *)data;
absw->datalen = datalen;
absm->url = url;
absm->flags = flags;
absm->data = data;
absm->datalen = datalen;
struct Process *proc = CreateNewProcTags(
NP_Name, "NetSurf backing store write process",
NP_Entry, ami_backing_store_write_process,
NP_Child, TRUE,
NP_StackSize, 16384,
NP_Priority, -1,
NP_UserData, absw,
TAG_DONE);
return ami_backing_store_send(AMI_BSM_STORE, absm);
}
if(proc == NULL) {
FreeVec(absw);
return NSERROR_NOMEM;
}
/**
* Retrive an object from the backing store.
*
* @param[in] url The url is used as the unique primary key for the data.
* @param[in] bsflags The flags to control how the object is retrieved.
* @param[out] data_out The objects data.
* @param[out] datalen_out The length of the \a data retrieved.
* @return NSERROR_OK on success or error code on faliure.
*/
static nserror ami_backing_store_fetch(nsurl *url,
enum backing_store_flags bsflags,
uint8_t **data_out,
size_t *datalen_out)
{
struct MsgPort *tempmsgport = AllocSysObjectTags(ASOT_PORT, TAG_END);
if(tempmsgport == NULL) return NSERROR_NOMEM;
return NSERROR_OK;
struct ami_bsm_fetch *absm =
AllocVecTagList(sizeof(struct ami_bsm_fetch), NULL);
if(absm == NULL) return NSERROR_NOMEM;
absm->url = url;
absm->bsflags = bsflags;
absm->data_out = data_out;
absm->datalen_out = datalen_out;
nserror error = ami_backing_store_send_reply(AMI_BSM_FETCH, absm, tempmsgport);
if(error != NSERROR_OK) return error;
WaitPort(tempmsgport);
struct ami_backing_store_msg *absmsg = (struct ami_backing_store_msg *)GetMsg(tempmsgport);
error = absmsg->error;
FreeVec(absm);
FreeSysObject(ASOT_MESSAGE, absmsg);
FreeSysObject(ASOT_PORT, tempmsgport);
return error;
}
/**
* release a previously fetched or stored memory object.
*
* @param[in] url The url is used as the unique primary key to invalidate.
* @param[in] bsflags The flags to control how the object data is released.
* @return NSERROR_OK on success or error code on faliure.
*/
static nserror ami_backing_store_release(nsurl *url, enum backing_store_flags bsflags)
{
struct ami_bsm_release *absm =
AllocVecTagList(sizeof(struct ami_bsm_release), NULL);
if(absm == NULL) return NSERROR_NOMEM;
absm->url = url;
absm->bsflags = bsflags;
return ami_backing_store_send(AMI_BSM_RELEASE, absm);
}
/**
* Invalidate a source object from the backing store.
*
* The entry (if present in the backing store) must no longer
* be returned as a result to the fetch or meta operations.
*
* @param url The url is used as the unique primary key to invalidate.
* @return NSERROR_OK on success or error code on faliure.
*/
static nserror ami_backing_store_invalidate(nsurl *url)
{
struct ami_bsm_store *absm =
AllocVecTagList(sizeof(struct ami_bsm_invalidate), NULL);
if(absm == NULL) return NSERROR_NOMEM;
absm->url = url;
return ami_backing_store_send(AMI_BSM_INVALIDATE, absm);
}
/**
* Finalise the backing store.
*
* \todo This will cause the backing store to leak any outstanding memory
* allocations. This will probably best be done by a global use count.
*
* @return NSERROR_OK on success.
*/
static nserror ami_backing_store_finalise(void)
{
struct MsgPort *tempmsgport = AllocSysObjectTags(ASOT_PORT, TAG_END);
if(tempmsgport == NULL) return NSERROR_NOMEM;
nserror error = ami_backing_store_send_reply(AMI_BSM_FINALISE, NULL, tempmsgport);
if(error != NSERROR_OK) return error;
LOG(("Waiting for backing store process to exit..."));
WaitPort(tempmsgport);
struct ami_backing_store_msg *absmsg = (struct ami_backing_store_msg *)GetMsg(tempmsgport);
error = absmsg->error;
FreeSysObject(ASOT_MESSAGE, absmsg);
FreeSysObject(ASOT_PORT, tempmsgport);
cachemsgport = NULL;
return error;
}
/**
* Initialise the backing store.
*
* @param parameters to configure backing store.
* @return NSERROR_OK on success or error code on faliure.
*/
static nserror
ami_backing_store_initialise(const struct llcache_store_parameters *parameters)
{
struct MsgPort *tempmsgport = AllocSysObjectTags(ASOT_PORT, TAG_END);
struct ami_backing_store *abs =
AllocVecTagList(sizeof(struct ami_backing_store), NULL);
if(abs == NULL) return NSERROR_NOMEM;
abs->msgport = tempmsgport;
abs->parameters = (struct llcache_store_parameters *)parameters;
struct Process *proc = CreateNewProcTags(
NP_Name, "NetSurf backing store",
NP_Entry, ami_backing_store_process,
NP_Child, TRUE,
NP_StackSize, 16384,
NP_Priority, -1,
NP_UserData, abs,
TAG_DONE);
if(proc == NULL) {
return NSERROR_NOMEM;
}
LOG(("Waiting for backing store process to start up..."));
WaitPort(tempmsgport);
struct ami_backing_store_msg *msg = (struct ami_backing_store_msg *)GetMsg(tempmsgport);
cachemsgport = msg->msg.mn_ReplyPort;
nserror error = msg->error;
ReplyMsg((struct Message *)msg);
FreeSysObject(ASOT_PORT, tempmsgport);
LOG(("Backing store process started. Error code: %d", error));
return error;
}
static struct gui_llcache_table amiga_llcache_table = {
#ifdef NSA_NO_ASYNC_STORE
.initialise = initialise,
.finalise = finalise,
#ifdef NSA_NO_ASYNC_STORE
.store = store,
#else
.store = ami_backing_store_store,
#endif
.fetch = fetch,
.invalidate = invalidate,
.release = release,
#else
.initialise = ami_backing_store_initialise,
.finalise = ami_backing_store_finalise,
.store = ami_backing_store_store,
.fetch = ami_backing_store_fetch,
.invalidate = ami_backing_store_invalidate,
.release = ami_backing_store_release,
#endif
};
struct gui_llcache_table *amiga_filesystem_llcache_table = &amiga_llcache_table;