summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-04-02 22:40:51 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2023-04-29 11:58:03 +0200
commit15435a5508ef6b8f553bd1a3d244801d51b50ccd (patch)
treef221401c76249eef7f22e76a922c29bdd7663d80
parentfd5e359529049415cffba965b10a7afe85093c31 (diff)
Change the cache entry API to use the database API
-rw-r--r--doc/disfluid.texi163
-rw-r--r--include/Makefile.am3
-rw-r--r--include/disfluid-gobject.h52
-rw-r--r--include/disfluid.h8
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/gir/Makefile.am2
-rw-r--r--src/gobject/main.c49
-rw-r--r--src/libdisfluid/disfluid-cache-entry.h1182
-rw-r--r--src/libdisfluid/disfluid-tests.h561
-rw-r--r--src/libdisfluid/main.c205
-rw-r--r--src/vala/Makefile.am1
-rw-r--r--src/vala/main.vala11
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 <disfluid/cache_entry.h>
-
#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 <disfluid/cache_entry.h>
-
#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 <config.h>
+# include "string-desc.h"
+# include <stdbool.h>
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 <assert.h>
-# include <flexmember.h>
-
-# 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();
});