Skip to content

Commit

Permalink
added /cache/stats.html for statistics / flushing
Browse files Browse the repository at this point in the history
	modified:   include/cache.h
	modified:   src/cache.c
	modified:   src/server.c
  • Loading branch information
g3gg0 committed Aug 16, 2024
1 parent c94ebd5 commit ceffbdb
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
30 changes: 30 additions & 0 deletions include/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@

#include <stdbool.h>
#include <stdint.h>
#include <stddef.h> // for size_t

typedef struct
{
size_t total_entries; /**< Total number of cache entries. */
size_t exists_entries; /**< Number of cache entries where the file exists. */
size_t total_files; /**< Number of files in the cache. */
size_t total_size; /**< Total size of all files in the cache (in bytes). */
size_t memory_used; /**< Total memory used for cache infos (in bytes). */
} cache_stats_t;

/**
* @brief Structure representing a cache entry.
Expand All @@ -19,6 +29,26 @@ struct cache_entry_s
const char *file_path; /**< Path of the local cached file. */
};

/**
* @brief Flushes the cache by deleting local cached files and updating cache entries.
*
* This function iterates through all cache entries, deletes the associated local files if they exist,
* and sets the `exists` flag to `false` for each entry. It does not remove the cache entries themselves,
* only the cached files on disk.
*
* The function also logs the outcome of each file deletion attempt.
*
* @note This operation does not remove cache entries from memory; it only deletes the files from the file system.
*/
void cache_flush();

/**
* @brief Gathers statistics about the current cache.
*
* @param stats Pointer to a structure where the statistics will be stored.
*/
void cache_stats(cache_stats_t *stats);

/**
* @brief Adds a new cache entry for the given URL.
*
Expand Down
75 changes: 75 additions & 0 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,81 @@
cache_entry_t cache_table = {.next = NULL, .hash = 0, .original_url = NULL, .cached_url = NULL, .file_path = NULL};
uint32_t cache_entries = 0;

void cache_flush()
{
cache_entry_t *pos = &cache_table;

while (pos != NULL)
{
if (pos->exists)
{
// Attempt to delete the local file
if (pos->file_path && remove(pos->file_path) == 0)
{
TRACE_INFO("Deleted cached file: %s\n", pos->file_path);
}
else
{
TRACE_WARNING("Failed to delete cached file: %s\n", pos->file_path ? pos->file_path : "Unknown path");
}

// Set the exists flag to false
pos->exists = false;
}

pos = pos->next;
}
}

/**
* @brief Gathers statistics about the current cache.
*
* @param stats Pointer to a structure where the statistics will be stored.
*/
void cache_stats(cache_stats_t *stats)
{
if (stats == NULL)
{
return;
}

cache_entry_t *pos = &cache_table;
memset(stats, 0, sizeof(cache_stats_t)); // Initialize all stats to zero

while (pos != NULL)
{
stats->total_entries++;
stats->memory_used += sizeof(*pos); // Add size of the cache entry structure

if (pos->original_url)
{
stats->memory_used += strlen(pos->original_url) + 1; // Add length of original_url string
}
if (pos->cached_url)
{
stats->memory_used += strlen(pos->cached_url) + 1; // Add length of cached_url string
}
if (pos->file_path)
{
stats->memory_used += strlen(pos->file_path) + 1; // Add length of file_path string
}

if (pos->exists)
{
stats->exists_entries++;

if (fsFileExists(pos->file_path))
{
stats->total_files++;
uint32_t size = 0;
fsGetFileSize(pos->file_path, &size);
stats->total_size += size;
}
}
pos = pos->next;
}
}

/**
* @brief Caches and returns a modified base URL with trailing slashes removed.
*
Expand Down
57 changes: 57 additions & 0 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,63 @@ request_type_t request_paths[] = {

error_t handleCacheDownload(HttpConnection *connection, const char_t *uri, const char_t *queryString, client_ctx_t *client_ctx)
{
if (strcmp(uri, "/cache/flush") == 0)
{
cache_flush();

char *resp = "<html><body><h1>Cache Flushed</h1><p>The cache has been successfully flushed.</p><a href=\"/cache/stats.html\">Return to Cache Stats</a></body></html>";
httpPrepareHeader(connection, "text/html; charset=utf-8", osStrlen(resp));
return httpWriteResponseString(connection, resp, false);
}

if (strcmp(uri, "/cache/stats.html") == 0)
{
cache_stats_t stats;
cache_stats(&stats);

char stats_page[4096]; // Buffer for the HTML page
snprintf(stats_page, sizeof(stats_page),
"<!DOCTYPE html>"
"<html lang=\"en\">"
"<head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
"<meta http-equiv=\"refresh\" content=\"5\">"
"<title>Cache Statistics</title>"
"<style>"
"body { font-family: Arial, sans-serif; background-color: #f4f4f4; color: #333; }"
"h1 { color: #444; text-align: center; }"
".container { max-width: 800px; margin: 50px auto; padding: 20px; background-color: #fff; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }"
"table { width: 100%%; border-collapse: collapse; margin-top: 20px; }"
"th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }"
"th { background-color: #f2f2f2; }"
".btn { display: inline-block; padding: 10px 20px; font-size: 16px; color: #fff; background-color: #007bff; border: none; border-radius: 5px; text-decoration: none; margin-top: 20px; }"
"</style>"
"</head>"
"<body>"
"<div class=\"container\">"
"<h1>Cache Statistics</h1>"
"<table>"
"<tr><th>Total Entries</th><td>%zu</td></tr>"
"<tr><th>Entries with Existing Files</th><td>%zu</td></tr>"
"<tr><th>Total Cached Files</th><td>%zu</td></tr>"
"<tr><th>Total Cache Size</th><td>%zu bytes</td></tr>"
"<tr><th>Memory Used</th><td>%zu bytes</td></tr>"
"</table>"
"<a href=\"/cache/flush\" class=\"btn\">Flush Cache</a>"
"</div>"
"</body>"
"</html>",
stats.total_entries,
stats.exists_entries,
stats.total_files,
stats.total_size,
stats.memory_used);

httpPrepareHeader(connection, "text/html; charset=utf-8", osStrlen(stats_page));
return httpWriteResponseString(connection, stats_page, false);
}

cache_entry_t *entry = cache_fetch_by_path(uri);
if (!entry)
{
Expand Down

0 comments on commit ceffbdb

Please sign in to comment.