aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRodrigo Arias Mallo <rodarima@gmail.com>2025-08-03 14:59:02 +0200
committerRodrigo Arias Mallo <rodarima@gmail.com>2025-08-11 21:43:10 +0200
commitc3431cc169a7bc24dcff845aeda3f7f30a8ad1fa (patch)
treeaa4b21207b25f99e48f9ba64f6e211d256a9e024 /src
parent7dfbd6818b9f81df58fb10f3a56ed39338fdd002 (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.c93
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;