summaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2014-11-27 13:31:43 +0000
committerVincent Sanders <vince@kyllikki.org>2014-11-27 13:31:43 +0000
commit8d51dd4879e5e0812fd440d7370fdeabf8bfde55 (patch)
tree17f98b4a76c4633e584e14e3b068f6f84eafe437 /content
parent79d5b1bf3bfebdc96ad717b0ebf1d9bc62182b0b (diff)
downloadnetsurf-8d51dd4879e5e0812fd440d7370fdeabf8bfde55.tar.gz
netsurf-8d51dd4879e5e0812fd440d7370fdeabf8bfde55.tar.bz2
update the backing store to allow for invalidating entries which have an allocation
Diffstat (limited to 'content')
-rw-r--r--content/fs_backing_store.c112
-rw-r--r--content/llcache.c6
2 files changed, 69 insertions, 49 deletions
diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c
index 08a1ddd23..34bb149ec 100644
--- a/content/fs_backing_store.c
+++ b/content/fs_backing_store.c
@@ -119,6 +119,13 @@ enum store_entry_elem_flags {
};
+enum store_entry_flags {
+ /** entry is normal */
+ ENTRY_FLAGS_NONE = 0,
+ /** entry has been invalidated but something still holding a reference */
+ ENTRY_FLAGS_INVALID = 1,
+};
+
/**
* Backing store entry element.
*
@@ -156,6 +163,7 @@ struct store_entry {
int64_t last_used; /**< unix time the entry was last used */
entry_ident_t ident; /**< entry identifier */
uint16_t use_count; /**< number of times this entry has been accessed */
+ uint8_t flags; /**< entry flags */
/** Entry element (data or meta) specific information */
struct store_entry_element elem[ENTRY_ELEM_COUNT];
};
@@ -211,50 +219,25 @@ struct store_state *storestate;
* removes it from the table. The removed entry is returned but is
* only valid until the next set_store_entry call.
*
- * @param state The store state to use.
- * @param ident The entry ident of the entry to store.
- * @param bse Pointer used to return value.
- * @return NSERROR_OK and bse updated on succes or NSERROR_NOT_FOUND
+ * @param[in] state The store state to use.
+ * @param[in, out] bse Pointer to the entry to be removed.
+ * @return NSERROR_OK and \a bse updated on succes or NSERROR_NOT_FOUND
* if no entry coresponds to the url.
*/
static nserror
-remove_store_entry(struct store_state *state,
- entry_ident_t ident,
- struct store_entry **bse)
+remove_store_entry(struct store_state *state, struct store_entry **bse)
{
entry_index_t sei; /* store entry index */
- sei = BS_ENTRY_INDEX(ident, state);
- if (sei == 0) {
- LOG(("ident 0x%08x not in index", ident));
- return NSERROR_NOT_FOUND;
- }
-
- if (state->entries[sei].ident != ident) {
- /* entry ident did not match */
- LOG(("ident 0x%08x did not match entry index %d", ident, sei));
- return NSERROR_NOT_FOUND;
- }
-
- /* check if the entry has storage already allocated */
- if (((state->entries[sei].elem[ENTRY_ELEM_DATA].flags &
- (ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP)) != 0) ||
- ((state->entries[sei].elem[ENTRY_ELEM_META].flags &
- (ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP)) != 0)) {
- /* this entry cannot be removed as it has associated
- * allocation.
- */
- LOG(("attempt to remove entry with in use data"));
- return NSERROR_PERMISSION;
- }
-
- /* sei is entry to be removed, we swap it to the end of the
- * table so there are no gaps and the returned entry is held
- * in storage with reasonable lifetime.
+ /* sei is index to entry to be removed, we swap it to the end
+ * of the table so there are no gaps and the returned entry is
+ * held in storage with reasonable lifetime.
*/
+ sei = BS_ENTRY_INDEX((*bse)->ident, state);
+
/* remove entry from map */
- BS_ENTRY_INDEX(ident, state) = 0;
+ BS_ENTRY_INDEX((*bse)->ident, state) = 0;
/* global allocation accounting */
state->total_alloc -= state->entries[sei].elem[ENTRY_ELEM_DATA].size;
@@ -408,21 +391,34 @@ store_fname(struct store_state *state,
* @return NSERROR_OK on sucess or error code on failure.
*/
static nserror
-unlink_ident(struct store_state *state, entry_ident_t ident)
+invalidate_entry(struct store_state *state, struct store_entry *bse)
{
char *fname;
nserror ret;
- struct store_entry *bse;
- /* LOG(("ident %08x", ident)); */
+ /* mark entry as invalid */
+ bse->flags |= ENTRY_FLAGS_INVALID;
- /* use the url hash as the entry identifier */
- ret = remove_store_entry(state, ident, &bse);
+ /* check if the entry has storage already allocated */
+ if (((bse->elem[ENTRY_ELEM_DATA].flags &
+ (ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP)) != 0) ||
+ ((bse->elem[ENTRY_ELEM_META].flags &
+ (ENTRY_ELEM_FLAG_HEAP | ENTRY_ELEM_FLAG_MMAP)) != 0)) {
+ /*
+ * This entry cannot be immediately removed as it has
+ * associated allocation so wait for allocation release.
+ */
+ LOG(("invalidating entry with referenced allocation"));
+ return NSERROR_OK;
+ }
+
+ /* remove the entry from the index */
+ ret = remove_store_entry(state, &bse);
if (ret != NSERROR_OK) {
- /* LOG(("entry not found")); */
return ret;
}
+ /* unlink the files from disc */
fname = store_fname(state, bse->ident, BACKING_STORE_META);
if (fname == NULL) {
return NSERROR_NOMEM;
@@ -535,11 +531,14 @@ static nserror store_evict(struct store_state *state)
/* evict entries in listed order */
removed = 0;
for (ent = 0; ent < ent_count; ent++) {
+ struct store_entry *bse;
+
+ bse = &BS_ENTRY(elist[ent], state);
- removed += BS_ENTRY(elist[ent], state).elem[ENTRY_ELEM_DATA].size;
- removed += BS_ENTRY(elist[ent], state).elem[ENTRY_ELEM_META].size;
+ removed += bse->elem[ENTRY_ELEM_DATA].size;
+ removed += bse->elem[ENTRY_ELEM_META].size;
- ret = unlink_ident(state, elist[ent]);
+ ret = invalidate_entry(state, bse);
if (ret != NSERROR_OK) {
break;
}
@@ -760,7 +759,7 @@ set_store_entry(struct store_state *state,
/* this entry cannot be removed as it has associated
* allocation.
*/
- LOG(("attempt to remove entry with in use data"));
+ LOG(("attempt to overwrite entry with in use data"));
return NSERROR_PERMISSION;
}
@@ -1465,7 +1464,18 @@ static nserror release(nsurl *url, enum backing_store_flags bsflags)
elem = &bse->elem[ENTRY_ELEM_DATA];
}
- return entry_release_alloc(elem);
+ ret = entry_release_alloc(elem);
+
+ /* if the entry has previously been invalidated but had
+ * allocation it must be invalidated fully now the allocation
+ * has been released.
+ */
+ if ((ret == NSERROR_OK) &&
+ ((bse->flags & ENTRY_FLAGS_INVALID) != 0)) {
+ ret = invalidate_entry(storestate, bse);
+ }
+
+ return ret;
}
@@ -1481,14 +1491,20 @@ static nserror release(nsurl *url, enum backing_store_flags bsflags)
static nserror
invalidate(nsurl *url)
{
+ nserror ret;
+ struct store_entry *bse;
+
/* check backing store is initialised */
if (storestate == NULL) {
return NSERROR_INIT_FAILED;
}
- LOG(("url:%s", nsurl_access(url)));
+ ret = get_store_entry(storestate, url, &bse);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
- return unlink_ident(storestate, nsurl_hash(url));
+ return invalidate_entry(storestate, bse);
}
diff --git a/content/llcache.c b/content/llcache.c
index 3c46a6d22..5defb1121 100644
--- a/content/llcache.c
+++ b/content/llcache.c
@@ -2300,10 +2300,13 @@ build_candidate_list(struct llcache_object ***lst_out, int *lst_len_out)
*
* \param object The object to put in the backing store.
* \param written_out The amount of data written out.
+ * \param elapsed The time in ms it took to complete the write to backing store.
* \return NSERROR_OK on success or appropriate error code.
*/
static nserror
-write_backing_store(struct llcache_object *object, size_t *written_out, unsigned long *elapsed)
+write_backing_store(struct llcache_object *object,
+ size_t *written_out,
+ unsigned long *elapsed)
{
nserror ret;
uint8_t *metadata;
@@ -2388,6 +2391,7 @@ static void llcache_persist(void *p)
}
total_written += size_written;
total_elapsed += elapsed;
+ LOG(("Wrote %d bytes in %dms %s", size_written, total_elapsed, nsurl_access(lst[idx]->url) ));
if (total_written > llcache->bandwidth) {
/* The bandwidth limit has been reached.