]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
TrivialDB support (#223)
authorAmos Jeffries <yadij@users.noreply.github.com>
Tue, 17 Jul 2018 23:36:31 +0000 (23:36 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Tue, 17 Jul 2018 23:36:35 +0000 (23:36 +0000)
Allow use of Samba TrivialDB instead of outdated BerkleyDB in
the session helper.

Require TrivialDB support for use of the time_quota helper.
libdb v1.85 is no longer supported by distributors and
upgrading to v5 only to deprecate use does not seem to be
worthwhile.

acinclude/tdb.m4 [new file with mode: 0644]
configure.ac
doc/release-notes/release-5.sgml
src/acl/external/session/Makefile.am
src/acl/external/session/ext_session_acl.cc
src/acl/external/session/required.m4
src/acl/external/time_quota/Makefile.am
src/acl/external/time_quota/ext_time_quota_acl.cc
src/acl/external/time_quota/required.m4
test-suite/buildtests/layer-01-minimal.opts
test-suite/buildtests/layer-02-maximus.opts

diff --git a/acinclude/tdb.m4 b/acinclude/tdb.m4
new file mode 100644 (file)
index 0000000..20b2b2a
--- /dev/null
@@ -0,0 +1,49 @@
+## Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+##
+## Squid software is distributed under GPLv2+ license and includes
+## contributions from numerous individuals and organizations.
+## Please see the COPYING and CONTRIBUTORS files for details.
+##
+
+dnl check for --with-tdb option
+AC_DEFUN([SQUID_CHECK_LIBTDB],[
+AC_ARG_WITH(tdb,
+  AS_HELP_STRING([--without-tdb],
+                 [Do not use Samba TrivialDB. Default: auto-detect]), [
+case "$with_tdb" in
+  yes|no|auto)
+    : # Nothing special to do here
+    ;;
+  *)
+    AS_IF([test ! -d "$withval"],
+      AC_MSG_ERROR([--with-tdb path ($with_tdb) does not point to a directory])
+    )
+    LIBTDB_PATH="-L$withval/lib"
+    CPPFLAGS="-I$withval/include $CPPFLAGS"
+  ;;
+esac
+])
+AH_TEMPLATE(USE_TRIVIALDB,[Samba TrivialDB support is available])
+AS_IF([test "x$with_tdb" != "xno"],[
+  SQUID_STATE_SAVE(squid_libtdb_state)
+  LIBS="$LIBS $LIBTDB_PATH"
+  PKG_CHECK_MODULES([LIBTDB],[tdb],[CPPFLAGS="$CPPFLAGS $LIBTDB_CFLAGS"],[:])
+  AC_CHECK_HEADERS([sys/stat.h tdb.h],,,[
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+  ])
+  SQUID_STATE_ROLLBACK(squid_libtdb_state) #de-pollute LIBS
+
+  AS_IF([test "x$with_tdb" = "xyes" -a "x$LIBTDB_LIBS" = "x"],
+    AC_MSG_ERROR([Required TrivialDB library not found])
+  )
+  AS_IF([test "x$LIBTDB_LIBS" != "x"],[
+    CXXFLAGS="$LIBTDB_CFLAGS $CXXFLAGS"
+    LIBTDB_LIBS="$LIBTDB_PATH $LIBTDB_LIBS"
+    AC_DEFINE_UNQUOTED(USE_TRIVIALDB, HAVE_TDB_H, [Samba TrivialDB support is available])
+  ],[with_tdb=no])
+])
+AC_MSG_NOTICE([Samba TrivialDB library support: ${with_tdb:=auto} ${LIBTDB_PATH} ${LIBTDB_LIBS}])
+AC_SUBST(LIBTDB_LIBS)
+])
index 1ec245adde2f30884661f080d907e0aa21631729..c8cd9964a2590c711582c3edcbe3abbb7387e3a2 100644 (file)
@@ -23,6 +23,7 @@ m4_include([acinclude/os-deps.m4])
 m4_include([acinclude/krb5.m4])
 m4_include([acinclude/pam.m4])
 m4_include([acinclude/pkg.m4])
+m4_include([acinclude/tdb.m4])
 m4_include([acinclude/lib-checks.m4])
 m4_include([acinclude/ax_cxx_compile_stdcxx_11.m4])
 m4_include([acinclude/ax_cxx_0x_types.m4])
index 174fb7cda21f6996db14ad2b7ef10f847bd9774f..63e583f1292722cfd6252de0f757aff0bed4e2d5 100644 (file)
@@ -114,7 +114,12 @@ This section gives an account of those changes in three categories:
 <sect1>New options<label id="newoptions">
 <p>
 <descrip>
-       <p>No new options in this version.
+       <tag>--without-tdb</tag>
+       <p>New option to determine whether TrivialDB support is used, and
+          build against local custom installs.
+       <p>Samba TrivialDB is now the preferred database used by the
+          <em>ext_session_acl</em> and <em>ext_time_quota_acl</em> helpers,
+          deprecating use of BerkleyDB.
 
 </descrip>
 
index e54f22b0995cd75257153c5d540d8da1257539f5..7509848622b69707b73d84ea908d3cc0ec91ba56 100644 (file)
@@ -14,6 +14,7 @@ ext_session_acl_SOURCES= \
        ext_session_acl.cc
 ext_session_acl_LDADD = \
        $(COMPAT_LIB) \
-       -ldb
+       $(LIBBDB_LIBS) \
+       $(LIBTDB_LIBS)
 
 EXTRA_DIST= ext_session_acl.8 required.m4
index 09a35ca2c6a6dfd6a4625b8eebe7f2193ffd2160..64ffb60e42a0e7b4b467f08cba0cbd561a837460 100644 (file)
@@ -43,6 +43,9 @@
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
+#if HAVE_TDB_H
+#include <tdb.h>
+#endif
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -60,8 +63,36 @@ static int fixed_timeout = 0;
 char *db_path = NULL;
 const char *program_name;
 
+#if USE_BERKLEYDB
 DB *db = NULL;
 DB_ENV *db_env = NULL;
+typedef DBT DB_ENTRY;
+
+#elif USE_TRIVIALDB
+TDB_CONTEXT *db = nullptr;
+typedef TDB_DATA DB_ENTRY;
+
+#endif
+
+static void
+shutdown_db()
+{
+    if (db) {
+#if USE_BERKLEYDB
+        db->close(db, 0);
+    }
+    if (db_env) {
+        db_env->close(db_env, 0);
+
+#elif USE_TRIVIALDB
+        if (tdb_close(db) != 0) {
+            fprintf(stderr, "%s| WARNING: error closing session db '%s'\n", program_name, db_path);
+            exit(EXIT_FAILURE);
+        }
+#endif
+    }
+    xfree(db_path);
+}
 
 static void init_db(void)
 {
@@ -70,6 +101,7 @@ static void init_db(void)
     if (db_path) {
         if (!stat(db_path, &st_buf)) {
             if (S_ISDIR (st_buf.st_mode)) {
+#if USE_BERKLEYDB
                 /* If directory then open database environment. This prevents sync problems
                     between different processes. Otherwise fallback to single file */
                 db_env_create(&db_env, 0);
@@ -79,10 +111,16 @@ static void init_db(void)
                     exit(EXIT_FAILURE);
                 }
                 db_create(&db, db_env, 0);
+#elif USE_TRIVIALDB
+                std::string newPath(db_path);
+                newPath.append("session", 7);
+                db_path = xstrdup(newPath.c_str());
+#endif
             }
         }
     }
 
+#if USE_BERKLEYDB
     if (db_env) {
         if (db->open(db, NULL, "session", NULL, DB_BTREE, DB_CREATE, 0666)) {
             fprintf(stderr, "FATAL: %s: Failed to open db file '%s' in dir '%s'\n",
@@ -93,60 +131,121 @@ static void init_db(void)
     } else {
         db_create(&db, NULL, 0);
         if (db->open(db, NULL, db_path, NULL, DB_BTREE, DB_CREATE, 0666)) {
-            fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
-            exit(EXIT_FAILURE);
+            db = nullptr;
         }
     }
+#elif USE_TRIVIALDB
+    db = tdb_open(db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT|O_DSYNC, 0666);
+#endif
+    if (!db) {
+        fprintf(stderr, "FATAL: %s: Failed to open session db '%s'\n", program_name, db_path);
+        shutdown_db();
+        exit(EXIT_FAILURE);
+    }
 }
 
-static void shutdown_db(void)
+int session_is_active = 0;
+
+static size_t
+dataSize(DB_ENTRY *data)
 {
-    db->close(db, 0);
-    if (db_env) {
-        db_env->close(db_env, 0);
-    }
+#if USE_BERKLEYDB
+    return data->size;
+#elif USE_TRIVIALDB
+    return data->dsize;
+#endif
 }
 
-int session_is_active = 0;
+static bool
+fetchKey(/*const*/ DB_ENTRY &key, DB_ENTRY *data)
+{
+#if USE_BERKLEYDB
+    return (db->get(db, nullptr, &key, data, 0) == 0);
+#elif USE_TRIVIALDB
+    // NP: API says returns NULL on errors, but return is a struct type WTF??
+    *data = tdb_fetch(db, key);
+    return (data->dptr != nullptr);
+#endif
+}
+
+static void
+deleteEntry(/*const*/ DB_ENTRY &key)
+{
+#if USE_BERKLEYDB
+    db->del(db, nullptr, &key, 0);
+#elif USE_TRIVIALDB
+    tdb_delete(db, key);
+#endif
+}
+
+static void
+copyValue(void *dst, const DB_ENTRY *src, size_t sz)
+{
+#if USE_BERKLEYDB
+    memcpy(dst, src->data, sz);
+#elif USE_TRIVIALDB
+    memcpy(dst, src->dptr, sz);
+#endif
+}
 
 static int session_active(const char *details, size_t len)
 {
+#if USE_BERKLEYDB
     DBT key = {0};
     DBT data = {0};
     key.data = (void *)details;
     key.size = len;
-    if (db->get(db, NULL, &key, &data, 0) == 0) {
+#elif USE_TRIVIALDB
+    TDB_DATA key;
+    TDB_DATA data;
+#endif
+    if (fetchKey(key, &data)) {
         time_t timestamp;
-        if (data.size != sizeof(timestamp)) {
+        if (dataSize(&data) != sizeof(timestamp)) {
             fprintf(stderr, "ERROR: %s: CORRUPTED DATABASE (%s)\n", program_name, details);
-            db->del(db, NULL, &key, 0);
+            deleteEntry(key);
             return 0;
         }
-        memcpy(&timestamp, data.data, sizeof(timestamp));
+        copyValue(&timestamp, &data, sizeof(timestamp));
         if (timestamp + session_ttl >= time(NULL))
             return 1;
     }
     return 0;
 }
 
-static void session_login(const char *details, size_t len)
+static void
+session_login(/*const*/ char *details, size_t len)
 {
-    DBT key = {0};
-    DBT data = {0};
-    key.data = (void *)details;
+    DB_ENTRY key = {0};
+    DB_ENTRY data = {0};
+    time_t now = time(0);
+#if USE_BERKLEYDB
+    key.data = static_cast<decltype(key.data)>(details);
     key.size = len;
-    time_t now = time(NULL);
     data.data = &now;
     data.size = sizeof(now);
     db->put(db, NULL, &key, &data, 0);
+#elif USE_TRIVIALDB
+    key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+    key.dsize = len;
+    data.dptr = reinterpret_cast<decltype(data.dptr)>(&now);
+    data.dsize = sizeof(now);
+    tdb_store(db, key, data, 0);
+#endif
 }
 
-static void session_logout(const char *details, size_t len)
+static void
+session_logout(/*const*/ char *details, size_t len)
 {
-    DBT key = {0};
-    key.data = (void *)details;
+    DB_ENTRY key = {0};
+#if USE_BERKLEYDB
+    key.data = static_cast<decltype(key.data)>(details);
     key.size = len;
-    db->del(db, NULL, &key, 0);
+#elif USE_TRIVIALDB
+    key.dptr = reinterpret_cast<decltype(key.dptr)>(details);
+    key.dsize = len;
+#endif
+    deleteEntry(key);
 }
 
 static void usage(void)
@@ -173,7 +272,7 @@ int main(int argc, char **argv)
             session_ttl = strtol(optarg, NULL, 0);
             break;
         case 'b':
-            db_path = optarg;
+            db_path = xstrdup(optarg);
             break;
         case 'a':
             default_action = 0;
index 229774bd3bc2e52aae32bdeb81970449e12a12b4..1fe8a0e0c981f940bf277fa1f64b1c93a0497084 100755 (executable)
@@ -5,11 +5,23 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_CHECK_HEADERS(db.h,[
-  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
-    DB_ENV *db_env = nullptr;
-    db_env_create(&db_env, 0);
-  ]])],[
+SQUID_CHECK_LIBTDB
+if test "$with_tdb" != "no"; then
     BUILD_HELPER="session"
-  ],[])
-])
+fi
+
+LIBBDB_LIBS=
+AH_TEMPLATE(USE_BERKLEYDB,[BerkleyDB support is available])
+if test "x$with_tdb" = "xno"; then
+  AC_CHECK_HEADERS(db.h,[
+    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
+      DB_ENV *db_env = nullptr;
+      db_env_create(&db_env, 0);
+    ]])],[
+      AC_DEFINE_UNQUOTED(USE_BERKLEYDB, HAVE_DB_H, [BerkleyDB support is available])
+      BUILD_HELPER="session"
+      LIBBDB_LIBS="-ldb"
+    ],[])
+  ])
+fi
+AC_SUBST(LIBBDB_LIBS)
index 4684637e28385f1b8a500b7427f147d7c9eaadc6..20eba222f96d498e0fd8d7f76fc5b91b1ec96193 100644 (file)
@@ -16,6 +16,6 @@ ext_time_quota_acl_SOURCES= \
        ext_time_quota_acl.cc
 ext_time_quota_acl_LDADD = \
        $(COMPAT_LIB) \
-       -ldb
+       $(LIBTDB_LIBS)
 
 EXTRA_DIST= ext_time_quota_acl.8 required.m4
index 764fa862e06c14f9a680e862290df6622051eb2b..8f1bbefebb8b5177a8afd21d7ac3f9e604c19fcb 100644 (file)
 #if HAVE_GETOPT_H
 #include <getopt.h>
 #endif
-
-/* At this point all Bit Types are already defined, so we must
-   protect from multiple type definition on platform where
-   __BIT_TYPES_DEFINED__ is not defined.
- */
-#ifndef        __BIT_TYPES_DEFINED__
-#define        __BIT_TYPES_DEFINED__
-#endif
-
-#if HAVE_DB_185_H
-#include <db_185.h>
-#elif HAVE_DB_H
-#include <db.h>
+#if HAVE_TDB_H
+#include <tdb.h>
 #endif
 
 #ifndef DEFAULT_QUOTA_DB
@@ -63,7 +52,7 @@
 const char *db_path = DEFAULT_QUOTA_DB;
 const char *program_name;
 
-DB *db = NULL;
+TDB_CONTEXT *db = nullptr;
 
 #define KEY_LAST_ACTIVITY            "last-activity"
 #define KEY_PERIOD_START             "period-start"
@@ -147,7 +136,7 @@ static void log_fatal(const char *format, ...)
 static void init_db(void)
 {
     log_info("opening time quota database \"%s\".\n", db_path);
-    db = dbopen(db_path, O_CREAT | O_RDWR, 0666, DB_BTREE, NULL);
+    db = tdb_open(db_path, 0, TDB_CLEAR_IF_FIRST, O_CREAT | O_RDWR, 0666);
     if (!db) {
         log_fatal("Failed to open time_quota db '%s'\n", db_path);
         exit(EXIT_FAILURE);
@@ -156,52 +145,68 @@ static void init_db(void)
 
 static void shutdown_db(void)
 {
-    db->close(db);
+    tdb_close(db);
 }
 
-static void writeTime(const char *user_key, const char *sub_key, time_t t)
+static char *KeyString(int &len, const char *user_key, const char *sub_key)
 {
-    char keybuffer[TQ_BUFFERSIZE];
-    DBT key, data;
+    static char keybuffer[TQ_BUFFERSIZE];
+    *keybuffer = 0;
+
+    len = snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+    if (len < 0) {
+        log_error("Cannot add entry: %s-%s", user_key, sub_key);
+        len = 0;
 
-    if ( strlen(user_key) + strlen(sub_key) + 1 + 1 > sizeof(keybuffer) ) {
+    } else if (static_cast<size_t>(len) >= sizeof(keybuffer)) {
         log_error("key too long (%s,%s)\n", user_key, sub_key);
-    } else {
-        snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+        len = 0;
+    }
+
+    return keybuffer;
+}
+
+static void writeTime(const char *user_key, const char *sub_key, time_t t)
+{
+    int len = 0;
+    if (/* const */ char *keybuffer = KeyString(len, user_key, sub_key)) {
+
+        TDB_DATA key, data;
+
+        key.dptr = reinterpret_cast<unsigned char *>(keybuffer);
+        key.dsize = len;
 
-        key.data = (void *)keybuffer;
-        key.size = strlen(keybuffer);
-        data.data = &t;
-        data.size = sizeof(t);
-        db->put(db, &key, &data, 0);
+        data.dptr = reinterpret_cast<unsigned char *>(&t);
+        data.dsize = sizeof(t);
+
+        tdb_store(db, key, data, TDB_REPLACE);
         log_debug("writeTime(\"%s\", %d)\n", keybuffer, t);
     }
 }
 
 static time_t readTime(const char *user_key, const char *sub_key)
 {
-    char keybuffer[TQ_BUFFERSIZE];
-    DBT key, data;
-    time_t t = 0;
+    int len = 0;
+    if (/* const */ char *keybuffer = KeyString(len, user_key, sub_key)) {
 
-    if ( strlen(user_key) + 1 + strlen(sub_key) + 1 > sizeof(keybuffer) ) {
-        log_error("key too long (%s,%s)\n", user_key, sub_key);
-    } else {
-        snprintf(keybuffer, sizeof(keybuffer), "%s-%s", user_key, sub_key);
+        TDB_DATA key;
+        key.dptr = reinterpret_cast<unsigned char *>(keybuffer);
+        key.dsize = len;
 
-        key.data = (void *)keybuffer;
-        key.size = strlen(keybuffer);
-        if (db->get(db, &key, &data, 0) == 0) {
-            if (data.size != sizeof(t)) {
-                log_error("CORRUPTED DATABASE (%s)\n", keybuffer);
-            } else {
-                memcpy(&t, data.data, sizeof(t));
-            }
+        auto data = tdb_fetch(db, key);
+
+        time_t t = 0;
+        if (data.dsize != sizeof(t)) {
+            log_error("CORRUPTED DATABASE (%s)\n", keybuffer);
+        } else {
+            memcpy(&t, data.dptr, sizeof(t));
         }
+
         log_debug("readTime(\"%s\")=%d\n", keybuffer, t);
+        return t;
     }
 
-    return t;
+    return 0;
 }
 
 static void parseTime(const char *s, time_t *secs, time_t *start)
@@ -388,8 +393,6 @@ static void processActivity(const char *user_key)
         log_debug("ERR %s\n", message);
         SEND_ERR("Time budget exceeded.");
     }
-
-    db->sync(db, 0);
 }
 
 static void usage(void)
index a54daae4da8624408a0a4f776c660745d1672556..c9e52bf426377e2392cc7b4771c5ca3ed79eefb1 100644 (file)
@@ -5,12 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_CHECK_HEADERS(db_185.h,[BUILD_HELPER="time_quota"],[
-  AC_CHECK_HEADERS(db.h,[
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <db.h>]],[[
-      DB *db = dbopen("/tmp", O_CREAT | O_RDWR, 0666, DB_BTREE, NULL);
-    ]])],[
-      BUILD_HELPER="time_quota"
-    ],[])
-  ])
-])
+SQUID_CHECK_LIBTDB
+if test "$with_tdb" != "no"; then
+    BUILD_HELPER="time_quota"
+fi
index e1d8e398dd04d9696e5d021b8fedc2c7a9d16697..ef48707655524738929d31b6f9023ac0948bd071 100644 (file)
@@ -106,6 +106,7 @@ DISTCHECK_CONFIGURE_FLAGS=" \
        --without-gnutls \
        --without-openssl \
        --without-po2html \
+       --without-tdb \
        "
 
 # Fix the distclean testing.
index ff2d052032febf36b9d088cdb923e7f88e94faeb..e1b4a69dfaef043124d8d3b037e0959c11a61233 100644 (file)
@@ -43,6 +43,7 @@ MAKETEST="distcheck"
 #   --enable-win32-service \
 #   --with-valgrind-debug \
 #   --with-gnutls \
+#   --with-tdb \
 #
 #   --enable-cpu-profiling \  Requires CPU support.
 #