BLog |
|
---|
Litmus and Prestan tests of Cyclaero’s embedded WebDAV serverMy company Cyclaero Ltda. develops and ships device controllers running an embedded WebDAV enabled HTTP server written in C, which is an essential part of the web application by which measurements are executed and the results are presented to the operator. The measurement files can be accessed via WebDAV. The software runs on FreeBSD systems, either headless (x86 and ARM) or on x86 with GNOME 3 desktops. The performance test suite Prestan and the compliance test suite Litmus have been employed for verifying the performance and compliance of our WebDAV service. While Litmus worked out of the box, Prestan needed some fixes for running on FreeBSD and macOS clients. The Litmus compliance test
The Cyclaero HTTP/WebDAV server passes all Litmus compliance tests by 100 %. The Prestan performance testAs stated already, Prestan does not work out of the box on macOS, and here I provide a patch file which can be applied to the original sources: diff -ru Prestan/Makefile.in Prestan-fixed/Makefile.in --- Prestan/Makefile.in 2007-08-20 15:38:43.000000000 -0300 +++ Prestan-fixed/Makefile.in 2022-02-14 13:21:21.000000000 -0300 @@ -16,7 +16,7 @@ LDFLAGS = @LDFLAGS@ LIBS = @NEON_LIBS@ @LIBS@ # expat may be in LIBOBJS, so must come after $(LIBS) (which has -lneon) -ALL_LIBS = -L. -ltest -lm -g $(LIBS) $(LIBOBJS) +ALL_LIBS = -L. -ltest -lm $(LIBS) $(LIBOBJS) top_builddir = . top_srcdir = @top_srcdir@ @@ -97,7 +97,11 @@ $(RANLIB) $@ clean: - rm -f */*.o $(TESTS) libtest.a + cd libneon && $(MAKE) clean + -rm -f */*.o $(TESTS) libtest.a + +distclean: clean + -rm -f config.log config.status config.h Makefile libneon/Makefile .c.o: $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ @@ -112,3 +116,4 @@ src/xmloutput.o: src/xmloutput.c $(HDRS) src/acl.o: src/acl.c $(HDRS) +.PHONY: clean distclean diff -ru Prestan/configure.in Prestan-fixed/configure.in --- Prestan/configure.in 2007-06-13 18:14:04.000000000 -0300 +++ Prestan-fixed/configure.in 2022-02-14 13:22:12.000000000 -0300 @@ -25,7 +25,7 @@ ]) dnl Check for getopt_long -AC_CHECK_FUNC(getopt_long,,[AC_LIBOBJ(lib/getopt); AC_LIBOBJ(lib/getopt1)]) +AC_CHECK_FUNC(getopt_long,,[AC_LIBOBJ(lib/getopt) AC_LIBOBJ(lib/getopt1)]) NEON_DEBUG NEON_WARNINGS diff -ru Prestan/libneon/memleak.h Prestan-fixed/libneon/memleak.h --- Prestan/libneon/memleak.h 2007-06-13 18:14:02.000000000 -0300 +++ Prestan-fixed/libneon/memleak.h 2022-02-14 10:30:33.000000000 -0300 @@ -26,6 +26,7 @@ * wrappers in ne_alloc.c, which perform simple leak detection. It * MUST NOT BE INSTALLED, or used from neon applications. */ +#if 0 #ifndef MEMLEAK_H #define MEMLEAK_H @@ -53,3 +54,4 @@ extern size_t ne_alloc_used; #endif /* MEMLEAK_H */ +#endif diff -ru Prestan/libneon/ne_basic.c Prestan-fixed/libneon/ne_basic.c --- Prestan/libneon/ne_basic.c 2007-06-13 18:14:02.000000000 -0300 +++ Prestan-fixed/libneon/ne_basic.c 2022-02-14 13:44:45.000000000 -0300 @@ -100,6 +100,8 @@ int ne_put(ne_session *sess, const char *uri, int fd) { ne_request *req = ne_request_create(sess, "PUT", uri); + if (fd < 0) + ne_add_request_header(req, "Content-Length", "0"); int ret; #ifdef USE_DAV_LOCKS diff -ru Prestan/libneon/ne_locks.c Prestan-fixed/libneon/ne_locks.c --- Prestan/libneon/ne_locks.c 2007-06-13 18:14:02.000000000 -0300 +++ Prestan-fixed/libneon/ne_locks.c 2022-02-14 13:33:17.000000000 -0300 @@ -90,10 +90,11 @@ #define NE_ELM_owner (NE_ELM_LOCK_FIRST + 5) #define NE_ELM_timeout (NE_ELM_LOCK_FIRST + 6) #define NE_ELM_locktoken (NE_ELM_LOCK_FIRST + 7) -#define NE_ELM_lockinfo (NE_ELM_LOCK_FIRST + 8) -#define NE_ELM_write (NE_ELM_LOCK_FIRST + 9) -#define NE_ELM_exclusive (NE_ELM_LOCK_FIRST + 10) -#define NE_ELM_shared (NE_ELM_LOCK_FIRST + 11) +#define NE_ELM_lockroot (NE_ELM_LOCK_FIRST + 8) +#define NE_ELM_lockinfo (NE_ELM_LOCK_FIRST + 9) +#define NE_ELM_write (NE_ELM_LOCK_FIRST + 10) +#define NE_ELM_exclusive (NE_ELM_LOCK_FIRST + 11) +#define NE_ELM_shared (NE_ELM_LOCK_FIRST + 13) static const struct ne_xml_elm lock_elms[] = { #define A(x) { "DAV:", #x, NE_ELM_ ## x, NE_XML_COLLECT } /* ANY */ @@ -102,7 +103,7 @@ #define E(x) { "DAV:", #x, NE_ELM_ ## x, 0 /* LEAF */ } /* EMPTY */ D(lockdiscovery), D(activelock), D(prop), - D(lockscope), D(locktype), C(depth), A(owner), C(timeout), D(locktoken), + D(lockscope), D(locktype), C(depth), A(owner), C(timeout), D(locktoken), D(lockroot), /* no lockentry */ D(lockinfo), D(lockscope), D(locktype), E(write), E(exclusive), E(shared), @@ -116,6 +117,7 @@ static const ne_propname lock_props[] = { { "DAV:", "lockdiscovery" }, + { "DAV:", "lockroot" }, { NULL } }; @@ -441,6 +443,7 @@ case NE_ELM_owner: case NE_ELM_timeout: case NE_ELM_locktoken: + case NE_ELM_lockroot: return NE_XML_VALID; default: break; @@ -460,6 +463,7 @@ break; /* ... depth is PCDATA, owner is COLLECT, timeout is PCDATA */ case NE_ELM_locktoken: + case NE_ELM_lockroot: if (child == NE_ELM_href) return NE_XML_VALID; break; @@ -668,6 +672,7 @@ if (value[0] == '<') value++; ctx->token = ne_strdup(value); ne_shave(ctx->token, ">"); + ctx->found = 1; } int ne_lock(ne_session *sess, struct ne_lock *lock) diff -ru Prestan/libneon/ne_socket.c Prestan-fixed/libneon/ne_socket.c --- Prestan/libneon/ne_socket.c 2007-06-13 18:14:02.000000000 -0300 +++ Prestan-fixed/libneon/ne_socket.c 2022-02-13 22:33:50.000000000 -0300 @@ -838,7 +838,7 @@ return NULL; val = 1; - if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val)) < 0){ + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) < 0){ perror("setsockopt() :"); return -1; } diff -ru Prestan/src/common.c Prestan-fixed/src/common.c --- Prestan/src/common.c 2007-09-06 16:25:40.000000000 -0300 +++ Prestan-fixed/src/common.c 2022-02-14 13:38:38.000000000 -0300 @@ -397,6 +397,8 @@ pget_option.requests = old_requests; printf ( "Done\n" ); g_echo = 1; + + return OK; } int begin ( void ) @@ -487,16 +489,11 @@ return ret; } -inline int latency ( struct timeval tv1, struct timeval tv2 ) -{ - return ( ( tv2.tv_sec-tv1.tv_sec ) *1000000+ ( tv2.tv_usec-tv1.tv_usec ) ); -} - int my_mkcol ( char* uri, int depth ) { char myuri[128]; - int i, ret; + int i, ret = -1; if ( depth > 1 ) { @@ -506,9 +503,9 @@ if ( ret=ne_mkcol ( i_session, myuri ) ) { printf ( "my_mkcol failed 1\n" ); - return ret; + return -1; } - my_mkcol ( myuri, depth-1 ); + ret = my_mkcol ( myuri, depth-1 ); } else if ( depth == 1 ) for ( i=0; i<pget_option.width; i++ ) @@ -518,8 +515,8 @@ sprintf ( myuri, "%ssub%d/", myuri, i ); if ( ret=ne_mkcol ( i_session, myuri ) ) { - return ret; printf ( "my_mkcol failed 2\n" ); + return ret; } } @@ -534,12 +531,12 @@ { char tmp[256] = "/tmp/Davtest-XXXXXX"; char myuri[128]; - int i, fd; + int i, fd, ret = -1; if ( ( fd=mkstemp ( tmp ) ) < 0 ) { perror ( "mkstemp() :" ); - return ; + return -1; } for ( i=0; i<4; i++ ) @@ -553,9 +550,9 @@ if ( ne_mkcol ( i_session, myuri ) ) { printf ( "ne_mkcol failed\n" ); - return; + return -1; } - my_mkcol2 ( myuri, depth-1 ); + ret = my_mkcol2 ( myuri, depth-1 ); } else if ( depth == 1 ) for ( i=0; i<pget_option.width; i++ ) @@ -566,25 +563,25 @@ if ( ne_put ( i_session, myuri, fd ) ) { printf ( "ne_put failed\n" ); - return; + return -1; } } unlink ( tmp ); - return; + return ret; } int my_mkcol2_proppatch ( char* uri, int depth, const ne_propname pops[] ) { char tmp[256] = "/tmp/Davtest-XXXXXX"; char myuri[128]; - int i, fd; + int i, fd, ret = -1; if ( ( fd=mkstemp ( tmp ) ) < 0 ) { perror ( "mkstemp() :" ); - return ; + return -1; } for ( i=0; i<4; i++ ) @@ -598,7 +595,7 @@ ONV ( ne_mkcol ( i_session, myuri ), ( "MKCOL %s: %s", myuri, ne_get_error ( i_session ) ) ); ONMREQ ( "PROPPATCH",myuri, ne_proppatch ( i_session, myuri, pops ) ); - my_mkcol2 ( myuri, depth-1 ); + ret = my_mkcol2 ( myuri, depth-1 ); } else if ( depth == 1 ) for ( i=0; i<pget_option.width; i++ ) @@ -609,7 +606,8 @@ ONV ( ne_put ( i_session, myuri, fd ), ( "PUT of %s: %s", myuri, ne_get_error ( i_session ) ) ); } - return ; + + return ret; } diff -ru Prestan/src/common.h Prestan-fixed/src/common.h --- Prestan/src/common.h 2007-08-26 15:00:43.000000000 -0300 +++ Prestan-fixed/src/common.h 2022-02-14 00:44:19.000000000 -0300 @@ -69,6 +69,8 @@ /* Upload htdocs/foo to i_path + path */ int upload_foo ( const char *path ); +void my_printf ( char *src ); + /* for method 'method' on 'uri', do operation 'x'. */ #define ONMREQ(method, uri, x) do { int _ret = (x); if (_ret) { t_context("%s on `%s': %s", method, uri, ne_get_error(i_session)); return FAIL; } } while (0) @@ -224,7 +226,11 @@ int time_filter ( float a[], float b[], int nelm, float median, float percentage ); float *times1, *times2; -inline int latency ( struct timeval sec, struct timeval usec ); +static inline int latency ( struct timeval tv1, struct timeval tv2 ) +{ + return ( ( tv2.tv_sec-tv1.tv_sec ) *1000000+ ( tv2.tv_usec-tv1.tv_usec ) ); +} + int my_mkcol ( char* uri, int depth ); int my_mkcol2 ( char* uri, int depth ); diff -ru Prestan/src/props.c Prestan-fixed/src/props.c --- Prestan/src/props.c 2007-08-26 15:00:43.000000000 -0300 +++ Prestan-fixed/src/props.c 2022-02-13 22:33:50.000000000 -0300 @@ -3,6 +3,7 @@ #include <stdlib.h> #include <stdio.h> +#include <sys/time.h> #include <ne_request.h> #include <ne_props.h>
Comparison with the DAV module of the latest Apache 2.4 running on the same HW
Prestan, Version 0.3.0 Copyright(c) 2003 Teng Xu, GRASE Research Group at UCSC Copyright(c) 2007 Markus Litz, Modified by DLR - 2007 http://www.dlr.de/sc Server Warming Up.......................Please Wait.......Done Start Testing http://apache-dav.local/test/: ********************************** * Number of Requests 10 * Number of Dead Properties 10 * Depth of Collection 10 * Width of Collection 100 * Type of Methods WebDAV ********************************** ProppatchMult................. Rsp = 584 [us] ProppatchSingle............... Rsp = 368 [us] PropfindDeadMult.............. Rsp = 524 [us] PropfindDeadSingle............ Rsp = 359 [us] PropfindLiveMult.............. Rsp = 602 [us] PropfindLiveSingle............ Rsp = 694 [us] Put1K......................... Rsp = 694 [us] Get1K......................... Rsp = 1146 [us] Put64K........................ Rsp = 7741 [us] Get64K........................ Rsp = 4972 [us] Put1024K...................... Rsp = 95347 [us] Get1024K...................... Rsp = 99121 [us] Copy.......................... Rsp = 416 [us] Move.......................... Rsp = 548 [us] Delete........................ Rsp = 471 [us] MkCol......................... Rsp = 464 [us] CopyCol....................... Rsp = 12040 [us] MoveCol....................... Rsp = 8388 [us] DeleteCol..................... Rsp = 7367 [us] Lock.......................... Rsp = 488 [us] UnLock........................ Rsp = 398 [us] LockCol....................... Rsp = 575 [us] UnLockCol..................... Rsp = 1983 [us] ACL Not Implemented The x-axis scale is logarithmic because otherwise the differences in the fast methods would not be visible. I conclude that Cyclaero's WebDAV is mostly on par with Apache's implementation. Copyright © Dr. Rolf Jansen - 2022-02-13 14:15:42 Discussion on Twitter: 1493582251992535042 |