summaryrefslogtreecommitdiff
path: root/content/fs_backing_store.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-11-19 16:22:06 +0000
committerVincent Sanders <vince@kyllikki.org>2014-11-19 16:22:06 +0000
commit92a1ac4fbbb2d3046cd6f27364e09f765bc2bf49 (patch)
tree4479609fd670ce7d31cadd68d5ef867e05f55877 /content/fs_backing_store.c
parenta79b30bd6ffff03a2246d6e1d40548a77a1d14b4 (diff)
downloadnetsurf-92a1ac4fbbb2d3046cd6f27364e09f765bc2bf49.tar.gz
netsurf-92a1ac4fbbb2d3046cd6f27364e09f765bc2bf49.tar.bz2
Improve backing store control data serialisation
By scheduling the control data to be maintained (entries index written and headers updated) once activity occurs to update these control structures rather than a single serialisation at browser exit the data is more likely to be up to date and not lost on a crash.
Diffstat (limited to 'content/fs_backing_store.c')
-rw-r--r--content/fs_backing_store.c150
1 files changed, 90 insertions, 60 deletions
diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c
index 012422048..83bd2a923 100644
--- a/content/fs_backing_store.c
+++ b/content/fs_backing_store.c
@@ -44,6 +44,8 @@
#include "utils/log.h"
#include "utils/utils.h"
#include "utils/messages.h"
+#include "desktop/gui_internal.h"
+#include "desktop/gui_misc.h"
#include "content/backing_store.h"
@@ -56,6 +58,9 @@
/** Backing store file format version */
#define CONTROL_VERSION 110
+/** Number of milliseconds after a update before control data maintinance is performed */
+#define CONTROL_MAINT_TIME 10000
+
/** Get address from ident */
#define BS_ADDRESS(ident, state) ((ident) & ((1 << state->ident_bits) - 1))
@@ -470,6 +475,86 @@ static nserror store_evict(struct store_state *state)
/**
+ * Write filesystem entries to file.
+ *
+ * Serialise entry index out to storage.
+ *
+ * @param state The backing store state to serialise.
+ * @return NSERROR_OK on sucess or error code on faliure.
+ */
+static nserror write_entries(struct store_state *state)
+{
+ int fd;
+ char *tname = NULL; /* temporary file name for atomic replace */
+ char *fname = NULL; /* target filename */
+ size_t entries_size;
+ size_t written;
+ nserror ret;
+
+ if (state->entries_dirty == false) {
+ /* entries have not been updated since last write */
+ return NSERROR_OK;
+ }
+
+ ret = netsurf_mkpath(&tname, NULL, 2, state->path, "t"ENTRIES_FNAME);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ fd = open(tname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ free(tname);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ entries_size = state->last_entry * sizeof(struct store_entry);
+
+ written = (size_t)write(fd, state->entries, entries_size);
+
+ close(fd);
+
+ /* check all data was written */
+ if (written != entries_size) {
+ unlink(tname);
+ free(tname);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
+ if (ret != NSERROR_OK) {
+ unlink(tname);
+ free(tname);
+ return ret;
+ }
+
+ if (rename(tname, fname) != 0) {
+ unlink(tname);
+ free(tname);
+ free(fname);
+ return NSERROR_SAVE_FAILED;
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * maintinance of control structures.
+ *
+ * callback scheduled when control data has been update. Currently
+ * this is for when the entries table is dirty and requires
+ * serialising.
+ *
+ * \param s store state to maintain.
+ */
+static void control_maintinance(void *s)
+{
+ struct store_state *state = s;
+
+ write_entries(state);
+}
+
+
+/**
* Lookup a backing store entry in the entry table from a url.
*
* This finds the store entry associated with the given
@@ -512,6 +597,8 @@ get_store_entry(struct store_state *state, nsurl *url, struct store_entry **bse)
state->entries_dirty = true;
+ guit->browser->schedule(CONTROL_MAINT_TIME, control_maintinance, state);
+
return NSERROR_OK;
}
@@ -603,6 +690,8 @@ set_store_entry(struct store_state *state,
state->entries_dirty = true;
+ guit->browser->schedule(CONTROL_MAINT_TIME, control_maintinance, state);
+
*bse = se;
return NSERROR_OK;
@@ -700,68 +789,8 @@ build_entrymap(struct store_state *state)
return NSERROR_OK;
}
-/**
- * Write filesystem entries to file.
- *
- * Serialise entry index out to storage.
- *
- * @param state The backing store state to serialise.
- * @return NSERROR_OK on sucess or error code on faliure.
- */
-static nserror write_entries(struct store_state *state)
-{
- int fd;
- char *tname = NULL; /* temporary file name for atomic replace */
- char *fname = NULL; /* target filename */
- size_t entries_size;
- size_t written;
- nserror ret;
-
- if (state->entries_dirty == false) {
- /* entries have not been updated since last write */
- return NSERROR_OK;
- }
- ret = netsurf_mkpath(&tname, NULL, 2, state->path, "t"ENTRIES_FNAME);
- if (ret != NSERROR_OK) {
- return ret;
- }
- fd = open(tname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- if (fd == -1) {
- free(tname);
- return NSERROR_SAVE_FAILED;
- }
-
- entries_size = state->last_entry * sizeof(struct store_entry);
-
- written = (size_t)write(fd, state->entries, entries_size);
-
- close(fd);
-
- /* check all data was written */
- if (written != entries_size) {
- unlink(tname);
- free(tname);
- return NSERROR_SAVE_FAILED;
- }
-
- ret = netsurf_mkpath(&fname, NULL, 2, state->path, ENTRIES_FNAME);
- if (ret != NSERROR_OK) {
- unlink(tname);
- free(tname);
- return ret;
- }
-
- if (rename(tname, fname) != 0) {
- unlink(tname);
- free(tname);
- free(fname);
- return NSERROR_SAVE_FAILED;
- }
-
- return NSERROR_OK;
-}
/**
* Read description entries into memory.
@@ -1087,6 +1116,7 @@ static nserror
finalise(void)
{
if (storestate != NULL) {
+ guit->browser->schedule(-1, control_maintinance, storestate);
write_entries(storestate);
/* avoid division by zero */