From 56e7b234152e5bd792d2885db2eabab008064b5e Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Mon, 10 Oct 2011 22:41:31 +0000 Subject: add about:imagecache some of teh implementation needs cleaning up svn path=/trunk/netsurf/; revision=13030 --- content/fetchers/about.c | 87 +++++++++++++++++++++++- image/image_cache.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++ image/image_cache.h | 25 ++++++- 3 files changed, 277 insertions(+), 2 deletions(-) diff --git a/content/fetchers/about.c b/content/fetchers/about.c index 5c33c1881..cb533bc54 100644 --- a/content/fetchers/about.c +++ b/content/fetchers/about.c @@ -54,6 +54,7 @@ #include "utils/utils.h" #include "utils/ring.h" #include "utils/testament.h" +#include "image/image_cache.h" struct fetch_about_context; @@ -159,7 +160,88 @@ static bool fetch_about_licence_handler(struct fetch_about_context *ctx) return true; } +/** Handler to generate about:cache page. + * + * Shows details of current iamge cache + * + */ +static bool fetch_about_imagecache_handler(struct fetch_about_context *ctx) +{ + char buffer[1024]; /* output buffer */ + int code = 200; + int slen; + unsigned int cent_loop = 0; + int res = 0; + /* content is going to return ok */ + fetch_set_http_code(ctx->fetchh, code); + + /* content type */ + if (fetch_about_send_header(ctx, "Content-Type: text/html")) + goto fetch_about_imagecache_handler_aborted; + + slen = snprintf(buffer, sizeof buffer, + "\n\n" + "NetSurf Browser Image Cache Status\n" + "\n" + "\n" + "\n" + "

" + "" + "\"NetSurf\"" + "

\n" + "

NetSurf Browser Image Cache Status

\n" ); + if (fetch_about_send_callback(FETCH_DATA, ctx, buffer, + slen, FETCH_ERROR_NO_ERROR)) + goto fetch_about_imagecache_handler_aborted; + + slen = image_cache_snsummaryf(buffer, sizeof(buffer), NULL); + + if (fetch_about_send_callback(FETCH_DATA, ctx, buffer, + slen, FETCH_ERROR_NO_ERROR)) + goto fetch_about_imagecache_handler_aborted; + + slen = snprintf(buffer, sizeof buffer, + "\n" + "\n"); + do { + res = image_cache_snentryf(buffer + slen, sizeof buffer - slen, + cent_loop, + "\n"); + if (res <= 0) + break; /* last option */ + + if (res >= (int) (sizeof buffer - slen)) { + /* last entry would not fit in buffer, submit buffer */ + if (fetch_about_send_callback(FETCH_DATA, ctx, buffer, + slen, FETCH_ERROR_NO_ERROR)) + goto fetch_about_imagecache_handler_aborted; + slen = 0; + } else { + /* normal addition */ + slen += res; + cent_loop++; + } + } while (res > 0); + + slen += snprintf(buffer + slen, sizeof buffer - slen, + "
EntryContent KeyRedraw CountConversion CountLast RedrawBitmap AgeBitmap Size
%e%k%r%c%a%g%s
\n\n\n"); + + if (fetch_about_send_callback(FETCH_DATA, ctx, buffer, slen, + FETCH_ERROR_NO_ERROR)) + goto fetch_about_imagecache_handler_aborted; + + fetch_about_send_callback(FETCH_FINISHED, ctx, 0, 0, + FETCH_ERROR_NO_ERROR); + + return true; + +fetch_about_imagecache_handler_aborted: + return false; +} + +/** Handler to generate about:config page */ static bool fetch_about_config_handler(struct fetch_about_context *ctx) { char buffer[1024]; @@ -226,6 +308,7 @@ fetch_about_config_handler_aborted: return false; } + /** Generate the text of a Choices file which represents the current * in use options. */ @@ -408,7 +491,9 @@ struct about_handlers about_handler_list[] = { { "testament", SLEN("testament"), NULL, fetch_about_testament_handler, false }, { "about", SLEN("about"), NULL, fetch_about_about_handler, true }, { "logo", SLEN("logo"), NULL, fetch_about_logo_handler, true }, - /* The default */ + /* details about the cache */ + { "imagecache", SLEN("iamgecache"), NULL, fetch_about_imagecache_handler, true }, + /* The default blank page */ { "blank", SLEN("blank"), NULL, fetch_about_blank_handler, true } }; diff --git a/image/image_cache.c b/image/image_cache.c index 32fe74571..e060c2303 100644 --- a/image/image_cache.c +++ b/image/image_cache.c @@ -22,6 +22,7 @@ #include #include "utils/errors.h" +#include "utils/utils.h" #include "utils/log.h" #include "utils/config.h" #include "utils/schedule.h" @@ -124,6 +125,20 @@ struct image_cache_s { static struct image_cache_s *image_cache = NULL; +/** Find the nth cache entry + */ +static struct image_cache_entry_s *image_cache__findn(int entryn) +{ + struct image_cache_entry_s *found; + + found = image_cache->entries; + while ((found != NULL) && (entryn > 0)) { + entryn--; + found = found->next; + } + return found; +} + /** Find the cache entry for a content */ static struct image_cache_entry_s *image_cache__find(const struct content *c) @@ -511,6 +526,158 @@ nserror image_cache_remove(struct content *content) return NSERROR_OK; } +/* exported interface documented in image_cache.h */ +int image_cache_snsummaryf(char *string, size_t size, const char *fmt) +{ + size_t slen = 0; /* current output string length */ + unsigned int op_count; + + slen += snprintf(string + slen, size - slen, + "

Configured limit of %ld hysteresis of %ld", + image_cache->params.limit, image_cache->params.hysteresis); + + slen += snprintf(string + slen, size - slen, + "

Total bitmap size in use %ld (in %d)", + image_cache->total_bitmap_size, + image_cache->bitmap_count); + + op_count = image_cache->hit_count + + image_cache->miss_count + + image_cache->fail_count; + + slen += snprintf(string + slen, size - slen, + "

Age %ds", image_cache->current_age / 1000); + + slen += snprintf(string + slen, size - slen, + "

Peak size %ld (in %d)", + image_cache->max_bitmap_size, + image_cache->max_bitmap_size_count ); + slen += snprintf(string + slen, size - slen, + "

Peak image count %d (size %ld)", + image_cache->max_bitmap_count, + image_cache->max_bitmap_count_size); + + if (op_count > 0) { + uint64_t op_size; + + op_size = image_cache->hit_size + + image_cache->miss_size + + image_cache->fail_size; + + slen += snprintf(string + slen, size - slen, + "

Cache total/hit/miss/fail (counts) %d/%d/%d/%d (100%%/%d%%/%d%%/%d%%)", + op_count, + image_cache->hit_count, + image_cache->miss_count, + image_cache->fail_count, + (image_cache->hit_count * 100) / op_count, + (image_cache->miss_count * 100) / op_count, + (image_cache->fail_count * 100) / op_count); + + slen += snprintf(string + slen, size - slen, + "

Cache total/hit/miss/fail (size) %"PRIu64"/%"PRIu64"/%"PRIu64"/%"PRIu64" (100%%/%"PRIu64"%%/%"PRIu64"%%/%"PRIu64"%%)", + op_size, + image_cache->hit_size, + image_cache->miss_size, + image_cache->fail_size, + (image_cache->hit_size * 100) / op_size, + (image_cache->miss_size * 100) / op_size, + (image_cache->fail_size * 100) / op_size); + } + + slen += snprintf(string + slen, size - slen, + "

Total images never rendered: %d (includes %d that were converted)", + image_cache->total_unrendered, + image_cache->specultive_miss_count); + + slen += snprintf(string + slen, size - slen, + "

Total number of excessive conversions: %d (from %d images converted more than once)", + image_cache->total_extra_conversions, + image_cache->total_extra_conversions_count); + + slen += snprintf(string + slen, size - slen, + "

Bitmap of size %d had most (%d) conversions", + image_cache->peak_conversions_size, + image_cache->peak_conversions); + + return slen; +} + +/* exported interface documented in image_cache.h */ +int image_cache_snentryf(char *string, size_t size, unsigned int entryn, + const char *fmt) +{ + struct image_cache_entry_s *centry; + size_t slen = 0; /* current output string length */ + int fmtc = 0; /* current index into format string */ + + centry = image_cache__findn(entryn); + if (centry == NULL) + return -1; + + while((slen < size) && (fmt[fmtc] != 0)) { + if (fmt[fmtc] == '%') { + fmtc++; + switch (fmt[fmtc]) { + case 'e': + slen += snprintf(string + slen, size - slen, + "%d", entryn); + break; + + case 'r': + slen += snprintf(string + slen, size - slen, + "%u", centry->redraw_count); + break; + + case 'a': + slen += snprintf(string + slen, size - slen, + "%.2f", (float)((image_cache->current_age - centry->redraw_age)) / 1000); + break; + + + case 'c': + slen += snprintf(string + slen, size - slen, + "%d", centry->conversion_count); + break; + + case 'g': + slen += snprintf(string + slen, size - slen, + "%.2f", (float)((image_cache->current_age - centry->bitmap_age)) / 1000); + break; + + case 'k': + slen += snprintf(string + slen, size - slen, + "%p", centry->content); + break; + + case 's': + if (centry->bitmap != NULL) { + slen += snprintf(string + slen, + size - slen, + "%ld", + centry->bitmap_size); + } else { + slen += snprintf(string + slen, + size - slen, + "0"); + } + break; + } + fmtc++; + } else { + string[slen] = fmt[fmtc]; + slen++; + fmtc++; + } + } + + /* Ensure that we NUL-terminate the output */ + string[min(slen, size - 1)] = '\0'; + + return slen; +} + + /* exported interface documented in image_cache.h */ bool image_cache_redraw(struct content *c, struct content_redraw_data *data, diff --git a/image/image_cache.h b/image/image_cache.h index e879c740d..e1ae24e3a 100644 --- a/image/image_cache.h +++ b/image/image_cache.h @@ -96,7 +96,30 @@ struct bitmap *image_cache_find_bitmap(struct content *c); */ bool image_cache_speculate(struct content *c); -/* Image content handler generic cache callbacks */ +/** + * Fill a buffer with an option using a format. + * + * The format string is copied into the output buffer with the + * following replaced: + * %e - The entry number + * %k - The content key + * %r - The number of redraws of this bitmap + * %c - The number of times this bitmap has been converted + * %s - The size of the current bitmap allocation + * + * \param string The buffer in which to place the results. + * \param size The size of the string buffer. + * \param entryn The opaque entry number. + * \param fmt The format string. + * \return The number of bytes written to \a string or -1 on error + */ +int image_cache_snentryf(char *string, size_t size, unsigned int entryn, + const char *fmt); + +/** cache summary */ +int image_cache_snsummaryf(char *string, size_t size, const char *fmt); + +/********* Image content handler generic cache callbacks ************/ /** Generic content redraw callback * -- cgit v1.2.3