diff options
author | Rodrigo Arias Mallo <rodarima@gmail.com> | 2025-08-03 14:59:02 +0200 |
---|---|---|
committer | Rodrigo Arias Mallo <rodarima@gmail.com> | 2025-08-11 21:43:10 +0200 |
commit | c3431cc169a7bc24dcff845aeda3f7f30a8ad1fa (patch) | |
tree | aa4b21207b25f99e48f9ba64f6e211d256a9e024 /src | |
parent | 7dfbd6818b9f81df58fb10f3a56ed39338fdd002 (diff) |
Add about:cache page with cache statistics
The internal network cache holds entries for all the URLs fetched by
Dillo, and it only grows over time. It is convenient to be able to see
what elements are being currently stored so we can have choose a better
criteria if we decide to remove entries to avoid a huge memory usage
over time.
The entries are generated every time the page is requested, so it always
reflects the current state.
Diffstat (limited to 'src')
-rw-r--r-- | src/cache.c | 93 |
1 files changed, 92 insertions, 1 deletions
diff --git a/src/cache.c b/src/cache.c index d05565c9..7ee9d9d7 100644 --- a/src/cache.c +++ b/src/cache.c @@ -36,6 +36,7 @@ #include "domain.h" #include "timeout.hh" #include "uicmd.hh" +#include "dlib/dlib.h" /** Maximum initial size for the automatically-growing data buffer */ #define MAX_INIT_BUF 1024*1024 @@ -91,6 +92,7 @@ static uint_t DelayedQueueIdleId = 0; static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry); static void Cache_delayed_process_queue(CacheEntry_t *entry); static void Cache_auth_entry(CacheEntry_t *entry, BrowserWindow *bw); +static Dstr *Cache_data(CacheEntry_t *entry); /** * Determine if two cache entries are equal (used by CachedURLs) @@ -266,6 +268,19 @@ static CacheEntry_t *Cache_entry_add(const DilloUrl *Url) } /** + * Compute the actual size occupied by a cache entry. + * + * The size is computed from the allocated buffer. */ +static int Cache_bufsize(CacheEntry_t *e) +{ + Dstr *buf = Cache_data(e); + if (buf) + return buf->len; + else + return 0; +} + +/** * Inject full page content directly into the cache. * Used for "about:splash". May be used for "about:cache" too. */ @@ -365,6 +380,64 @@ void a_Cache_entry_remove_by_url(DilloUrl *url) /* Misc. operations ------------------------------------------------------- */ +static Dstr *Cache_stats(void) +{ + float totalKB = 0.0f; + + Dstr *s = dStr_new( + "<!DOCTYPE HTML>\n" + "<html>\n" + "<head><title>Dillo Cache</title></head>\n" + "<body>\n"); + + int n = dList_length(CachedURLs); + dStr_sprintfa(s, "<h1>Cached URLs (%d)</h1>\n", n); + + dStr_append(s, "<table>\n"); + dStr_append(s, "<tr>\n"); + dStr_append(s, "<th>Hits</th>\n"); + dStr_append(s, "<th>Size</th>\n"); + dStr_append(s, "<th>URL</th>\n"); + dStr_append(s, "</tr>\n"); + for (int i = 0; i < n; i++) { + CacheEntry_t *e = dList_nth_data(CachedURLs, i); + float sizeKB = Cache_bufsize(e) / 1024.0f; + const char *url = URL_STR(e->Url); + dStr_append(s, "<tr>\n"); + dStr_sprintfa(s, "<td style='text-align:right'>%d</td>\n", e->Hits); + dStr_sprintfa(s, "<td style='text-align:right'>%.2f KiB</td>\n", sizeKB); + dStr_sprintfa(s, "<td><a href='%s'>", url); + dStr_shorten(s, url, 60); + dStr_append(s, "</a></td>\n"); + dStr_append(s, "</tr>\n"); + totalKB += sizeKB; + } + dStr_append(s, "</table>\n"); + dStr_sprintfa(s, "<p>Total cached: %.2f MiB</p>\n", totalKB / 1024.0f); + dStr_append(s, + "</body>\n" + "</html>\n"); + + return s; +} + +static int Cache_internal_url(CacheEntry_t *entry) +{ + Dstr *s = NULL; + + if (strcmp(URL_PATH(entry->Url), "cache") == 0) { + s = Cache_stats(); + } + + if (s != NULL) { + a_Cache_entry_inject(entry->Url, s); + /* Remove InternalUrl */ + entry->Flags = CA_GotHeader + CA_GotLength; + } + + return 0; +} + /** * Try finding the url in the cache. If it hits, send the cache contents * from there. If it misses, set up a new connection. @@ -383,6 +456,13 @@ int a_Cache_open_url(void *web, CA_Callback_t Call, void *CbData) CacheEntry_t *entry; DilloWeb *Web = web; DilloUrl *Url = Web->url; + int isInternal = 0; + + if (dStrAsciiCasecmp(URL_SCHEME(Url), "about") == 0) { + _MSG("got internal URL: %s\n", URL_STR(Url)); + isInternal = 1; + Cache_entry_remove(NULL, Url); + } if (URL_FLAGS(Url) & URL_E2EQuery) { /* remove current entry */ @@ -390,16 +470,27 @@ int a_Cache_open_url(void *web, CA_Callback_t Call, void *CbData) } if ((entry = Cache_entry_search(Url))) { + _MSG("serving cached entry: %s\n", URL_STR(Url)); /* URL is cached: feed our client with cached data */ ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData); Cache_delayed_process_queue(entry); entry->Hits++; } else { + _MSG("serving new entry: %s\n", URL_STR(Url)); /* URL not cached: create an entry, send our client to the queue, * and open a new connection */ entry = Cache_entry_add(Url); - ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData); + + /* URL is an internal call, populate */ + if (isInternal) { + _MSG("handling internal: %s\n", URL_STR(Url)); + Cache_internal_url(entry); + ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData); + Cache_delayed_process_queue(entry); + } else { + ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData); + } } return ClientKey; |