diff --git a/build/xxhash.m4 b/build/xxhash.m4 new file mode 100644 index 00000000000..11a5e5d58c7 --- /dev/null +++ b/build/xxhash.m4 @@ -0,0 +1,94 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Licensed to the Apache Software Foundation (ASF) under one or more +dnl contributor license agreements. See the NOTICE file distributed with +dnl this work for additional information regarding copyright ownership. +dnl The ASF licenses this file to You under the Apache License, Version 2.0 +dnl (the "License"); you may not use this file except in compliance with +dnl the License. You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl +dnl xxhash.m4: trafficserver's xxhash autoconf macros +dnl + +AC_DEFUN([TS_CHECK_XXHASH], [ +has_xxhash=no + +AC_ARG_WITH([xxhash], [AS_HELP_STRING([--with-xxhash=DIR],[use a specific xxhash library])], +[ + if test "$withval" != "no"; then + has_xxhash=yes + xxhash_base_dir="$withval" + case "$withval" in + yes) + xxhash_base_dir="/usr" + AC_MSG_NOTICE(checking for xxhash includes and libs in standard directories) + ;; + *":"*) + xxhash_include="`echo $withval |sed -e 's/:.*$//'`" + xxhash_ldflags="`echo $withval |sed -e 's/^.*://'`" + AC_MSG_NOTICE(checking for xxhash includes in $xxhash_include and libs in $xxhash_ldflags) + ;; + *) + xxhash_include="$withval/include" + xxhash_ldflags="$withval/lib" + AC_MSG_NOTICE(checking for xxhash includes in $xxhash_include and libs in $xxhash_ldflags) + ;; + esac + fi +]) + +has_xxhash=0 + +if test "$has_xxhash" != "no"; then + saved_ldflags=$LDFLAGS + saved_cppflags=$CPPFLAGS + + XXHASH_LIBS=-lxxhash + if test "$xxhash_base_dir" != "/usr"; then + XXHASH_INCLUDES=-I${xxhash_include} + XXHASH_LDFLAGS=-L${xxhash_ldflags} + + TS_ADDTO_RPATH(${xxhash_ldflags}) + fi + + xxhash_has_libs=0 + AC_CHECK_LIB([xxhash], [XXH64_digest], [xxhash_has_libs=1]) + + xxhash_has_headers=0 + if test "xxhash_has_libs" != "0"; then + AC_CHECK_HEADERS(xxhash.h, [xxhash_has_headers=1]) + fi + + if test "$xxhash_has_headers" != "0"; then + AC_RUN_IFELSE([ + AC_LANG_PROGRAM( + [#include ], + [ + #ifndef XXH_VERSION_MAJOR + exit(1); + #endif + ] + )], + [has_xxhash=1], + [AC_MSG_ERROR(xxhash has bogus version)] + ) + else + AC_MSG_WARN([xxhash not found]) + CPPFLAGS=$saved_cppflags + LDFLAGS=$saved_ldflags + fi +fi + +AC_SUBST(has_xxhash) +AC_SUBST(XXHASH_INCLUDES) +AC_SUBST(XXHASH_LDFLAGS) +AC_SUBST(XXHASH_LIBS) +]) diff --git a/configure.ac b/configure.ac index 4bdfcdc8646..f8b48d414d7 100644 --- a/configure.ac +++ b/configure.ac @@ -1792,6 +1792,11 @@ TS_CHECK_TCMALLOC TS_CHECK_JEMALLOC TS_CHECK_MIMALLOC +# +# Check xxxHash +TS_CHECK_XXHASH +AM_CONDITIONAL([HAS_XXHASH], [ test "x${has_xxhash}" = "x1" ]) + # # Check for libreadline/libedit AX_LIB_READLINE diff --git a/include/tscore/ink_config.h.in b/include/tscore/ink_config.h.in index 5b297efe7bf..00950b58c20 100644 --- a/include/tscore/ink_config.h.in +++ b/include/tscore/ink_config.h.in @@ -54,6 +54,8 @@ #define TS_HAS_TCMALLOC @has_tcmalloc@ #define TS_HAS_MIMALLOC @mimalloch@ +#define TS_HAS_XXHASH @has_xxhash@ + /* Features */ #define TS_HAS_IN6_IS_ADDR_UNSPECIFIED @has_in6_is_addr_unspecified@ #define TS_HAS_BACKTRACE @has_backtrace@ diff --git a/include/tscore/xxHash.h b/include/tscore/xxHash.h new file mode 100644 index 00000000000..29869fcd05a --- /dev/null +++ b/include/tscore/xxHash.h @@ -0,0 +1,83 @@ +/** @file + + xxHash support class. + + https://github.com/Cyan4973/xxHash + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#pragma once + +#if TS_HAS_XXHASH + +#include "tscore/CryptoHash.h" + +#include + +/** + This is NOT cryptographic hash + */ +class xxHashContext +{ +public: + /** + Dest type is CryptoHash for compatibility for a historical reason. + + TODO: get rid of CryptoHash. + */ + static bool + hash_immediate(CryptoHash &hash, void const *data, int length) + { + XXH128_hash_t r = XXH3_128bits(data, length); + hash = reinterpret_cast(r); + + return true; + } + + xxHashContext() { _state = XXH3_createState(); } + + ~xxHashContext() { XXH3_freeState(_state); } + + /// Update the hash with @a data of @a length bytes. + bool + update(void const *data, int length) + { + if (XXH3_128bits_update(_state, data, length) == XXH_ERROR) { + return false; + } + + return true; + } + + /// Finalize and extract the @a hash. + bool + finalize(CryptoHash &hash) + { + XXH128_hash_t r = XXH3_128bits_digest(_state); + hash = reinterpret_cast(r); + + return true; + } + +private: + XXH3_state_t *_state = nullptr; +}; + +#endif diff --git a/proxy/hdrs/URL.cc b/proxy/hdrs/URL.cc index 5614a9b9c8c..eb7ac1ae66b 100644 --- a/proxy/hdrs/URL.cc +++ b/proxy/hdrs/URL.cc @@ -1727,8 +1727,9 @@ memcpy_tolower(char *d, const char *s, int n) // fast path for CryptoHash, HTTP, no user/password/params/query, // no buffer overflow, no unescaping needed -static inline void -url_CryptoHash_get_fast(const URLImpl *url, CryptoContext &ctx, CryptoHash *hash, cache_generation_t generation) +template +void +url_CryptoHash_get_fast(const URLImpl *url, T &ctx, CryptoHash *hash, cache_generation_t generation) { char buffer[BUFSIZE]; char *p; @@ -1766,8 +1767,9 @@ url_CryptoHash_get_fast(const URLImpl *url, CryptoContext &ctx, CryptoHash *hash ctx.finalize(*hash); } -static inline void -url_CryptoHash_get_general(const URLImpl *url, CryptoContext &ctx, CryptoHash &hash, cache_generation_t generation) +template +void +url_CryptoHash_get_general(const URLImpl *url, T &ctx, CryptoHash &hash, cache_generation_t generation) { char buffer[BUFSIZE]; char *p, *e; diff --git a/proxy/hdrs/URL.h b/proxy/hdrs/URL.h index ac9d4a0d90a..ccd0e4dc960 100644 --- a/proxy/hdrs/URL.h +++ b/proxy/hdrs/URL.h @@ -118,7 +118,13 @@ class URLImpl : public HdrHeapObjImpl private: }; +#if TS_HAS_XXHASH +#include "tscore/xxHash.h" + +using URLHashContext = xxHashContext; +#else using URLHashContext = CryptoContext; +#endif extern const char *URL_SCHEME_FILE; extern const char *URL_SCHEME_FTP; diff --git a/src/tscore/Makefile.am b/src/tscore/Makefile.am index e5b6ed6eb3e..66c15fe964d 100644 --- a/src/tscore/Makefile.am +++ b/src/tscore/Makefile.am @@ -52,6 +52,12 @@ libtscore_la_LIBADD = \ @YAMLCPP_LIBS@ \ -lc +if HAS_XXHASH +AM_CPPFLAGS += @XXHASH_INCLUDES@ +libtscore_la_LDFLAGS += @XXHASH_LDFLAGS@ +libtscore_la_LIBADD += @XXHASH_LIBS@ +endif + libtscore_la_SOURCES = \ AcidPtr.cc \ Arena.cc \