summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-05-09 21:39:46 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2023-05-10 00:01:20 +0200
commit7072ca1ebdd9a6a3a4691eb282143f8eedfc0e8e (patch)
treedf5c97290a0b2586bba78e7b7d8b2aed67e248f9
parent196f21f601150ecb6510a40911750584873f0cf9 (diff)
Add a function to invalidate a cache entry.
The function reuses the memory for the key, response header and body, so it adds at most 80 bytes to the file.
-rw-r--r--src/libdisfluid/disfluid-cache-entry.h38
-rw-r--r--src/libdisfluid/disfluid-tests.h138
2 files changed, 176 insertions, 0 deletions
diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h
index ca4f743..1c06537 100644
--- a/src/libdisfluid/disfluid-cache-entry.h
+++ b/src/libdisfluid/disfluid-cache-entry.h
@@ -26,6 +26,9 @@ ao_cache_entry_push (int fd, size_t *offset,
const string_desc_t response_header,
const string_desc_t response_body);
+MAYBE_UNUSED static int
+ao_cache_entry_invalidate (int fd, size_t offset, size_t *invalidated_offset);
+
# include "disfluid-append-only-file.h"
# include "safe-alloc.h"
@@ -355,4 +358,39 @@ ao_cache_entry_push (int fd, size_t *offset,
}
return 0;
}
+
+static int
+ao_cache_entry_invalidate (int fd, size_t offset, size_t *invalidated_offset)
+{
+ struct cache_entry_header header;
+ uint8_t header_bytes[12 * 2 + 16 * 3 + 1 + 7] = { 0 };
+ string_desc_t data = {._nbytes = sizeof (header_bytes),._data = header_bytes
+ };
+ *invalidated_offset = offset;
+ if (ao_file_read (fd, offset, data) < 0)
+ {
+ return -1;
+ }
+ if (ao_cache_entry_from_bytes (header_bytes, &header) < 0)
+ {
+ return -1;
+ }
+ if (header.invalidated)
+ {
+ return 0;
+ }
+ header.invalidated = true;
+ /* Push just the header, reuse the memory for key, response header
+ and body. */
+ if (ao_cache_entry_to_bytes (&header, header_bytes) < 0)
+ {
+ return -1;
+ }
+ if (ao_file_push_data (fd, data, invalidated_offset) < 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
#endif /* DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED */
diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h
index fc16d4c..4ec4569 100644
--- a/src/libdisfluid/disfluid-tests.h
+++ b/src/libdisfluid/disfluid-tests.h
@@ -163,6 +163,142 @@ END_TEST
/* *INDENT-ON* */
/* *INDENT-OFF* */
+START_TEST (test_invalidate_cache_entry_noop)
+/* *INDENT-ON* */
+
+{
+ /* Add a single cache entry to the file. It is already invalidated,
+ so invalidating it again does not do anything. */
+ static const char *key_value = "GET http://example.com\r\n";
+ static const char *header_value =
+ "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
+ static const char *body_value = "Hello, world!";
+ const string_desc_t key = {._nbytes = strlen (key_value),._data =
+ (char *) key_value
+ };
+ const string_desc_t header = {._nbytes = strlen (header_value),._data =
+ (char *) header_value
+ };
+ const string_desc_t body = {._nbytes = strlen (body_value),._data =
+ (char *) body_value
+ };
+ const struct timespec request_date = {.tv_sec = 12345,.tv_nsec = 678910 };
+ const struct timespec response_date = {.tv_sec = 111213,.tv_nsec = 141516 };
+ char filename[] = "/tmp/test-ao-cache-entry-XXXXXX";
+ int file = mkstemp (filename);
+ ck_assert_int_ge (file, 0);
+ static const char *magic_data = "disfluid c.entry";
+ const string_desc_t file_magic = {
+ ._data = (char *) magic_data,
+ ._nbytes = strlen (magic_data)
+ };
+ int error = 0;
+ size_t top;
+ error = ao_file_prepare (file, file_magic);
+ error = ao_file_lock_for_writing (file, &top);
+ ck_assert_int_eq (error, 0);
+ error =
+ /* Notice the "true" here. */
+ ao_cache_entry_push (file, &top, &request_date, &response_date, true, key,
+ header, body);
+ ck_assert_int_eq (error, 0);
+ error = ao_file_commit_transaction (file);
+ ck_assert_int_eq (error, 0);
+ size_t invalidated_offset = 42;
+ error = ao_cache_entry_invalidate (file, top, &invalidated_offset);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (invalidated_offset, top);
+ remove (filename);
+ close (file);
+}
+/* *INDENT-OFF* */
+END_TEST
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
+START_TEST (test_invalidate_cache_entry)
+/* *INDENT-ON* */
+
+{
+ /* Add a single cache entry to the file. It is not invalidated, so
+ invalidating it again pushes a new cache entry. The cache entry
+ reuses storage for the key, header and body, so it is just 80
+ bytes after the existing entry. */
+ static const char *key_value = "GET http://example.com\r\n";
+ static const char *header_value =
+ "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n";
+ static const char *body_value = "Hello, world!";
+ const string_desc_t key = {._nbytes = strlen (key_value),._data =
+ (char *) key_value
+ };
+ const string_desc_t header = {._nbytes = strlen (header_value),._data =
+ (char *) header_value
+ };
+ const string_desc_t body = {._nbytes = strlen (body_value),._data =
+ (char *) body_value
+ };
+ const struct timespec request_date = {.tv_sec = 12345,.tv_nsec = 678910 };
+ const struct timespec response_date = {.tv_sec = 111213,.tv_nsec = 141516 };
+ char filename[] = "/tmp/test-ao-cache-entry-XXXXXX";
+ int file = mkstemp (filename);
+ ck_assert_int_ge (file, 0);
+ static const char *magic_data = "disfluid c.entry";
+ const string_desc_t file_magic = {
+ ._data = (char *) magic_data,
+ ._nbytes = strlen (magic_data)
+ };
+ int error = 0;
+ size_t top;
+ error = ao_file_prepare (file, file_magic);
+ error = ao_file_lock_for_writing (file, &top);
+ ck_assert_int_eq (error, 0);
+ error =
+ /* Notice the "false" here. */
+ ao_cache_entry_push (file, &top, &request_date, &response_date, false,
+ key, header, body);
+ ck_assert_int_eq (error, 0);
+ error = ao_file_commit_transaction (file);
+ ck_assert_int_eq (error, 0);
+ size_t invalidated_offset = 42;
+ error = ao_cache_entry_invalidate (file, top, &invalidated_offset);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (invalidated_offset, top + 80);
+ string_desc_t check_key = { 0 };
+ string_desc_t check_header = { 0 };
+ string_desc_t check_body = { 0 };
+ struct timespec check_request_date, check_response_date;
+ bool check_invalidated;
+ error =
+ ao_cache_entry_read (file, invalidated_offset, &check_request_date,
+ &check_response_date, &check_invalidated, true, true,
+ true, &check_key, &check_header, &check_body);
+ ck_assert_int_eq (error, 0);
+ ck_assert_int_eq (check_request_date.tv_sec, 12345);
+ ck_assert_int_eq (check_request_date.tv_nsec, 678910);
+ ck_assert_int_eq (check_response_date.tv_sec, 111213);
+ ck_assert_int_eq (check_response_date.tv_nsec, 141516);
+ ck_assert (check_invalidated);
+ ck_assert_int_eq (check_key._nbytes, strlen (key_value));
+ ck_assert_int_eq (check_header._nbytes, strlen (header_value));
+ ck_assert_int_eq (check_body._nbytes, strlen (body_value));
+ ck_assert_int_eq (memcmp (check_key._data, key_value, strlen (key_value)),
+ 0);
+ ck_assert_int_eq (memcmp
+ (check_header._data, header_value, strlen (header_value)),
+ 0);
+ ck_assert_int_eq (memcmp
+ (check_body._data, body_value, strlen (body_value)), 0);
+ FREE (check_key._data);
+ FREE (check_header._data);
+ FREE (check_body._data);
+ remove (filename);
+ close (file);
+}
+/* *INDENT-OFF* */
+END_TEST
+/* *INDENT-ON* */
+
+/* *INDENT-OFF* */
START_TEST (test_cache_key_no_host)
/* *INDENT-ON* */
@@ -926,6 +1062,8 @@ run_tests (size_t *n_tests, size_t *n_errors)
suite_add_tcase (suite, general);
TCase *cache_entry = tcase_create (_("disfluid cache entry files"));
tcase_add_test (cache_entry, test_read_normal);
+ tcase_add_test (cache_entry, test_invalidate_cache_entry_noop);
+ tcase_add_test (cache_entry, test_invalidate_cache_entry);
suite_add_tcase (suite, cache_entry);
TCase *cache_key = tcase_create (_("disfluid cache key"));
tcase_add_test (cache_key, test_cache_key_no_host);