summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Young <chris@unsatisfactorysoftware.co.uk>2014-12-01 21:42:07 +0000
committerChris Young <chris@unsatisfactorysoftware.co.uk>2014-12-01 21:42:07 +0000
commit020e1f827241b23ea51017f015a224b7465fa347 (patch)
treef71a799538eceb804355ef5dc6a272bdbdb9eeee
parent2f41c1ad11e3cafc50922f5a67bca98fd91d5ef4 (diff)
downloadnetsurf-020e1f827241b23ea51017f015a224b7465fa347.tar.gz
netsurf-020e1f827241b23ea51017f015a224b7465fa347.tar.bz2
Run backing store jobs synchronously in the background.
-rw-r--r--amiga/fs_backing_store.c337
1 files changed, 313 insertions, 24 deletions
diff --git a/amiga/fs_backing_store.c b/amiga/fs_backing_store.c
index 2eee04bf7..95c1b09a6 100644
--- a/amiga/fs_backing_store.c
+++ b/amiga/fs_backing_store.c
@@ -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;
+};
+
+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_write_process(STRPTR args, int32 length, APTR execbase)
+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;
+
+ 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;
+ }
+ }
+ }
+ }
+ }
- filesystem_llcache_table->store(absw->url, absw->flags, absw->data, absw->datalen);
- FreeVec(absw);
+ 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(absm == NULL) return NSERROR_NOMEM;
+
+ absm->url = url;
+ absm->flags = flags;
+ absm->data = data;
+ absm->datalen = datalen;
+
+ return ami_backing_store_send(AMI_BSM_STORE, absm);
+}
+
+/**
+ * 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;
+
+ struct ami_bsm_fetch *absm =
+ AllocVecTagList(sizeof(struct ami_bsm_fetch), NULL);
+ if(absm == NULL) return NSERROR_NOMEM;
- if(absw == NULL) return NSERROR_NOMEM;
+ absm->url = url;
+ absm->bsflags = bsflags;
+ absm->data_out = data_out;
+ absm->datalen_out = datalen_out;
- absw->url = url;
- absw->flags = flags;
- absw->data = (uint8_t *)data;
- absw->datalen = datalen;
+ 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 write process",
- NP_Entry, ami_backing_store_write_process,
+ NP_Name, "NetSurf backing store",
+ NP_Entry, ami_backing_store_process,
NP_Child, TRUE,
NP_StackSize, 16384,
NP_Priority, -1,
- NP_UserData, absw,
+ NP_UserData, abs,
TAG_DONE);
if(proc == NULL) {
- FreeVec(absw);
return NSERROR_NOMEM;
}
- return NSERROR_OK;
-}
+ 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;