diff --git a/content/hlcache.c b/content/hlcache.c index 49cceb0a2..1fd6fe4ad 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -87,6 +87,67 @@ static void hlcache_content_callback(struct content *c, * Public API * ******************************************************************************/ +/* See hlcache.h for documentation */ +void hlcache_finalise(void) +{ + uint32_t num_contents, prev_contents; + hlcache_entry *entry; + hlcache_retrieval_ctx *ctx, *next; + + /* Obtain initial count of contents remaining */ + for (num_contents = 0, entry = hlcache_content_list; + entry != NULL; entry = entry->next) { + num_contents++; + } + + /* Drain cache */ + do { + prev_contents = num_contents; + + hlcache_clean(); + + for (num_contents = 0, entry = hlcache_content_list; + entry != NULL; entry = entry->next) { + num_contents++; + } + } while (num_contents > 0 && num_contents != prev_contents); + + LOG(("%d contents remaining:", num_contents)); + for (entry = hlcache_content_list; entry != NULL; entry = entry->next) { + hlcache_handle entry_handle = { entry, NULL, NULL }; + + if (entry->content != NULL) { + LOG((" %p : %s", entry, + content_get_url(&entry_handle))); + } else { + LOG((" %p", entry)); + } + } + + /* Clean up retrieval contexts */ + if (hlcache_retrieval_ctx_ring != NULL) { + do { + ctx = hlcache_retrieval_ctx_ring; + next = ctx->r_next; + + if (ctx->llcache != NULL) + llcache_handle_release(ctx->llcache); + + if (ctx->handle != NULL) + free(ctx->handle); + + if (ctx->child.charset != NULL) + free((char *) ctx->child.charset); + + free(ctx); + + ctx = next; + } while (ctx != hlcache_retrieval_ctx_ring); + + hlcache_retrieval_ctx_ring = NULL; + } +} + /* See hlcache.h for documentation */ nserror hlcache_poll(void) { @@ -304,11 +365,11 @@ void hlcache_clean(void) if (content_count_users(entry->content) != 0) continue; - /** \todo This is over-zealous: all unused contents will be - * immediately destroyed. Ideally, we want to purge all - * unused contents that are using stale source data, and - * enough fresh contents such that the cache fits in the - * configured cache size limit. + /** \todo This is over-zealous: all unused contents + * will be immediately destroyed. Ideally, we want to + * purge all unused contents that are using stale + * source data, and enough fresh contents such that + * the cache fits in the configured cache size limit. */ /* Remove entry from cache */ diff --git a/content/hlcache.h b/content/hlcache.h index afc755e42..5ed37203d 100644 --- a/content/hlcache.h +++ b/content/hlcache.h @@ -63,6 +63,11 @@ enum hlcache_retrieve_flag { HLCACHE_RETRIEVE_MAY_DOWNLOAD = (1 << 31) }; +/** + * Finalise the high-level cache, destroying any remaining contents + */ +void hlcache_finalise(void); + /** * Drive the low-level cache poll loop, and attempt to clean the cache. * No guarantee is made about what, if any, cache cleaning will occur. diff --git a/content/llcache.c b/content/llcache.c index d5b518403..33b447570 100644 --- a/content/llcache.c +++ b/content/llcache.c @@ -224,6 +224,48 @@ nserror llcache_initialise(llcache_query_callback cb, void *pw) return NSERROR_OK; } +/* See llcache.h for documentation */ +void llcache_finalise(void) +{ + llcache_object *object, *next; + + /* Clean uncached objects */ + for (object = llcache_uncached_objects; object != NULL; object = next) { + llcache_object_user *user, *next_user; + + next = object->next; + + for (user = object->users; user != NULL; user = next_user) { + next_user = user->next; + + free(user); + } + + /* Fetch system has already been destroyed */ + object->fetch.fetch = NULL; + + llcache_object_destroy(object); + } + + /* Clean cached objects */ + for (object = llcache_cached_objects; object != NULL; object = next) { + llcache_object_user *user, *next_user; + + next = object->next; + + for (user = object->users; user != NULL; user = next_user) { + next_user = user->next; + + free(user); + } + + /* Fetch system has already been destroyed */ + object->fetch.fetch = NULL; + + llcache_object_destroy(object); + } +} + /* See llcache.h for documentation */ nserror llcache_poll(void) { diff --git a/content/llcache.h b/content/llcache.h index 3a1e32ca9..d7958b056 100644 --- a/content/llcache.h +++ b/content/llcache.h @@ -160,6 +160,11 @@ typedef nserror (*llcache_query_callback)(const llcache_query *query, void *pw, */ nserror llcache_initialise(llcache_query_callback cb, void *pw); +/** + * Finalise the low-level cache + */ +void llcache_finalise(void); + /** * Cause the low-level cache to emit any pending notifications * and attempt to clean the cache. No guarantee is made about diff --git a/desktop/netsurf.c b/desktop/netsurf.c index 2ce1012c2..b25209c4f 100644 --- a/desktop/netsurf.c +++ b/desktop/netsurf.c @@ -187,6 +187,10 @@ void netsurf_exit(void) utf8_finalise(); LOG(("Destroying URLdb")); urldb_destroy(); + LOG(("Finalising high-level cache")); + hlcache_finalise(); + LOG(("Finalising low-level cache")); + llcache_finalise(); LOG(("Exited successfully")); }