From 15435a5508ef6b8f553bd1a3d244801d51b50ccd Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Sun, 2 Apr 2023 22:40:51 +0200 Subject: Change the cache entry API to use the database API --- doc/disfluid.texi | 163 +---- include/Makefile.am | 3 +- include/disfluid-gobject.h | 52 -- include/disfluid.h | 8 - po/POTFILES.in | 1 - src/gir/Makefile.am | 2 +- src/gobject/main.c | 49 +- src/libdisfluid/disfluid-cache-entry.h | 1182 +++++--------------------------- src/libdisfluid/disfluid-tests.h | 561 +++------------ src/libdisfluid/main.c | 205 ------ src/vala/Makefile.am | 1 - src/vala/main.vala | 11 +- 12 files changed, 282 insertions(+), 1956 deletions(-) diff --git a/doc/disfluid.texi b/doc/disfluid.texi index bf66908..bf48070 100644 --- a/doc/disfluid.texi +++ b/doc/disfluid.texi @@ -7,8 +7,8 @@ @settitle Demanding Interoperability to Strengthen the Free (Libre) Web: Introducing Disfluid @c %**end of header -@set UPDATED 21 March 2023 -@set UPDATED-MONTH March 2023 +@set UPDATED 02 April 2023 +@set UPDATED-MONTH April 2023 @include version_number.texi @copying @@ -219,163 +219,4 @@ NUL-terminated, and the value @code{-2} is returned. Otherwise, @code{0} is returned. @end deftypefun -@deftp struct disfluid_cache_entry -A structure that can hold everything related to a cache entry. The -specific layout is hidden, but the overall size and alignment can be -queried at run-time. -@end deftp - -@deftypefun size_t disfluid_cache_entry_size (size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body}) -Return the size to allocate for a cache entry that can hold at most -@var{max_key} bytes of the key (method, URL and varied header values), -at most @var{max_header} for the response header, and at most -@var{max_body} for the response body. Do not hesitate to demand server -to send terse responses to you. 512 bytes for the key, 4 kB for the -header, and 2 MB for the body should be more than enough for proper -cache handling. - -This function is a constant function according to GCC: its output only -depends on the three inputs, and it is not allowed to read global -data. The compiler is free to reuse the same value without callig the -function again. Define the @code{ATTRIBUTE_CONST} macro to the syntax -for function attributes for your compiler. If you use gnulib, use the -@samp{attribute} module and include @code{attribute.h} before -@code{disfluid.h} to use this optimization. -@end deftypefun - -@deftypefun size_t disfluid_cache_entry_alignment (void) -Return the proper alignment for a cache entry. This function is -constant too. -@end deftypefun - -@deftypefun size_t disfluid_cache_entry_init (struct disfluid_cache_entry *@var{entry}, size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body}) -Initialize the @var{entry}, that must be aligned properly, and -allocated with an appropriate size, such as given by -@code{disfluid_cache_entry_size}. -@end deftypefun - -@deftypefun void disfluid_cache_entry_minimum_size (const struct disfluid_cache_entry *@var{entry}, size_t *@var{min_key}, size_t *@var{min_header}, size_t *@var{min_body}) -Set @var{min_key}, @var{min_header} and @var{min_body} to the minimum -sizes that should be allocated to hold the key, header and body of -@var{entry}. -@end deftypefun - -@deftypefun int disfluid_cache_entry_copy (struct disfluid_cache_entry *@var{dest}, const struct disfluid_cache_entry *@var{src}) -Copy @var{src} to @var{dest}. If one of the @var{dest} limits is too -short, return a negative error code. Otherwise, return 0. - -@table @code -@item -1, -3, -5, -7 -indicates that the key does not fit in @var{dest}; -@item -2, -3, -6, -7 -indicates that the response header does not fit in @var{dest}; -@item -4, -5, -6, -7 -indicates that the response body does not fit in @var{dest}. -@end table -@end deftypefun - -@deftypefun {struct disfluid_cache_entry *} disfluid_cache_entry_alloc (size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body}) -@deftypefunx {struct disfluid_cache_entry *} disfluid_cache_entry_dup (const struct disfluid_cache_entry *@var{src}) -Allocate a new cache entry with the libc standard -allocator. @code{disfluid_cache_entry_dup} allocates the same limits -as those of @var{src}. -@end deftypefun - -@deftypefun void disfluid_cache_entry_free (struct disfluid_cache_entry *@var{entry}) -Free a cache entry allocated with the standard libc allocator. -@end deftypefun - -To make memory allocation a bit safer, you can use the -@code{DISFLUID_CACHE_ENTRY_ALLOC (@var{ptr}, @var{max_key}, -@var{max_header}, @var{max_body})} and -@code{DISFLUID_CACHE_ENTRY_FREE(@var{ptr})} macros as: - -@example -struct disfluid_cache_entry *entry; -if (DISFLUID_CACHE_ENTRY_ALLOC (entry, 512, 4096, 2 * 1024 * 1024) < 0) - @{ - /* Handle memory allocation failure */ - @} -else - @{ - /* Do something with entry… */ - @} -DISFLUID_CACHE_ENTRY_FREE (entry); -/* entry is set to NULL */ -assert (entry == NULL); -@end example - -@deftypefun void disfluid_cache_entry_set_request_date (struct disfluid_cache_entry *@var{entry}, const struct timespec *@var{request_date}) -@deftypefunx void disfluid_cache_entry_set_response_date (struct disfluid_cache_entry *@var{entry}, const struct timespec *@var{response_date}) -@deftypefunx void disfluid_cache_entry_set_invalidated (struct disfluid_cache_entry *@var{entry}, int @var{invalidated}) -@deftypefunx void disfluid_cache_entry_invalidate (struct disfluid_cache_entry *@var{entry}) -Manage the metadata associated with @var{entry}. -@end deftypefun - -@deftypefun int disfluid_cache_entry_set_key (struct disfluid_cache_entry *@var{entry}, const char *@var{key}) -@deftypefunx int disfluid_cache_entry_set_header (struct disfluid_cache_entry *@var{entry}, const char *@var{header}) -@deftypefunx int disfluid_cache_entry_set_body (struct disfluid_cache_entry *@var{entry}, size_t @var{body_length}, const char *@var{body}) -Try and set the relevant cache entry section in @var{entry}. If the -respective limit is too short, return a negative error -code. Otherwise, return 0. -@end deftypefun - -@deftypefun void disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry *@var{entry}, struct timespec *@var{request_date}) -@deftypefunx void disfluid_cache_entry_get_response_date (const struct disfluid_cache_entry *@var{entry}, struct timespec *@var{response_date}) -@deftypefunx int disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry *@var{entry}) -Query the metadata of @var{entry}. -@end deftypefun - -@deftypefun size_t disfluid_cache_entry_get_key (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst}) -@deftypefunx size_t disfluid_cache_entry_get_header (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst}) -@deftypefunx size_t disfluid_cache_entry_get_body (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst}) -Ignore the first @var{start} bytes, and copy the next bytes of the -relevant section in @var{entry}, up to @var{max}, to @var{dst}. Return -the total length of the section. If there is more room allocated, make -sure that @var{dst} is NUL-terminated. -@end deftypefun - -@deftypefun int disfluid_cache_entry_load (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, ssize_t (*@var{read_impl}) (void *, void *, size_t), int (*@var{skip}) (void *, size_t), void *@var{context}) -@deftypefunx int disfluid_cache_entry_read (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, int @var{fd}) -@deftypefunx int disfluid_cache_entry_fread (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, FILE *@var{handle}) -Load a file to set up @var{entry}. If @var{load_key} (respectively, -@var{load_header} and @var{load_body}) is a strictly positive value, -then attempt to read the key (respectively, the header and body). If -it is 0, then skip it, but keep the previously loaded value. If it is -negative, then erase the value. The specific -@code{disfluid_cache_entry_read} and @code{disfluid_cache_entry_fread} -use a file descriptor and a stream file handle respectively, instead -of custom callbacks. - -@code{disfluid_cache_entry_load} uses custom callbacks to read the -file. The file is passed as @var{context}, and during the calls to -@var{read_impl} and @var{skip}, it is bound to the first argument. The -second argument of @var{read_impl} is bound to a buffer where to read -the bytes. The last argument is bound to the read request size, in -bytes. - -@var{read_impl} is supposed to return a negative value if a file -system failure occurs, 0 if the file is at end, or a value at most -equal to the read request, and set the bytes in the buffer -accordingly. @var{skip} is supposed to return 0 on success and advance -the file pointer by the request size, or return a negative error code. - -The loading functions return 0 on success, -1 in case of a file system -error, -2 if the file is invalid, -3 if it is incomplete, -4 if the -key is too large, -5 if the header is too large, -6 if the body is too -large. -@end deftypefun - -@deftypefun int disfluid_cache_entry_save (const struct disfluid_cache_entry *@var{entry}, ssize_t (*@var{write_impl}) (void *, const void *, size_t), void *@var{context}) -@deftypefunx int disfluid_cache_entry_write (const struct disfluid_cache_entry *@var{entry}, int @var{fd}) -@deftypefunx int disfluid_cache_entry_fwrite (const struct disfluid_cache_entry *@var{entry}, FILE *@var{handle}) -Save @var{entry} to a file. Return 0 on success, -1 if writing to the -file raised an error, -2 if the key, header or body is unset in -@var{entry}. @var{write_impl} is called with @var{context} bound to -the first argument, an array of bytes to write as the second, and the -array length as the third. It should return a negative value to signal -an error, or a value at most the write request length, and write the -corresponding bytes in the request to file. -@end deftypefun - @bye diff --git a/include/Makefile.am b/include/Makefile.am index b857453..5babfe2 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,8 +2,7 @@ include_HEADERS += %D%/disfluid.h pkgincludedir = $(includedir)/disfluid -dist_pkginclude_HEADERS = \ - %D%/disfluid/cache_entry.h +dist_pkginclude_HEADERS = if BUILD_GOBJECT include_HEADERS += %D%/disfluid-gobject.h diff --git a/include/disfluid-gobject.h b/include/disfluid-gobject.h index b7e5daa..2ee21cd 100644 --- a/include/disfluid-gobject.h +++ b/include/disfluid-gobject.h @@ -32,60 +32,8 @@ extern "C" { # endif /* __cplusplus */ - typedef struct disfluid_cache_entry DisfluidCacheEntry; - -# define DISFLUID_TYPE_CACHE_ENTRY (disfluid_cache_entry_get_type ()) - - /** - * disfluid_cache_entry_get_type: - * - * Query the type index used to register a cache entry. - * Returns: the type. - */ - DISFLUID_G_API extern GType disfluid_cache_entry_get_type (void); - - /** - * disfluid_cache_entry_set_request_gdate: - * @entry: (type DisfluidCacheEntry): the entry to modify. - * @request_date: the request date. - */ - DISFLUID_G_API extern void - disfluid_cache_entry_set_request_gdate (struct disfluid_cache_entry - *entry, GDateTime * request_date); - - /** - * disfluid_cache_entry_set_response_gdate: - * @entry: (type DisfluidCacheEntry): the entry to modify. - * @response_date: the response date. - */ - DISFLUID_G_API extern void - disfluid_cache_entry_set_response_gdate (struct disfluid_cache_entry - *entry, - GDateTime * response_date); - - /** - * disfluid_cache_entry_get_request_gdate: - * @entry: (type DisfluidCacheEntry): the entry to query. - * @date: (out) (transfer full): the request date. - */ - DISFLUID_G_API extern void - disfluid_cache_entry_get_request_gdate (const struct disfluid_cache_entry - *entry, GDateTime ** date); - - /** - * disfluid_cache_entry_get_response_gdate: - * @entry: (type DisfluidCacheEntry): the entry to query. - * @date: (out) (transfer full): the response date. - */ - DISFLUID_G_API extern void - disfluid_cache_entry_get_response_gdate (const struct disfluid_cache_entry - *entry, GDateTime ** date); - - # ifdef __cplusplus } # endif /* __cplusplus */ -# include - #endif /* not H_DISFLUID_GOBJECT_INCLUDED */ diff --git a/include/disfluid.h b/include/disfluid.h index 0f6649e..74b5737 100644 --- a/include/disfluid.h +++ b/include/disfluid.h @@ -87,12 +87,6 @@ # define DISFLUID_FD_ARG_WRITE_2 \ DISFLUID_FD_ARG_WRITE (2) -# define DISFLUID_DEALLOC_AS_CACHE_ENTRY \ - DISFLUID_DEALLOC_WITH (disfluid_cache_entry_free, 1) - -# define DISFLUID_DEALLOC_AS_CACHE \ - DISFLUID_DEALLOC_WITH (disfluid_cache_free, 1) - # ifdef __cplusplus extern "C" { @@ -282,6 +276,4 @@ extern "C" } # endif /* __cplusplus */ -# include - #endif /* not H_DISFLUID_INCLUDED */ diff --git a/po/POTFILES.in b/po/POTFILES.in index fe71f69..4ec33d1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,7 +1,6 @@ desktop/eu.planete_kraus.Disfluid.Devel.desktop.in desktop/eu.planete_kraus.Disfluid.desktop.in src/libdisfluid/disfluid-authors.h -src/libdisfluid/disfluid-cache-entry.h src/libdisfluid/disfluid-tests.h src/libdisfluid/disfluid-ui.h src/libdisfluid/disfluid-version.h diff --git a/src/gir/Makefile.am b/src/gir/Makefile.am index 860b2f0..ada5598 100644 --- a/src/gir/Makefile.am +++ b/src/gir/Makefile.am @@ -20,7 +20,7 @@ if BUILD_GOBJECT %D%/Disfluid-$(DLL_VERSION).gir: $(INTROSPECTION_LISTS) $(INTROSPECTION_SRC) $(MAKE) $(AM_MAKEFLAGS) $(INTROSPECTED_LIBS) - $(AM_V_GEN) $(G_IR_SCANNER) $(AM_G_IR_SCANNER_FLAGS) $(G_IR_SCANNER_FLAGS) --c-include=disfluid.h --c-include=disfluid/cache_entry.h --c-include=disfluid-gobject.h -n Disfluid --nsversion=$(DLL_VERSION) --symbol-prefix=disfluid_ --output=%D%/Disfluid-$(DLL_VERSION).gir-t $$(for lib in $(INTROSPECTED_LIBS) ; do echo "--library=$$lib" ; done) --cflags-begin $(GOBJECT_CFLAGS) --cflags-end $(INTROSPECTED_FILES) && $(SED) 's/shared-library="[^"]*"/shared-library=""/g' %D%/Disfluid-$(DLL_VERSION).gir-t > %D%/Disfluid-$(DLL_VERSION).gir-fixed && rm %D%/Disfluid-$(DLL_VERSION).gir-t && mv %D%/Disfluid-$(DLL_VERSION).gir-fixed $(srcdir)/%D%/Disfluid-$(DLL_VERSION).gir + $(AM_V_GEN) $(G_IR_SCANNER) $(AM_G_IR_SCANNER_FLAGS) $(G_IR_SCANNER_FLAGS) --c-include=disfluid.h --c-include=disfluid-gobject.h -n Disfluid --nsversion=$(DLL_VERSION) --symbol-prefix=disfluid_ --output=%D%/Disfluid-$(DLL_VERSION).gir-t $$(for lib in $(INTROSPECTED_LIBS) ; do echo "--library=$$lib" ; done) --cflags-begin $(GOBJECT_CFLAGS) --cflags-end $(INTROSPECTED_FILES) && $(SED) 's/shared-library="[^"]*"/shared-library=""/g' %D%/Disfluid-$(DLL_VERSION).gir-t > %D%/Disfluid-$(DLL_VERSION).gir-fixed && rm %D%/Disfluid-$(DLL_VERSION).gir-t && mv %D%/Disfluid-$(DLL_VERSION).gir-fixed $(srcdir)/%D%/Disfluid-$(DLL_VERSION).gir else # not BUILD_GOBJECT diff --git a/src/gobject/main.c b/src/gobject/main.c index ed1daf9..2c21374 100644 --- a/src/gobject/main.c +++ b/src/gobject/main.c @@ -21,54 +21,7 @@ #define _(String) dgettext (PACKAGE, (String)) #define N_(String) (String) -typedef struct disfluid_cache_entry DisfluidCacheEntry; - -/* *INDENT-OFF* */ -G_DEFINE_BOXED_TYPE (DisfluidCacheEntry, - disfluid_cache_entry, - disfluid_cache_entry_dup, disfluid_cache_entry_free) -/* *INDENT-ON* */ - -void -disfluid_cache_entry_set_request_gdate (struct disfluid_cache_entry *entry, - GDateTime * request_date) -{ - struct timespec ts; - ts.tv_sec = g_date_time_to_unix (request_date); - ts.tv_nsec = g_date_time_get_microsecond (request_date) * 1000; - disfluid_cache_entry_set_request_date (entry, &ts); -} - -void -disfluid_cache_entry_set_response_gdate (struct disfluid_cache_entry *entry, - GDateTime * response_date) -{ - struct timespec ts; - ts.tv_sec = g_date_time_to_unix (response_date); - ts.tv_nsec = g_date_time_get_microsecond (response_date) * 1000; - disfluid_cache_entry_set_response_date (entry, &ts); -} - -void -disfluid_cache_entry_get_request_gdate (const struct disfluid_cache_entry - *entry, GDateTime ** date) -{ - struct timespec ts; - disfluid_cache_entry_get_request_date (entry, &ts); - GDateTime *gd = g_date_time_new_from_unix_utc (ts.tv_sec); - const double nsecs = ts.tv_nsec; - *date = g_date_time_add_seconds (gd, nsecs * 1e-9); - g_date_time_unref (gd); -} - void -disfluid_cache_entry_get_response_gdate (const struct disfluid_cache_entry - *entry, GDateTime ** date) +disfluid_gobject_empty (void) { - struct timespec ts; - disfluid_cache_entry_get_response_date (entry, &ts); - GDateTime *gd = g_date_time_new_from_unix_utc (ts.tv_sec); - const double nsecs = ts.tv_nsec; - *date = g_date_time_add_seconds (gd, nsecs * 1e-9); - g_date_time_unref (gd); } diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h index eb78a6c..76de29a 100644 --- a/src/libdisfluid/disfluid-cache-entry.h +++ b/src/libdisfluid/disfluid-cache-entry.h @@ -1,1089 +1,233 @@ #ifndef DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED # define DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED -MAYBE_UNUSED static size_t -cache_entry_size (size_t max_key, size_t max_header, size_t max_body); - -MAYBE_UNUSED static size_t cache_entry_alignment (void); - -MAYBE_UNUSED static void -cache_entry_init (struct disfluid_cache_entry *entry, size_t max_key, - size_t max_header, size_t max_body); - -MAYBE_UNUSED static void -cache_entry_minimum_size (const struct disfluid_cache_entry *entry, - size_t *used_key, size_t *used_header, - size_t *used_body); - -MAYBE_UNUSED static int -cache_entry_copy (struct disfluid_cache_entry *restrict dest, - const struct disfluid_cache_entry *restrict src); - -MAYBE_UNUSED static struct disfluid_cache_entry - *cache_entry_alloc (size_t max_key, size_t max_header, size_t max_body); - -MAYBE_UNUSED static void -cache_entry_free (struct disfluid_cache_entry *entry); - -MAYBE_UNUSED static struct disfluid_cache_entry - *cache_entry_dup (const struct disfluid_cache_entry *entry); - -MAYBE_UNUSED static void -cache_entry_set_request_date (struct disfluid_cache_entry *entry, - const struct timespec *date); - -MAYBE_UNUSED static void -cache_entry_set_response_date (struct disfluid_cache_entry *entry, - const struct timespec *date); - -MAYBE_UNUSED static void -cache_entry_invalidate (struct disfluid_cache_entry *entry); - -MAYBE_UNUSED static void -cache_entry_set_invalidated (struct disfluid_cache_entry *entry, - bool invalidated); - -MAYBE_UNUSED static int -cache_entry_set_key (struct disfluid_cache_entry *entry, const char *key); - -MAYBE_UNUSED static int -cache_entry_set_response_header (struct disfluid_cache_entry *entry, - const char *header); - -MAYBE_UNUSED static int -cache_entry_set_response_body (struct disfluid_cache_entry *entry, - size_t length, const char *body); - -/* Return value: 0 -> OK, -1 -> read_impl error, -2 -> invalid file, - -3 -> incomplete file, -4 -> key too large, -5 -> header too large, - -6 -> body too large. */ -MAYBE_UNUSED static int -cache_entry_load (struct disfluid_cache_entry *entry, - int load_key, - int load_header, - int load_body, - ssize_t (*read_impl) (void *context, void *buffer, - size_t max_size), - int (*skip) (void *context, size_t size), void *context); - -MAYBE_UNUSED static int -cache_entry_read (struct disfluid_cache_entry *entry, int load_key, - int load_header, int load_body, int fd); +# include +# include "string-desc.h" +# include MAYBE_UNUSED static int -cache_entry_fread (struct disfluid_cache_entry *entry, int load_key, - int load_header, int load_body, FILE * f); +db_mark_cache_entry (const char *db_root, const string_desc_t * id); -MAYBE_UNUSED static void -cache_entry_get_request_date (const struct disfluid_cache_entry *entry, - struct timespec *date); - -MAYBE_UNUSED static void -cache_entry_get_response_date (const struct disfluid_cache_entry *entry, - struct timespec *date); - -MAYBE_UNUSED static bool -cache_entry_is_invalidated (const struct disfluid_cache_entry *entry); - -MAYBE_UNUSED static void -cache_entry_is_loaded (const struct disfluid_cache_entry *entry, - bool *key_loaded, bool *header_loaded, - bool *body_loaded); - -/* If max is too large, key will be NUL-terminated. */ -MAYBE_UNUSED static size_t -cache_entry_get_key (const struct disfluid_cache_entry *entry, size_t start, - size_t max, char *key); - -MAYBE_UNUSED static size_t -cache_entry_get_header (const struct disfluid_cache_entry *entry, - size_t start, size_t max, char *header); - -MAYBE_UNUSED static size_t -cache_entry_get_body (const struct disfluid_cache_entry *entry, size_t start, - size_t max, char *body); - -/* -1: write_impl failed. 0: OK. -2: the entry is not fully loaded. */ MAYBE_UNUSED static int -cache_entry_save (const struct disfluid_cache_entry *entry, - ssize_t (*write_impl) (void *context, const void *buffer, - size_t max_size), void *context); +db_read_cache_entry (const char *db_root, const string_desc_t * id, + struct timespec *request_date, + struct timespec *response_date, bool *invalidated, + string_desc_t * key_id, + string_desc_t * response_header_id, + string_desc_t * response_body_id); MAYBE_UNUSED static int -cache_entry_write (const struct disfluid_cache_entry *entry, int fd); +db_write_cache_entry (const char *db_root, string_desc_t * id, + const struct timespec *request_date, + const struct timespec *response_date, bool invalidated, + const string_desc_t * key_id, + const string_desc_t * response_header_id, + const string_desc_t * response_body_id); -MAYBE_UNUSED static int -cache_entry_fwrite (const struct disfluid_cache_entry *entry, FILE * f); +# include "disfluid-db.h" +# include "safe-alloc.h" MAYBE_UNUSED static int -cache_entry_describe_request_date (const struct disfluid_cache_entry *entry, - char **description); - -MAYBE_UNUSED static int -cache_entry_describe_response_date (const struct disfluid_cache_entry *entry, - char **description); - -# include -# include - -# include "disfluid-init.h" - -# define INVALIDATED 0b1000 -# define KEY_NOT_LOADED 0b0001 -# define HEADER_NOT_LOADED 0b0010 -# define BODY_NOT_LOADED 0b0100 - -struct disfluid_cache_entry -{ - struct timespec request_date; - struct timespec response_date; - int flags; - size_t max_key; - size_t max_header; - size_t max_body; - size_t key_length; - size_t header_length; - size_t body_length; - char data[FLEXIBLE_ARRAY_MEMBER]; /* Contains max_key + 1 + - max_header + 1 + max_body - elements */ - /* The key and header are NUL-terminated in memory. */ -}; - -static char * -cache_entry_internal_data (struct disfluid_cache_entry *entry) -{ - return &(entry->data[0]); -} - -static char * -cache_entry_key (struct disfluid_cache_entry *entry) -{ - return cache_entry_internal_data (entry); -} - -static char * -cache_entry_header (struct disfluid_cache_entry *entry) +db_mark_cache_entry (const char *db_root, const string_desc_t * id) { - char *key = cache_entry_key (entry); - return &(key[entry->max_key + 1]); -} - -static char * -cache_entry_body (struct disfluid_cache_entry *entry) -{ - char *key = cache_entry_header (entry); - return &(key[entry->max_header + 1]); -} - -static size_t -cache_entry_size (size_t max_key, size_t max_header, size_t max_body) -{ - return FLEXSIZEOF (struct disfluid_cache_entry, data, - max_key + 1 + max_header + 1 + max_body); -} - -static size_t -cache_entry_alignment (void) -{ - return FLEXALIGNOF (struct disfluid_cache_entry); -} - -static void -cache_entry_init (struct disfluid_cache_entry *entry, size_t max_key, - size_t max_header, size_t max_body) -{ - ensure_init (); - entry->request_date.tv_sec = 0; - entry->request_date.tv_nsec = 0; - entry->response_date.tv_sec = 0; - entry->response_date.tv_nsec = 0; - entry->flags = KEY_NOT_LOADED | HEADER_NOT_LOADED | BODY_NOT_LOADED; - entry->max_key = max_key; - entry->max_header = max_header; - entry->max_body = max_body; - entry->key_length = 0; - entry->header_length = 0; - entry->body_length = 0; - char *key = cache_entry_key (entry); - char *header = cache_entry_header (entry); - *key = '\0'; - *header = '\0'; -} - -static void -cache_entry_minimum_size (const struct disfluid_cache_entry *entry, - size_t *min_key, size_t *min_header, - size_t *min_body) -{ - (void) entry; - *min_key = entry->key_length; - *min_header = entry->header_length; - *min_body = entry->body_length; - assert (entry->flags & KEY_NOT_LOADED - || (strlen (cache_entry_key ((struct disfluid_cache_entry *) entry)) - == entry->key_length)); - assert (entry->flags & HEADER_NOT_LOADED - || - (strlen (cache_entry_header ((struct disfluid_cache_entry *) entry)) - == entry->header_length)); -} - -static int -cache_entry_copy (struct disfluid_cache_entry *restrict dest, - const struct disfluid_cache_entry *restrict src) -{ - dest->request_date.tv_sec = src->request_date.tv_sec; - dest->request_date.tv_nsec = src->request_date.tv_nsec; - dest->response_date.tv_sec = src->response_date.tv_sec; - dest->response_date.tv_nsec = src->response_date.tv_nsec; - dest->flags = src->flags; - size_t src_key_size, src_header_size, src_body_size; - cache_entry_minimum_size (src, &src_key_size, &src_header_size, - &src_body_size); - char *dest_key = cache_entry_key (dest); - char *dest_header = cache_entry_header (dest); - char *dest_body = cache_entry_body (dest); - const char *src_key = cache_entry_key ((struct disfluid_cache_entry *) src); - const char *src_header = - cache_entry_header ((struct disfluid_cache_entry *) src); - const char *src_body = - cache_entry_body ((struct disfluid_cache_entry *) src); - int flags = 0; - if (src_key_size > dest->max_key) - { - flags = flags | 1; - } - if (src_header_size > dest->max_header) - { - flags = flags | 2; - } - if (src_body_size > dest->max_body) - { - flags = flags | 4; - } - if (flags == 0) - { - if (!(src->flags & KEY_NOT_LOADED)) - { - strcpy (dest_key, src_key); - } - dest->key_length = src_key_size; - if (!(src->flags & HEADER_NOT_LOADED)) - { - strcpy (dest_header, src_header); - } - dest->header_length = src_header_size; - if (!(src->flags & BODY_NOT_LOADED)) - { - memcpy (dest_body, src_body, src_body_size); - } - dest->body_length = src_body_size; - } - return -flags; -} - -static struct disfluid_cache_entry * -cache_entry_alloc (size_t max_key, size_t max_header, size_t max_body) -{ - const size_t size = cache_entry_size (max_key, max_header, max_body); - const size_t alignment = cache_entry_alignment (); - struct disfluid_cache_entry *ret = calloc (1, size); - if (ret != NULL) - { - size_t address; - assert (sizeof (address) == sizeof (ret)); - memcpy (&address, &ret, sizeof (size_t)); - if ((address % alignment) != 0) - { - /* Calloc alignment is not strict enough. Should not happen - unless disfluid_cache_entry has bizarrely-aligned fields. */ - abort (); - } - cache_entry_init (ret, max_key, max_header, max_body); - } - return ret; -} - -static void -cache_entry_free (struct disfluid_cache_entry *entry) -{ - free (entry); -} - -static struct disfluid_cache_entry * -cache_entry_dup (const struct disfluid_cache_entry *entry) -{ - struct disfluid_cache_entry *ret = - cache_entry_alloc (entry->max_key, entry->max_header, entry->max_body); - if (ret != NULL) + struct timespec request_date = { 0 }, response_date = { 0 }; + bool invalidated = false; + string_desc_t key = { 0 }, header = { 0 }, body = { 0 }; + int error = db_read_cache_entry (db_root, id, &request_date, &response_date, + &invalidated, &key, &header, &body); + if (error < 0) { - int error = cache_entry_copy (ret, entry); - /* There is just as much room in ret as in entry, so the copy - cannot fail. */ - assert (error == 0); + goto cleanup; } - return ret; -} - -static void -cache_entry_normalize_timespec (struct timespec *ts) -{ - static const long billion = 1 * 1000 * 1000 * 1000; - if (ts->tv_nsec >= 1 * billion) + int key_error = db_mark_leaf (db_root, &key); + int header_error = db_mark_leaf (db_root, &header); + int body_error = db_mark_leaf (db_root, &body); + if (key_error < 0 || header_error < 0 || body_error < 0) { - time_t additional_seconds = ts->tv_nsec / (1 * billion); - ts->tv_sec += additional_seconds; - ts->tv_nsec = ts->tv_nsec % (1 * billion); + error = -1; } +cleanup: + FREE (key._data); + FREE (header._data); + FREE (body._data); + return error; } -static void -cache_entry_set_request_date (struct disfluid_cache_entry *entry, - const struct timespec *date) -{ - entry->request_date.tv_sec = date->tv_sec; - entry->request_date.tv_nsec = date->tv_nsec; - cache_entry_normalize_timespec (&(entry->request_date)); -} - -static void -cache_entry_set_response_date (struct disfluid_cache_entry *entry, - const struct timespec *date) -{ - entry->response_date.tv_sec = date->tv_sec; - entry->response_date.tv_nsec = date->tv_nsec; - cache_entry_normalize_timespec (&(entry->response_date)); -} +/* The cache entry file is organized as follows: -static void -cache_entry_invalidate (struct disfluid_cache_entry *entry) -{ - cache_entry_set_invalidated (entry, true); -} - -static void -cache_entry_set_invalidated (struct disfluid_cache_entry *entry, - bool invalidated) -{ - if (invalidated) - { - entry->flags = entry->flags | INVALIDATED; - } - else - { - entry->flags = entry->flags & ~INVALIDATED; - } -} + - on 16 bytes, "disfluid c.entry", + - on 8 bytes, the request date (timestamp in seconds), + - on 4 bytes, the request date (number of nanoseconds), + - on 8 bytes, the response date (timestamp in seconds), + - on 4 bytes, the response date (number of nanoseconds), + - on 32 bytes, the key digest, + - on 32 bytes, the header digest, + - on 32 bytes, the body digest, + - 80 if the entry has been artificially invalidated, 00 otherwise. + */ static int -cache_entry_set_key (struct disfluid_cache_entry *entry, const char *key) +parse_timespec (const char *data, struct timespec *ts) { - if (strlen (key) < entry->max_key) + ts->tv_sec = 0; + ts->tv_nsec = 0; + for (size_t i = 0; i < 8; i++) { - strcpy (cache_entry_key (entry), key); - entry->key_length = strlen (key); - entry->flags = entry->flags & ~KEY_NOT_LOADED; - return 0; + ts->tv_sec *= 256; + ts->tv_sec += (uint8_t) data[i]; } - return -1; -} - -static int -cache_entry_set_response_header (struct disfluid_cache_entry *entry, - const char *header) -{ - if (strlen (header) < entry->max_header) + for (size_t i = 0; i < 4; i++) { - strcpy (cache_entry_header (entry), header); - entry->header_length = strlen (header); - entry->flags = entry->flags & ~HEADER_NOT_LOADED; - return 0; + ts->tv_nsec *= 256; + ts->tv_nsec += (uint8_t) data[8 + i]; } - return -1; -} - -static int -cache_entry_set_response_body (struct disfluid_cache_entry *entry, - size_t length, const char *body) -{ - if (length <= entry->max_body) + if (ts->tv_nsec < 1000000000) { - memcpy (cache_entry_body (entry), body, length); - entry->body_length = length; - entry->flags = entry->flags & ~BODY_NOT_LOADED; return 0; } return -1; } -/* The cache entry file is composed as: */ - -/* "disfluid c.entry" as the magic number on 16 bytes. */ -/* The request date on 12 bytes: 8 bytes, big endian, unsigned, for - the tv_sec field, and then 4 bytes, big endian, unsigned, for the - tv_nsec field (must be < 1e9). */ -/* The response date on 12 bytes. */ -/* On 1 byte: a value >= 128 if invalidated, < 128 if still valid. */ -/* On 8 bytes: the key length. */ -/* The key. */ -/* On 8 bytes: the header length. */ -/* The header. */ -/* On 8 bytes: the body length. */ -/* The body. */ - -struct disfluid_cache_entry_loader -{ - ssize_t (*read_impl) (void *, void *, size_t); - int (*skip) (void *, size_t); - void *context; -}; - -static int -cache_entry_really_load_n (struct disfluid_cache_entry_loader *loader, - size_t n, uint8_t * bytes) -{ - while (n > 0) - { - ssize_t n_this_time = loader->read_impl (loader->context, bytes, n); - if (n_this_time < 0) - { - return -1; - } - else if (n_this_time == 0) - { - return -3; - } - else - { - assert (n_this_time > 0); - bytes = &(bytes[n_this_time]); - n -= n_this_time; - } - } - return 0; -} - -static int -cache_entry_skip_n (struct disfluid_cache_entry_loader *loader, size_t n) -{ - return loader->skip (loader->context, n); -} - -static int -cache_entry_load_magic (struct disfluid_cache_entry_loader *loader) -{ - uint8_t magic[16]; - int err = cache_entry_really_load_n (loader, 16, magic); - if (err) - { - return err; - } - if (memcmp (magic, "disfluid c.entry", 16) != 0) - { - return -2; - } - return 0; -} - -static int -cache_entry_load_timespec (struct disfluid_cache_entry_loader *loader, - struct timespec *timespec) -{ - uint8_t data[12]; - int err = cache_entry_really_load_n (loader, 12, data); - if (err) - { - return err; - } - timespec->tv_sec = 0; - timespec->tv_nsec = 0; - for (size_t i = 0; i < 8; i++) - { - timespec->tv_sec *= 256; - timespec->tv_sec += data[i]; - } - for (size_t i = 8; i < 12; i++) - { - timespec->tv_nsec *= 256; - timespec->tv_nsec += data[i]; - } - return 0; -} - -static int -cache_entry_load_flags (struct disfluid_cache_entry_loader *loader, - bool *invalidated) -{ - uint8_t data; - int err = cache_entry_really_load_n (loader, 1, &data); - if (err) - { - return err; - } - *invalidated = ((data & 0x80) != 0); - return 0; -} - -static int -cache_entry_skip_or_load_section (struct disfluid_cache_entry_loader *loader, - int mode, - int flag_bit, - int *restrict flags_value, - size_t *restrict length, - bool nul_terminate, - size_t max_data, char *restrict data) -{ - uint8_t size[sizeof (*length)] = { 0 }; - int error = cache_entry_really_load_n (loader, sizeof (size), size); - if (error) - { - return error; - } - *length = 0; - for (size_t i = 0; i < sizeof (size); i++) - { - *length *= 256; - *length += size[i]; - } - if (*length > max_data) - { - return -4; - } - if (mode <= 0) - { - if (mode < 0) - { - *flags_value = *flags_value | flag_bit; - if (max_data != 0) - { - *data = '\0'; - } - } - error = cache_entry_skip_n (loader, *length); - } - else - { - error = cache_entry_really_load_n (loader, *length, (uint8_t *) data); - } - if (error == 0 && nul_terminate) - { - /* We are allowed to access data[max_data]. */ - data[*length] = '\0'; - } - return error; -} - -static int -cache_entry_skip_or_load_key (struct disfluid_cache_entry_loader *loader, - int mode, - int *restrict flags, - size_t *restrict length, - size_t max_data, char *restrict data) -{ - int error = cache_entry_skip_or_load_section (loader, mode, KEY_NOT_LOADED, - flags, length, true, max_data, - data); - if (error == -4) - { - /* -4 means the recipient is too small. Coincidentally, it is - also the correct return value for cache_entry_load. */ - return -4; - } - return error; -} - -static int -cache_entry_skip_or_load_header (struct disfluid_cache_entry_loader *loader, - int mode, - int *restrict flags, - size_t *restrict length, - size_t max_data, char *restrict data) -{ - int error = - cache_entry_skip_or_load_section (loader, mode, HEADER_NOT_LOADED, - flags, length, true, max_data, data); - if (error == -4) - { - return -5; - } - return error; -} - -static int -cache_entry_skip_or_load_body (struct disfluid_cache_entry_loader *loader, - int mode, - int *restrict flags, - size_t *restrict length, - size_t max_data, char *restrict data) -{ - int error = cache_entry_skip_or_load_section (loader, mode, BODY_NOT_LOADED, - flags, length, true, max_data, - data); - if (error == -4) - { - return -6; - } - return error; -} - static int -cache_entry_load (struct disfluid_cache_entry *entry, - int load_key, - int load_header, - int load_body, - ssize_t (*read_impl) (void *, void *, size_t), - int (*skip) (void *, size_t), void *context) +represent_timespec (char *data, const struct timespec *ts) { - struct disfluid_cache_entry_loader loader = { - .read_impl = read_impl, - .skip = skip, - .context = context - }; - int error = 0; - struct timespec request_date, response_date; - bool invalidated; - if (error == 0) - { - error = cache_entry_load_magic (&loader); - } - if (error == 0) - { - error = cache_entry_load_timespec (&loader, &request_date); - } - if (error == 0) - { - error = cache_entry_load_timespec (&loader, &response_date); - } - if (error == 0) - { - error = cache_entry_load_flags (&loader, &invalidated); - } - if (error == 0) - { - error = - cache_entry_skip_or_load_key (&loader, load_key, &(entry->flags), - &(entry->key_length), entry->max_key, - cache_entry_key (entry)); - } - if (error == 0) - { - error = - cache_entry_skip_or_load_header (&loader, load_header, - &(entry->flags), - &(entry->header_length), - entry->max_header, - cache_entry_header (entry)); - } - if (error == 0) + struct timespec cp = {.tv_sec = ts->tv_sec,.tv_nsec = ts->tv_nsec }; + for (size_t i = 8; i-- > 0;) { - error = - cache_entry_skip_or_load_body (&loader, load_body, &(entry->flags), - &(entry->body_length), entry->max_body, - cache_entry_body (entry)); + data[i] = (char) (uint8_t) cp.tv_sec % 256; + cp.tv_sec /= 256; } - if (error == 0) + for (size_t i = 4; i-- > 0;) { - cache_entry_set_request_date (entry, &request_date); - cache_entry_set_response_date (entry, &response_date); - cache_entry_set_invalidated (entry, invalidated); + data[8 + i] = (char) (uint8_t) cp.tv_nsec % 256; + cp.tv_nsec /= 256; } - return error; -} - -static ssize_t -disfluid_cache_entry_loader_read (void *context, void *buffer, size_t max) -{ - int *fdp = context; - return read (*fdp, buffer, max); } -static int -disfluid_cache_entry_loader_lseek (void *context, size_t size) -{ - int *fdp = context; - off_t error = lseek (*fdp, size, SEEK_CUR); +MAYBE_UNUSED static int +db_read_cache_entry (const char *db_root, const string_desc_t * id, + struct timespec *request_date, + struct timespec *response_date, bool *invalidated, + string_desc_t * key_id, + string_desc_t * response_header_id, + string_desc_t * response_body_id) +{ + string_desc_t file_data = { 0 }; + request_date->tv_sec = 0; + request_date->tv_nsec = 0; + response_date->tv_sec = 0; + response_date->tv_nsec = 0; + *invalidated = false; + assert (key_id->_data == NULL); + assert (response_header_id->_data == NULL); + assert (response_body_id->_data == NULL); + key_id->_nbytes = 0; + response_header_id->_nbytes = 0; + response_body_id->_nbytes = 0; + int error = db_read (db_root, id, &file_data); if (error < 0) { - return -1; + goto cleanup; } - return 0; -} - -static ssize_t -disfluid_cache_entry_loader_fread (void *context, void *buffer, size_t max) -{ - assert (max <= SIZE_MAX); - FILE *f = context; - size_t n_read = fread (buffer, 1, max, f); - if (ferror (f)) + if (file_data._nbytes != 16 + 8 + 4 + 8 + 4 + 32 + 32 + 32 + 1) { - return -1; + error = -1; + goto cleanup; } - assert (n_read <= max); - assert (n_read <= SIZE_MAX); - return n_read; -} - -static int -disfluid_cache_entry_loader_fseek (void *context, size_t size) -{ - FILE *f = context; - off_t error = fseek (f, size, SEEK_CUR); - if (error < 0) + if (memcmp (file_data._data, "disfluid c.entry", 16) != 0) { - return -1; + error = -1; + goto cleanup; } - return 0; -} - -static int -cache_entry_read (struct disfluid_cache_entry *entry, int load_key, - int load_header, int load_body, int fd) -{ - int *fdp = &fd; - return cache_entry_load (entry, load_key, load_header, load_body, - disfluid_cache_entry_loader_read, - disfluid_cache_entry_loader_lseek, fdp); -} - -static int -cache_entry_fread (struct disfluid_cache_entry *entry, int load_key, - int load_header, int load_body, FILE * f) -{ - return cache_entry_load (entry, load_key, load_header, load_body, - disfluid_cache_entry_loader_fread, - disfluid_cache_entry_loader_fseek, f); -} - -static void -cache_entry_get_request_date (const struct disfluid_cache_entry *entry, - struct timespec *date) -{ - date->tv_sec = entry->request_date.tv_sec; - date->tv_nsec = entry->request_date.tv_nsec; -} - -static void -cache_entry_get_response_date (const struct disfluid_cache_entry *entry, - struct timespec *date) -{ - date->tv_sec = entry->response_date.tv_sec; - date->tv_nsec = entry->response_date.tv_nsec; -} - -static bool -cache_entry_is_invalidated (const struct disfluid_cache_entry *entry) -{ - return (entry->flags & INVALIDATED) != 0; -} - -static void -cache_entry_is_loaded (const struct disfluid_cache_entry *entry, - bool *key_loaded, bool *header_loaded, - bool *body_loaded) -{ - *key_loaded = !(entry->flags & KEY_NOT_LOADED); - *header_loaded = !(entry->flags & HEADER_NOT_LOADED); - *body_loaded = !(entry->flags & BODY_NOT_LOADED); -} - -struct disfluid_cache_entry_saver -{ - ssize_t (*write_impl) (void *, const void *, size_t); - void *context; -}; - -static size_t -cache_entry_careful_copy (size_t skip, size_t dest_max, char *dest, - size_t source_length, const char *source) -{ - size_t max = dest_max; - const char *relevant_source = NULL; - if (skip <= source_length) + const char *data = file_data._data + 16; + error = parse_timespec (data, request_date); + data += 12; + if (error != 0) { - relevant_source = &(source[skip]); - size_t max_source = source_length - skip; - max = max_source; - if (max > dest_max) - { - max = dest_max; - } - assert (skip + max <= source_length); - assert (max <= dest_max); + goto cleanup; } - else + error = parse_timespec (data, response_date); + data += 12; + if (error != 0) { - max = 0; + goto cleanup; } - memcpy (dest, relevant_source, max); - if (max < dest_max) - { - dest[max] = '\0'; - } - return source_length; -} - -static size_t -cache_entry_get_key (const struct disfluid_cache_entry *entry, size_t start, - size_t max, char *key) -{ - return cache_entry_careful_copy (start, max, key, entry->key_length, - cache_entry_key ((struct - disfluid_cache_entry *) - entry)); -} - -static size_t -cache_entry_get_header (const struct disfluid_cache_entry *entry, - size_t start, size_t max, char *header) -{ - return cache_entry_careful_copy (start, max, header, entry->header_length, - cache_entry_header ((struct - disfluid_cache_entry - *) entry)); -} - -static size_t -cache_entry_get_body (const struct disfluid_cache_entry *entry, size_t start, - size_t max, char *body) -{ - return cache_entry_careful_copy (start, max, body, entry->body_length, - cache_entry_body ((struct - disfluid_cache_entry *) - entry)); -} - -static int -cache_entry_really_save_n (struct disfluid_cache_entry_saver *saver, size_t n, - const uint8_t * data) -{ - while (n != 0) - { - ssize_t n_this_time = saver->write_impl (saver->context, data, n); - if (n_this_time < 0) - { - return -1; - } - else if (n_this_time == 0) - { - /* Impossible */ - abort (); - } - else - { - assert (n_this_time > 0); - n -= n_this_time; - data = &(data[n_this_time]); - } - } - return 0; -} - -static int -cache_entry_save_magic (struct disfluid_cache_entry_saver *saver) -{ - static const uint8_t magic[16] = "disfluid c.entry"; - return cache_entry_really_save_n (saver, 16, magic); -} - -static int -cache_entry_save_timespec (struct disfluid_cache_entry_saver *saver, - const struct timespec *ts) -{ - uint8_t data[12]; - time_t tv_sec = ts->tv_sec; - long tv_nsec = ts->tv_nsec; - assert (tv_nsec >= 0); - for (size_t i = 8; i-- > 0;) - { - data[i] = tv_sec % 256; - tv_sec /= 256; - } - for (size_t i = 12; i-- > 8;) - { - data[i] = tv_nsec % 256; - tv_nsec /= 256; - } - return cache_entry_really_save_n (saver, 12, data); -} - -static int -cache_entry_save_flags (struct disfluid_cache_entry_saver *saver, - bool invalidated) -{ - uint8_t value = 0; - if (invalidated) - { - value = value | 0x80; - } - return cache_entry_really_save_n (saver, 1, &value); -} - -static int -cache_entry_save_section (struct disfluid_cache_entry_saver *saver, - size_t length, const char *section) -{ - uint8_t size[sizeof (length)] = { 0 }; - size_t size_n = length; - for (size_t i = sizeof (length); i-- > 0;) - { - size[i] = size_n % 256; - size_n /= 256; - } - int error = cache_entry_really_save_n (saver, sizeof (length), size); - if (error == 0) - { - error = - cache_entry_really_save_n (saver, length, (const uint8_t *) section); - } - return error; -} - -static int -cache_entry_save (const struct disfluid_cache_entry *entry, - ssize_t (*write_impl) (void *context, const void *buffer, - size_t max_size), void *context) -{ - struct disfluid_cache_entry_saver saver = { - .write_impl = write_impl, - .context = context - }; - int error = 0; - if (entry->flags & (KEY_NOT_LOADED | HEADER_NOT_LOADED | BODY_NOT_LOADED)) + if (ALLOC_N (key_id->_data, 32) < 0) { error = -2; + goto cleanup; } - if (error == 0) - { - error = cache_entry_save_magic (&saver); - } - if (error == 0) + key_id->_nbytes = 32; + memcpy (key_id->_data, data, 32); + data += 32; + if (ALLOC_N (response_header_id->_data, 32) < 0) { - error = cache_entry_save_timespec (&saver, &(entry->request_date)); - } - if (error == 0) - { - error = cache_entry_save_timespec (&saver, &(entry->response_date)); - } - if (error == 0) - { - error = cache_entry_save_flags (&saver, !!(entry->flags & INVALIDATED)); - } - if (error == 0) - { - error = - cache_entry_save_section (&saver, entry->key_length, - cache_entry_key ((struct - disfluid_cache_entry *) - entry)); - } - if (error == 0) - { - error = - cache_entry_save_section (&saver, entry->header_length, - cache_entry_header ((struct - disfluid_cache_entry *) - entry)); + error = -2; + goto cleanup; } - if (error == 0) + response_header_id->_nbytes = 32; + memcpy (response_header_id->_data, data, 32); + data += 32; + if (ALLOC_N (response_body_id->_data, 32) < 0) { - error = - cache_entry_save_section (&saver, entry->body_length, - cache_entry_body ((struct - disfluid_cache_entry *) - entry)); - } + error = -2; + goto cleanup; + } + response_body_id->_nbytes = 32; + memcpy (response_body_id->_data, data, 32); + data += 32; + switch (*data) + { + case 0: + break; + case 80: + *invalidated = true; + break; + default: + error = -1; + goto cleanup; + } +cleanup: + if (error != 0) + { + FREE (key_id->_data); + FREE (response_header_id->_data); + FREE (response_body_id->_data); + } + FREE (file_data._data); return error; } -static ssize_t -disfluid_cache_entry_saver_write (void *context, const void *buffer, - size_t max) -{ - int *fdp = context; - return write (*fdp, buffer, max); -} - -static ssize_t -disfluid_cache_entry_saver_fwrite (void *context, const void *buffer, - size_t max) -{ - assert (max <= SIZE_MAX); - FILE *f = context; - size_t n_written = fwrite (buffer, 1, max, f); - if (ferror (f)) - { - return -1; - } - assert (n_written <= max); - assert (n_written <= SIZE_MAX); - return n_written; -} - -static int -cache_entry_write (const struct disfluid_cache_entry *entry, int fd) -{ - int *fdp = &fd; - return cache_entry_save (entry, disfluid_cache_entry_saver_write, fdp); -} - -static int -cache_entry_fwrite (const struct disfluid_cache_entry *entry, FILE * f) -{ - return cache_entry_save (entry, disfluid_cache_entry_saver_fwrite, f); -} - -static int -cache_entry_describe_date (const struct timespec *ts, const char *format, - char **description) +MAYBE_UNUSED static int +db_write_cache_entry (const char *db_root, string_desc_t * id, + const struct timespec *request_date, + const struct timespec *response_date, bool invalidated, + const string_desc_t * key_id, + const string_desc_t * response_header_id, + const string_desc_t * response_body_id) { - struct tm date; - struct tm *result = localtime_r (&(ts->tv_sec), &date); - if (result == NULL) - { - return -1; - } - char buffer[256]; - size_t n_buffer = strftime (buffer, sizeof (buffer), "%c", &date); - if (n_buffer == 0) + char file_data[16 + 8 + 4 + 8 + 4 + 32 + 32 + 32 + 1]; + if (key_id->_nbytes != 32 || response_header_id->_nbytes != 32 + || response_body_id->_nbytes != 32) { return -1; } - if (n_buffer >= sizeof (buffer)) - { - buffer[n_buffer - 1] = '\0'; - } - else - { - buffer[n_buffer] = '\0'; - } - /* TRANSLATORS: the argument is a date in the preferred format for - the locale. */ - int error = asprintf (description, format, buffer); - if (error < 0) + memcpy (file_data, "disfluid c.entry", 16); + represent_timespec (file_data + 16, request_date); + represent_timespec (file_data + 16 + 12, response_date); + memcpy (file_data + 16 + 12 + 12, key_id->_data, 32); + memcpy (file_data + 16 + 12 + 12 + 32, response_header_id->_data, 32); + memcpy (file_data + 16 + 12 + 12 + 32 + 32, response_body_id->_data, 32); + file_data[16 + 12 + 12 + 32 + 32 + 32] = 0; + if (invalidated) { - return -2; + file_data[16 + 12 + 12 + 32 + 32 + 32] = 80; } - return 0; -} - -static int -cache_entry_describe_request_date (const struct disfluid_cache_entry *entry, - char **description) -{ - struct timespec ts; - cache_entry_get_request_date (entry, &ts); - return cache_entry_describe_date (&ts, _("Requested %s"), description); -} - -static int -cache_entry_describe_response_date (const struct disfluid_cache_entry *entry, - char **description) -{ - struct timespec ts; - cache_entry_get_response_date (entry, &ts); - return cache_entry_describe_date (&ts, _("Responded %s"), description); + const string_desc_t sd_data = { + ._nbytes = sizeof (file_data), + ._data = file_data + }; + return db_write (db_root, id, &sd_data); } #endif /* DISFLUID_DISFLUID_CACHE_ENTRY_INCLUDED */ diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h index 74b1198..325f2ca 100644 --- a/src/libdisfluid/disfluid-tests.h +++ b/src/libdisfluid/disfluid-tests.h @@ -12,6 +12,7 @@ static inline char *run_tests (size_t *n_tests, size_t *n_errors); # include "disfluid-cache-entry.h" # include "disfluid-cache-entry-key.h" # include "disfluid-db.h" +# include "string-desc.h" # define BYTES * 1 @@ -25,41 +26,45 @@ static inline char *run_tests (size_t *n_tests, size_t *n_errors); # define BILLION THOUSAND MILLION -static inline int -test_tmp_file_with_content (size_t n, const uint8_t * content) +static void +prepare_database (char **filename) { - char name[] = "/tmp/disfluid-cache-entry-test-XXXXXX"; - int fd = mkstemp (name); - remove (name); - if (fd < 0) + if (ALLOC_N (*filename, strlen ("/tmp/check-disfluid-db-XXXXXX") + 1) < 0) { abort (); } - while (n > 0) + strcpy (*filename, "/tmp/check-disfluid-db-XXXXXX"); + if (mkdtemp (*filename) == NULL) { - ssize_t next = write (fd, content, n); - if (next <= 0) - { - abort (); - } - else if (next == 0) - { - /* Impossible */ - abort (); - } - else - { - assert (next > 0); - assert ((size_t) next <= n); - n -= next; - content = &(content[next]); - } + abort (); } - if (lseek (fd, 0, SEEK_SET) != 0) +} + +static int +cleanup_database (char **filename) +{ + int error = 0; + ck_assert_int_eq (db_unmark (*filename), 0); + ck_assert_int_eq (db_collect (*filename), 0); + for (size_t i = 0; i < 256; i++) { - abort (); + char *group_name = NULL; + ck_assert_int_ge (ALLOC_N + (group_name, + strlen (*filename) + strlen ("/") + 2 + 1), 0); + strcpy (group_name, *filename); + strcat (group_name, "/"); + static const char *alpha[] = { + "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "a", "b", "c", "d", "e", "f" + }; + strcat (group_name, alpha[i / 16]); + strcat (group_name, alpha[i % 16]); + rmdir (group_name); + FREE (group_name); } - return fd; + rmdir (*filename); + FREE (*filename); } /* *INDENT-OFF* */ @@ -79,424 +84,101 @@ START_TEST (test_read_invalid_magic_number) /* *INDENT-ON* */ { - uint8_t data[16 + 12 + 12 + 1] = { 0 }; + char *database; + prepare_database (&database); + string_desc_t file_id = { 0 }; + string_desc_t lit_id = { 0 }; + char data[16 + 12 + 12 + 32 + 32 + 32 + 1] = { 0 }; memcpy (data, "invalid magic no", 16); - int fd = - test_tmp_file_with_content (sizeof (data) / sizeof (data[0]), data); - if (fd < 0) - { - abort (); - } - struct disfluid_cache_entry *entry = - cache_entry_alloc (512 BYTES, 4 KILOBYTES, 2 MEGABYTES); - if (entry == NULL) - { - abort (); - } - int error = cache_entry_read (entry, true, true, true, fd); - cache_entry_free (entry); - close (fd); - ck_assert_int_eq (error, -2); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -static inline void -test_check_partial_situation (size_t n_partial) -{ - const uint8_t data[] = { 'd', 'i', 's', 'f', 'l', 'u', 'i', 'd', - ' ', 'c', '.', 'e', 'n', 't', 'r', 'y', - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, - 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, - 128, - 0, 0, 0, 0, 0, 0, 0, 25, - 'G', 'E', 'T', ' ', 'h', 't', 't', 'p', - 's', ':', '/', '/', 'e', 'x', 'a', 'm', - 'p', 'l', 'e', '.', 'c', 'o', 'm', '\r', - '\n', - 0, 0, 0, 0, 0, 0, 0, 22, - 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', - 'o', 'n', 's', 'e', ' ', 'h', 'e', 'a', - 'd', 'e', 'r', '.', '.', '.', - 0, 0, 0, 0, 0, 0, 0, 20, - 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', - 'o', 'n', 's', 'e', ' ', 'b', 'o', 'd', - 'y', '.', '.', '.' + const string_desc_t file_data = {._nbytes = sizeof (data),._data = data }; + static const char *lit_data = "hello :)"; + const string_desc_t lit = {._nbytes = strlen (lit_data),._data = + (char *) lit_data }; - assert (sizeof (data) == 132); - /* The data has a request date of 1s + 2ns, response of 3s + 4ns, - and is invalidated. */ - assert (n_partial <= sizeof (data) / sizeof (data[0])); - int fd = test_tmp_file_with_content (n_partial, data); - if (fd < 0) - { - abort (); - } - struct disfluid_cache_entry *entry = - cache_entry_alloc (512 BYTES, 4 KILOBYTES, 2 MEGABYTES); - if (entry == NULL) - { - abort (); - } - int error = cache_entry_read (entry, 1, 1, 1, fd); - if (n_partial < sizeof (data) / sizeof (data[0])) - { - ck_assert_int_eq (error, -3); - } - else - { - ck_assert_int_eq (error, 0); - struct timespec request, response; - cache_entry_get_request_date (entry, &request); - cache_entry_get_response_date (entry, &response); - bool invalidated = cache_entry_is_invalidated (entry); - char key[512 BYTES]; - char header[4 KILOBYTES]; - char body[4 KILOBYTES]; /* Do NOT allocate 2 megabytes on the - stack, valgrind finds it - offensive. */ - ck_assert_int_eq (request.tv_sec, 1); - ck_assert_int_eq (request.tv_nsec, 2); - ck_assert_int_eq (response.tv_sec, 3); - ck_assert_int_eq (response.tv_nsec, 4); - ck_assert (invalidated); - ck_assert_int_eq (cache_entry_get_key (entry, 0, sizeof (key), key), - 25); - ck_assert_int_eq (cache_entry_get_header - (entry, 0, sizeof (header), header), 22); - ck_assert_int_eq (cache_entry_get_body (entry, 0, sizeof (body), body), - 20); - body[strlen ("the response body...")] = '\0'; - ck_assert_str_eq (key, "GET https://example.com\r\n"); - ck_assert_str_eq (header, "the response header..."); - ck_assert_str_eq (body, "the response body..."); - } - cache_entry_free (entry); - close (fd); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -START_TEST (test_read_cache_file_partial_0) -/* *INDENT-ON* */ - -{ - test_check_partial_situation (0); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -START_TEST (test_read_cache_file_partial_1) -/* *INDENT-ON* */ - -{ - test_check_partial_situation (1); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -START_TEST (test_read_cache_file_partial_16) -/* *INDENT-ON* */ - -{ - test_check_partial_situation (16); -} -/* *INDENT-OFF* */ -END_TEST - -/* *INDENT-ON* */ - -START_TEST (test_read_cache_file_partial_17) -/* *INDENT-ON* */ -{ - test_check_partial_situation (17); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_28) -/* *INDENT-ON* */ -{ - test_check_partial_situation (28); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_29) -/* *INDENT-ON* */ -{ - test_check_partial_situation (29); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_36) -/* *INDENT-ON* */ -{ - test_check_partial_situation (36); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_37) -/* *INDENT-ON* */ -{ - test_check_partial_situation (37); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_40) -/* *INDENT-ON* */ -{ - test_check_partial_situation (40); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_41) -/* *INDENT-ON* */ -{ - test_check_partial_situation (41); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_50) -/* *INDENT-ON* */ -{ - test_check_partial_situation (50); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_131) -/* *INDENT-ON* */ -{ - test_check_partial_situation (131); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_read_cache_file_partial_132) -/* *INDENT-ON* */ -{ - test_check_partial_situation (132); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-ON* */ -START_TEST (test_load_and_shrink) -/* *INDENT-ON* */ -{ - /* This pattern lets you load a cache entry on the stack, with a - maximum size, but not knowing the required size beforehand. The - resulting entry will not waste any room on the stack (except for - alignment and padding…). */ - /* 1. Create a large entry. */ - /* 2. Load data into the large entry. */ - /* 3. Push a minimal entry on the stack. */ - /* 4. Copy the contents to the minimal entry. */ - /* 5. Reinitialize the initial entry. */ - /* 6. Copy the second entry to the initial entry. */ - /* 7. Shrink the stack. */ - /* No copy operation can fail here. */ - size_t default_key_size = 512; - size_t default_header_size = 4096; - size_t default_body_size = 2 * 1024 * 1024; - struct disfluid_cache_entry *entry; - assert (sizeof (entry) == sizeof (size_t)); - const size_t required_size = - cache_entry_size (default_key_size, default_header_size, - default_body_size); - const size_t required_alignment = cache_entry_alignment (); - entry = calloc (1, required_size); - if (entry == NULL) - { - abort (); - } - size_t address; - memcpy (&address, &entry, sizeof (entry)); - ck_assert_int_eq (address % required_alignment, 0); - cache_entry_init (entry, default_key_size, default_header_size, - default_body_size); + ck_assert_int_eq (db_write (database, &lit_id, &lit), 0); + memcpy (data + 16 + 12 + 12, lit_id._data, lit_id._nbytes); + memcpy (data + 16 + 12 + 12 + 32, lit_id._data, lit_id._nbytes); + memcpy (data + 16 + 12 + 12 + 32 + 32, lit_id._data, lit_id._nbytes); + FREE (lit_id._data); + ck_assert_int_eq (db_write (database, &file_id, &file_data), 0); struct timespec request_date, response_date; - request_date.tv_sec = 42; - request_date.tv_nsec = 69; - response_date.tv_sec = 118; - response_date.tv_nsec = 218; - cache_entry_set_request_date (entry, &request_date); - cache_entry_set_response_date (entry, &response_date); - cache_entry_set_invalidated (entry, true); - size_t really_used_key_size, really_used_header_size, really_used_body_size; - cache_entry_minimum_size (entry, &really_used_key_size, - &really_used_header_size, &really_used_body_size); - struct disfluid_cache_entry *best_fit; - const size_t really_used_size = - cache_entry_size (really_used_key_size, really_used_header_size, - really_used_body_size); - best_fit = calloc (1, really_used_size); - if (best_fit == NULL) - { - abort (); - } - cache_entry_init (best_fit, really_used_key_size, really_used_header_size, - really_used_body_size); - int copy_error = cache_entry_copy (best_fit, entry); - ck_assert_int_eq (copy_error, 0); - cache_entry_init (entry, really_used_key_size, really_used_header_size, - really_used_body_size); - copy_error = cache_entry_copy (entry, best_fit); - ck_assert_int_eq (copy_error, 0); - struct disfluid_cache_entry *shrinked = realloc (entry, really_used_size); - assert (shrinked != NULL); - entry = shrinked; - free (best_fit); - struct timespec check_request_date, check_response_date; - cache_entry_get_request_date (entry, &check_request_date); - cache_entry_get_response_date (entry, &check_response_date); - bool check_invalidated = cache_entry_is_invalidated (entry); - ck_assert_int_eq (check_request_date.tv_sec, 42); - ck_assert_int_eq (check_request_date.tv_nsec, 69); - ck_assert_int_eq (check_response_date.tv_sec, 118); - ck_assert_int_eq (check_response_date.tv_nsec, 218); - ck_assert (check_invalidated); - free (entry); + bool invalidated; + string_desc_t key_id = { 0 }, response_header_id = { 0 }, response_body_id = + { 0 }; + ck_assert_int_lt (db_read_cache_entry + (database, &file_id, &request_date, &response_date, + &invalidated, &key_id, &response_header_id, + &response_body_id), 0); + FREE (key_id._data); + FREE (response_header_id._data); + FREE (response_body_id._data); + FREE (file_id._data); + cleanup_database (&database); } /* *INDENT-OFF* */ END_TEST /* *INDENT-ON* */ /* *INDENT-OFF* */ -START_TEST (test_write_cache_entry) +START_TEST (test_read_normal) /* *INDENT-ON* */ { - uint8_t old_data[16 + 12 + 12 + 1 + 8 + 8 + 8 + 1024] = { 0 }; - memcpy (old_data, "disfluid c.entry", 16); - old_data[16 + 8 - 1] = 1; - old_data[16 + 12 - 1] = 2; - old_data[16 + 12 + 8 - 1] = 3; - old_data[16 + 12 + 12 - 1] = 4; - old_data[16 + 12 + 12 + 1 - 1] = 0x80; - /* The old data has a request date of 1s + 2ns, response of 3s + - 4ns, and is invalidated. */ - int fd = - test_tmp_file_with_content (sizeof (old_data) / sizeof (old_data[0]), - old_data); - if (fd < 0) - { - abort (); - } - struct disfluid_cache_entry *entry = - cache_entry_alloc (512 BYTES, 4 KILOBYTES, 2 MEGABYTES); - if (entry == NULL) - { - abort (); - } - struct timespec request, response; - request.tv_sec = 10; - request.tv_nsec = 11; - response.tv_sec = 12; - response.tv_nsec = 13; - cache_entry_set_request_date (entry, &request); - cache_entry_set_response_date (entry, &response); - cache_entry_set_invalidated (entry, false); - cache_entry_set_key (entry, "GET https://example.com\r\n"); - cache_entry_set_response_header (entry, "the response header..."); - cache_entry_set_response_body (entry, strlen ("the response body..."), - "the response body..."); - int error = cache_entry_write (entry, fd); - ck_assert_int_eq (error, 0); - uint8_t check_data[16 + 12 + 12 + 1 + 8 + 8 + 8 + 25 + 22 + 20]; - error = lseek (fd, 0, SEEK_SET); - ck_assert_int_eq (error, 0); - struct disfluid_cache_entry_loader read_loader = { - .read_impl = disfluid_cache_entry_loader_read, - .context = &fd + 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 }; - int check_error = - (cache_entry_really_load_n - (&read_loader, (sizeof (check_data) / sizeof (check_data[0])), - check_data)); - ck_assert_int_eq (check_error, 0); - static const uint8_t expected_data[] = - { 'd', 'i', 's', 'f', 'l', 'u', 'i', 'd', - ' ', 'c', '.', 'e', 'n', 't', 'r', 'y', - 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 11, - 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 13, - 0, - 0, 0, 0, 0, 0, 0, 0, 25, - 'G', 'E', 'T', ' ', 'h', 't', 't', 'p', - 's', ':', '/', '/', 'e', 'x', 'a', 'm', - 'p', 'l', 'e', '.', 'c', 'o', 'm', '\r', - '\n', - 0, 0, 0, 0, 0, 0, 0, 22, - 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', - 'o', 'n', 's', 'e', ' ', 'h', 'e', 'a', - 'd', 'e', 'r', '.', '.', '.', - 0, 0, 0, 0, 0, 0, 0, 20, - 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', - 'o', 'n', 's', 'e', ' ', 'b', 'o', 'd', - 'y', '.', '.', '.', + const string_desc_t header = {._nbytes = strlen (header_value),._data = + (char *) header_value }; - ck_assert_int_eq (sizeof (expected_data), sizeof (check_data)); - for (size_t i = 0; i < sizeof (expected_data); i++) - { - if (check_data[i] != expected_data[i]) - { - fprintf (stderr, "%s:%d: %lu: %d vs %d.\n", __FILE__, __LINE__, i, - (int) check_data[i], (int) expected_data[i]); - } - } - ck_assert_int_eq (memcmp - (check_data, expected_data, sizeof (expected_data)), 0); - close (fd); - cache_entry_free (entry); -} -/* *INDENT-OFF* */ -END_TEST -/* *INDENT-ON* */ - -/* *INDENT-OFF* */ -START_TEST (test_normalize_timespec) -/* *INDENT-ON* */ - -{ - struct timespec ts = { - .tv_sec = 42, - .tv_nsec = 2 BILLION + 123 MILLION + 456 THOUSAND + 789 + const string_desc_t body = {._nbytes = strlen (body_value),._data = + (char *) body_value }; - cache_entry_normalize_timespec (&ts); - ck_assert_int_eq (ts.tv_sec, 44); - ck_assert_int_eq (ts.tv_nsec, 123 MILLION + 456 THOUSAND + 789); + string_desc_t key_id = { 0 }; + string_desc_t header_id = { 0 }; + string_desc_t body_id = { 0 }; + string_desc_t entry_id = { 0 }; + const struct timespec request_date = {.tv_sec = 12345,.tv_nsec = 678910 }; + const struct timespec response_date = {.tv_sec = 111213,.tv_nsec = 141516 }; + char *database; + prepare_database (&database); + ck_assert_int_eq (db_write (database, &key_id, &key), 0); + ck_assert_int_eq (db_write (database, &header_id, &header), 0); + ck_assert_int_eq (db_write (database, &body_id, &body), 0); + ck_assert_int_eq (db_write_cache_entry + (database, &entry_id, &request_date, &response_date, true, + &key_id, &header_id, &body_id), 0); + string_desc_t check_key_id = { 0 }; + string_desc_t check_header_id = { 0 }; + string_desc_t check_body_id = { 0 }; + struct timespec check_request_date, check_response_date; + bool check_invalidated; + ck_assert_int_eq (db_read_cache_entry + (database, &entry_id, &check_request_date, + &check_response_date, &check_invalidated, &check_key_id, + &check_header_id, &check_body_id), 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_id._nbytes, 32); + ck_assert_int_eq (check_header_id._nbytes, 32); + ck_assert_int_eq (check_body_id._nbytes, 32); + ck_assert_int_eq (memcmp (check_key_id._data, key_id._data, 32), 0); + ck_assert_int_eq (memcmp (check_header_id._data, header_id._data, 32), 0); + ck_assert_int_eq (memcmp (check_body_id._data, body_id._data, 32), 0); + FREE (check_key_id._data); + FREE (check_header_id._data); + FREE (check_body_id._data); + FREE (key_id._data); + FREE (header_id._data); + FREE (body_id._data); + FREE (entry_id._data); + cleanup_database (&database); } /* *INDENT-OFF* */ END_TEST @@ -779,26 +461,9 @@ run_tests (size_t *n_tests, size_t *n_errors) TCase *general = tcase_create (_("disfluid general tests")); tcase_add_test (general, test_check_version); suite_add_tcase (suite, general); - TCase *time_functions = tcase_create (_("disfluid time functions")); - tcase_add_test (time_functions, test_normalize_timespec); - suite_add_tcase (suite, time_functions); TCase *cache_entry = tcase_create (_("disfluid cache entry files")); + tcase_add_test (cache_entry, test_read_normal); tcase_add_test (cache_entry, test_read_invalid_magic_number); - tcase_add_test (cache_entry, test_read_cache_file_partial_0); - tcase_add_test (cache_entry, test_read_cache_file_partial_1); - tcase_add_test (cache_entry, test_read_cache_file_partial_16); - tcase_add_test (cache_entry, test_read_cache_file_partial_17); - tcase_add_test (cache_entry, test_read_cache_file_partial_28); - tcase_add_test (cache_entry, test_read_cache_file_partial_29); - tcase_add_test (cache_entry, test_read_cache_file_partial_36); - tcase_add_test (cache_entry, test_read_cache_file_partial_37); - tcase_add_test (cache_entry, test_read_cache_file_partial_40); - tcase_add_test (cache_entry, test_read_cache_file_partial_41); - tcase_add_test (cache_entry, test_read_cache_file_partial_50); - tcase_add_test (cache_entry, test_read_cache_file_partial_131); - tcase_add_test (cache_entry, test_read_cache_file_partial_132); - tcase_add_test (cache_entry, test_load_and_shrink); - tcase_add_test (cache_entry, test_write_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); diff --git a/src/libdisfluid/main.c b/src/libdisfluid/main.c index 5aab482..dbe7cfb 100644 --- a/src/libdisfluid/main.c +++ b/src/libdisfluid/main.c @@ -124,197 +124,6 @@ disfluid_copyright_statement (void) return copyright_statement (); } -size_t -disfluid_cache_entry_size (size_t max_key, size_t max_header, size_t max_body) -{ - return cache_entry_size (max_key, max_header, max_body); -} - -size_t -disfluid_cache_entry_alignment (void) -{ - return cache_entry_alignment (); -} - -void -disfluid_cache_entry_init (struct disfluid_cache_entry *entry, - size_t max_key, size_t max_header, size_t max_body) -{ - cache_entry_init (entry, max_key, max_header, max_body); -} - -void -disfluid_cache_entry_minimum_size (const struct disfluid_cache_entry *entry, - size_t *min_key, size_t *min_header, - size_t *min_body) -{ - cache_entry_minimum_size (entry, min_key, min_header, min_body); -} - -int -disfluid_cache_entry_copy (struct disfluid_cache_entry *restrict dest, - const struct disfluid_cache_entry *restrict src) -{ - return cache_entry_copy (dest, src); -} - -struct disfluid_cache_entry * -disfluid_cache_entry_alloc (size_t max_key, size_t max_header, - size_t max_body) -{ - return cache_entry_alloc (max_key, max_header, max_body); -} - -struct disfluid_cache_entry * -disfluid_cache_entry_dup (const struct disfluid_cache_entry *entry) -{ - return cache_entry_dup (entry); -} - -void -disfluid_cache_entry_free (struct disfluid_cache_entry *entry) -{ - return cache_entry_free (entry); -} - -void -disfluid_cache_entry_set_request_date (struct disfluid_cache_entry *entry, - const struct timespec *date) -{ - cache_entry_set_request_date (entry, date); -} - -void -disfluid_cache_entry_set_response_date (struct disfluid_cache_entry *entry, - const struct timespec *date) -{ - cache_entry_set_response_date (entry, date); -} - -void -disfluid_cache_entry_invalidate (struct disfluid_cache_entry *entry) -{ - cache_entry_invalidate (entry); -} - -void -disfluid_cache_entry_set_invalidated (struct disfluid_cache_entry *entry, - int invalidated) -{ - cache_entry_set_invalidated (entry, invalidated); -} - -int -disfluid_cache_entry_set_key (struct disfluid_cache_entry *entry, - const char *key) -{ - return cache_entry_set_key (entry, key); -} - -int -disfluid_cache_entry_set_response_header (struct disfluid_cache_entry *entry, - const char *header) -{ - return cache_entry_set_response_header (entry, header); -} - -int -disfluid_cache_entry_set_response_body (struct disfluid_cache_entry *entry, - size_t body_length, const char *body) -{ - return cache_entry_set_response_body (entry, body_length, body); -} - -void -disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry - *entry, struct timespec *date) -{ - cache_entry_get_request_date (entry, date); -} - -void -disfluid_cache_entry_get_response_date (const struct disfluid_cache_entry - *entry, struct timespec *date) -{ - cache_entry_get_response_date (entry, date); -} - -int -disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry *entry) -{ - return cache_entry_is_invalidated (entry); -} - -size_t -disfluid_cache_entry_get_key (const struct disfluid_cache_entry *entry, - size_t start, size_t max, char *key) -{ - return cache_entry_get_key (entry, start, max, key); -} - -size_t -disfluid_cache_entry_get_header (const struct disfluid_cache_entry *entry, - size_t start, size_t max, char *header) -{ - return cache_entry_get_header (entry, start, max, header); -} - -size_t -disfluid_cache_entry_get_body (const struct disfluid_cache_entry *entry, - size_t start, size_t max, char *body) -{ - return cache_entry_get_body (entry, start, max, body); -} - -int -disfluid_cache_entry_load (struct disfluid_cache_entry *entry, - int load_key, - int load_header, - int load_body, - ssize_t (*read_impl) (void *, void *, size_t), - int (*skip) (void *, size_t), void *context) -{ - return cache_entry_load (entry, load_key, load_header, load_body, read_impl, - skip, context); -} - -int -disfluid_cache_entry_save (const struct disfluid_cache_entry *entry, - ssize_t (*write_impl) (void *, const void *, - size_t), void *context) -{ - return cache_entry_save (entry, write_impl, context); -} - -int -disfluid_cache_entry_read (struct disfluid_cache_entry *entry, - int read_key, - int read_header, int read_body, int fd) -{ - return cache_entry_read (entry, read_key, read_header, read_body, fd); -} - -int -disfluid_cache_entry_fread (struct disfluid_cache_entry *entry, - int read_key, - int read_header, int read_body, FILE * f) -{ - return cache_entry_fread (entry, read_key, read_header, read_body, f); -} - -int -disfluid_cache_entry_write (const struct disfluid_cache_entry *entry, int fd) -{ - return cache_entry_write (entry, fd); -} - -int -disfluid_cache_entry_fwrite (const struct disfluid_cache_entry *entry, - FILE * f) -{ - return cache_entry_fwrite (entry, f); -} - int disfluid_compute_cache_key (const char *request_scheme, const char *request_header, @@ -347,17 +156,3 @@ disfluid_metaphor_name (void) { return metaphor_name (); } - -int -disfluid_cache_entry_describe_request_date (const struct disfluid_cache_entry - *entry, char **description) -{ - return cache_entry_describe_request_date (entry, description); -} - -int -disfluid_cache_entry_describe_response_date (const struct disfluid_cache_entry - *entry, char **description) -{ - return cache_entry_describe_response_date (entry, description); -} diff --git a/src/vala/Makefile.am b/src/vala/Makefile.am index a0e4279..54481e8 100644 --- a/src/vala/Makefile.am +++ b/src/vala/Makefile.am @@ -19,7 +19,6 @@ bin_PROGRAMS += %D%/disfluid %C%_disfluid_SOURCES = \ %D%/main.vala \ %D%/about.vala \ - %D%/cache_entry_widget.vala \ %D%/main_window.vala \ %D%/disfluid-$(DLL_VERSION).vapi diff --git a/src/vala/main.vala b/src/vala/main.vala index 535baf6..256a684 100644 --- a/src/vala/main.vala +++ b/src/vala/main.vala @@ -9,16 +9,7 @@ int main (string[] args) { ApplicationFlags.FLAGS_NONE ); app.activate.connect(() => { - var cache_entry = new Disfluid.CacheEntry.alloc (512, 4096, 2 * 1024 * 1024); - cache_entry.set_request_gdate (new GLib.DateTime.utc (2023, 03, 26, 19, 38, 00)); - cache_entry.set_response_gdate (new GLib.DateTime.now ()); - cache_entry.set_key ("GET https://example.com\r\n"); - cache_entry.set_response_header ("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n"); - cache_entry.set_response_body ((char[]) "Hello"); - var cache_entry_view = new Disfluid.CacheEntryView.with_value ("/tmp/test.cache", cache_entry); - var cache_view = new Adw.PreferencesPage (); - cache_view.add (cache_entry_view); - var window = new Disfluid.MainWindow (cache_view); + var window = Disfluid.make_about_window (); window.set_application (app); window.present(); }); -- cgit v1.2.3