From 03c73f23c42cd935a3f917e89e6d5791e1b7056d Mon Sep 17 00:00:00 2001 From: Empornium Development Team Date: Wed, 10 Oct 2018 12:20:36 +0000 Subject: [PATCH] Radiance v1.1.4 Release --- .gitignore | 10 +- CHANGES | 8 + README.md | 14 +- clean | 7 - compile | 347 --------------- config.h.in | 209 --------- configure.ac | 12 +- depcomp | 791 ----------------------------------- install-sh | 508 ---------------------- install/radiance.conf | 7 +- missing | 215 ---------- src/Makefile.am | 2 +- src/config.cpp | 19 +- src/config.h | 3 + src/{db.cpp => database.cpp} | 551 ++++++++++-------------- src/{db.h => database.h} | 47 ++- src/debug.cpp | 5 +- src/debug.h | 2 + src/domain.cpp | 3 + src/domain.h | 3 - src/events.cpp | 10 +- src/events.h | 22 +- src/logger.cpp | 7 +- src/logger.h | 13 - src/misc_functions.cpp | 2 + src/radiance.cpp | 35 +- src/radiance.h | 29 +- src/report.cpp | 13 +- src/response.cpp | 3 +- src/schedule.cpp | 9 +- src/schedule.h | 4 +- src/site_comm.cpp | 3 +- src/site_comm.h | 2 - src/worker.cpp | 102 +++-- src/worker.h | 9 +- 35 files changed, 446 insertions(+), 2580 deletions(-) delete mode 100755 clean delete mode 100755 compile delete mode 100644 config.h.in delete mode 100755 depcomp delete mode 100755 install-sh delete mode 100755 missing rename src/{db.cpp => database.cpp} (61%) rename src/{db.h => database.h} (76%) diff --git a/.gitignore b/.gitignore index 214bdcd..95c22e7 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,13 @@ configure Makefile Makefile.in radiance.conf -radiance +src/radiance debug.log +autoconf.h.in +autoconf.h +compile +depcomp +install-sh +missing +stamp-h1 + diff --git a/CHANGES b/CHANGES index d4c05c2..befbb83 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +-- 1.1.4 (2018-10-10) +Improved DB queue status reporting +Fix potential shutdown race condition +Update usge text to include -v option for version output +Upgrade DB handling to use a connection pool +Fix debug build mode +Fix IPv4/IPv6 peer accounting performance issues + -- 1.1.3 (2018-10-01) Update user loading SQL query Fix logger file handling diff --git a/README.md b/README.md index 105e01e..c3afc42 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,12 @@ Radiance is a BitTorrent tracker written in C++ for the [Luminance](http://www.g * Edit `radiance.conf` to your liking. * Build Radiance: - - autoreconf - ./configure - make - make install +``` +autoreconf -i +./configure +make +sudo make install +``` # Configure options: `--with-jemalloc` is recommended @@ -47,8 +48,9 @@ Radiance is a BitTorrent tracker written in C++ for the [Luminance](http://www.g * `-c ` - Path to config file. If unspecified, the current working directory is used. * `-d` - Fork to the background and run as a service daemon. +* `-v` - Print version string and exit. ### Signals * `SIGHUP` - Reload config -* `SIGUSR1` - Reload torrent list, user list and client whitelist +* `SIGUSR1` - Reload torrent list, user list and client blacklist diff --git a/clean b/clean deleted file mode 100755 index dca6e2f..0000000 --- a/clean +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -if [ -a Makefile ] -then - make maintainer-clean -fi - -rm -f configure Makefile.in diff --git a/compile b/compile deleted file mode 100755 index a85b723..0000000 --- a/compile +++ /dev/null @@ -1,347 +0,0 @@ -#! /bin/sh -# Wrapper for compilers which do not understand '-c -o'. - -scriptversion=2012-10-14.11; # UTC - -# Copyright (C) 1999-2014 Free Software Foundation, Inc. -# Written by Tom Tromey . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -nl=' -' - -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent tools from complaining about whitespace usage. -IFS=" "" $nl" - -file_conv= - -# func_file_conv build_file lazy -# Convert a $build file to $host form and store it in $file -# Currently only supports Windows hosts. If the determined conversion -# type is listed in (the comma separated) LAZY, no conversion will -# take place. -func_file_conv () -{ - file=$1 - case $file in - / | /[!/]*) # absolute file, and not a UNC file - if test -z "$file_conv"; then - # lazily determine how to convert abs files - case `uname -s` in - MINGW*) - file_conv=mingw - ;; - CYGWIN*) - file_conv=cygwin - ;; - *) - file_conv=wine - ;; - esac - fi - case $file_conv/,$2, in - *,$file_conv,*) - ;; - mingw/*) - file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` - ;; - cygwin/*) - file=`cygpath -m "$file" || echo "$file"` - ;; - wine/*) - file=`winepath -w "$file" || echo "$file"` - ;; - esac - ;; - esac -} - -# func_cl_dashL linkdir -# Make cl look for libraries in LINKDIR -func_cl_dashL () -{ - func_file_conv "$1" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" -} - -# func_cl_dashl library -# Do a library search-path lookup for cl -func_cl_dashl () -{ - lib=$1 - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - lib=$dir/$lib.dll.lib - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - lib=$dir/$lib.lib - break - fi - if test -f "$dir/lib$lib.a"; then - found=yes - lib=$dir/lib$lib.a - break - fi - done - IFS=$save_IFS - - if test "$found" != yes; then - lib=$lib.lib - fi -} - -# func_cl_wrapper cl arg... -# Adjust compile command to suit cl -func_cl_wrapper () -{ - # Assume a capable shell - lib_path= - shared=: - linker_opts= - for arg - do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - eat=1 - case $2 in - *.o | *.[oO][bB][jJ]) - func_file_conv "$2" - set x "$@" -Fo"$file" - shift - ;; - *) - func_file_conv "$2" - set x "$@" -Fe"$file" - shift - ;; - esac - ;; - -I) - eat=1 - func_file_conv "$2" mingw - set x "$@" -I"$file" - shift - ;; - -I*) - func_file_conv "${1#-I}" mingw - set x "$@" -I"$file" - shift - ;; - -l) - eat=1 - func_cl_dashl "$2" - set x "$@" "$lib" - shift - ;; - -l*) - func_cl_dashl "${1#-l}" - set x "$@" "$lib" - shift - ;; - -L) - eat=1 - func_cl_dashL "$2" - ;; - -L*) - func_cl_dashL "${1#-L}" - ;; - -static) - shared=false - ;; - -Wl,*) - arg=${1#-Wl,} - save_ifs="$IFS"; IFS=',' - for flag in $arg; do - IFS="$save_ifs" - linker_opts="$linker_opts $flag" - done - IFS="$save_ifs" - ;; - -Xlinker) - eat=1 - linker_opts="$linker_opts $2" - ;; - -*) - set x "$@" "$1" - shift - ;; - *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) - func_file_conv "$1" - set x "$@" -Tp"$file" - shift - ;; - *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) - func_file_conv "$1" mingw - set x "$@" "$file" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift - done - if test -n "$linker_opts"; then - linker_opts="-link$linker_opts" - fi - exec "$@" $linker_opts - exit 1 -} - -eat= - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: compile [--help] [--version] PROGRAM [ARGS] - -Wrapper for compilers which do not understand '-c -o'. -Remove '-o dest.o' from ARGS, run PROGRAM with the remaining -arguments, and rename the output as expected. - -If you are trying to build a whole package this is not the -right script to run: please start by reading the file 'INSTALL'. - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "compile $scriptversion" - exit $? - ;; - cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) - func_cl_wrapper "$@" # Doesn't return... - ;; -esac - -ofile= -cfile= - -for arg -do - if test -n "$eat"; then - eat= - else - case $1 in - -o) - # configure might choose to run compile as 'compile cc -o foo foo.c'. - # So we strip '-o arg' only if arg is an object. - eat=1 - case $2 in - *.o | *.obj) - ofile=$2 - ;; - *) - set x "$@" -o "$2" - shift - ;; - esac - ;; - *.c) - cfile=$1 - set x "$@" "$1" - shift - ;; - *) - set x "$@" "$1" - shift - ;; - esac - fi - shift -done - -if test -z "$ofile" || test -z "$cfile"; then - # If no '-o' option was seen then we might have been invoked from a - # pattern rule where we don't need one. That is ok -- this is a - # normal compilation that the losing compiler can handle. If no - # '.c' file was seen then we are probably linking. That is also - # ok. - exec "$@" -fi - -# Name of file we expect compiler to create. -cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` - -# Create the lock directory. -# Note: use '[/\\:.-]' here to ensure that we don't use the same name -# that we are using for the .o file. Also, base the name on the expected -# object file name, since that is what matters with a parallel build. -lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d -while true; do - if mkdir "$lockdir" >/dev/null 2>&1; then - break - fi - sleep 1 -done -# FIXME: race condition here if user kills between mkdir and trap. -trap "rmdir '$lockdir'; exit 1" 1 2 15 - -# Run the compile. -"$@" -ret=$? - -if test -f "$cofile"; then - test "$cofile" = "$ofile" || mv "$cofile" "$ofile" -elif test -f "${cofile}bj"; then - test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" -fi - -rmdir "$lockdir" -exit $ret - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/config.h.in b/config.h.in deleted file mode 100644 index 8dafa5e..0000000 --- a/config.h.in +++ /dev/null @@ -1,209 +0,0 @@ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* compile and link with jemalloc */ -#undef ENABLE_JEMALLOC - -/* compile and link with tcmalloc */ -#undef ENABLE_TCMALLOC - -/* Define to 1 if you have the header file. */ -#undef HAVE_ARPA_INET_H - -/* define if the Boost library is available */ -#undef HAVE_BOOST - -/* define if the Boost::Date_Time library is available */ -#undef HAVE_BOOST_DATE_TIME - -/* define if the Boost::IOStreams library is available */ -#undef HAVE_BOOST_IOSTREAMS - -/* define if the Boost::Log library is available */ -#undef HAVE_BOOST_LOG - -/* define if the Boost::Log_setup library is available */ -#undef HAVE_BOOST_LOG_SETUP - -/* define if the Boost::System library is available */ -#undef HAVE_BOOST_SYSTEM - -/* define if the Boost::Thread library is available */ -#undef HAVE_BOOST_THREAD - -/* define if the compiler supports basic C++11 syntax */ -#undef HAVE_CXX11 - -/* Define to 1 if you have the header file. */ -#undef HAVE_FCNTL_H - -/* Define to 1 if you have the `fork' function. */ -#undef HAVE_FORK - -/* Define to 1 if you have the `ftruncate' function. */ -#undef HAVE_FTRUNCATE - -/* Define to 1 if you have the header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_JEMALLOC_JEMALLOC_H - -/* Define to 1 if you have the `dl' library (-ldl). */ -#undef HAVE_LIBDL - -/* Define to 1 if you have the `z' library (-lz). */ -#undef HAVE_LIBZ - -/* Define to 1 if you have the header file. */ -#undef HAVE_MEMORY_H - -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETDB_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_NETINET_IN_H - -/* Define if you have POSIX threads libraries and header files. */ -#undef HAVE_PTHREAD - -/* Have PTHREAD_PRIO_INHERIT. */ -#undef HAVE_PTHREAD_PRIO_INHERIT - -/* Define to 1 if you have the `socket' function. */ -#undef HAVE_SOCKET - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STDLIB_H - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_STRING_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_FILE_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_SOCKET_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the `vfork' function. */ -#undef HAVE_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_VFORK_H - -/* Define to 1 if `fork' works. */ -#undef HAVE_WORKING_FORK - -/* Define to 1 if `vfork' works. */ -#undef HAVE_WORKING_VFORK - -/* Define to 1 if you have the header file. */ -#undef HAVE_ZLIB_H - -/* Define to 1 if the system has the type `_Bool'. */ -#undef HAVE__BOOL - -/* Define to the address where bug reports for this package should be sent. */ -#undef PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#undef PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#undef PACKAGE_STRING - -/* Define to the one symbol short name of this package. */ -#undef PACKAGE_TARNAME - -/* Define to the home page for this package. */ -#undef PACKAGE_URL - -/* Define to the version of this package. */ -#undef PACKAGE_VERSION - -/* Define to necessary symbol if this constant uses a non-standard name on - your system. */ -#undef PTHREAD_CREATE_JOINABLE - -/* Define to 1 if you have the ANSI C header files. */ -#undef STDC_HEADERS - -/* Define for Solaris 2.5.1 so the uint32_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT32_T - -/* Define for Solaris 2.5.1 so the uint64_t typedef from , - , or is not used. If the typedef were allowed, the - #define below would cause a syntax error. */ -#undef _UINT64_T - -/* enable debug build */ -#undef __DEBUG_BUILD__ - -/* Link/compile against jemalloc */ -#undef has_jemalloc - -/* Link/compile against tcmalloc */ -#undef has_tcmalloc - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -#undef inline -#endif - -/* Define to the type of a signed integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef int32_t - -/* Define to the type of a signed integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef int64_t - -/* Define to `long int' if does not define. */ -#undef off_t - -/* Define to `int' if does not define. */ -#undef pid_t - -/* jemalloc prefix */ -#undef prefix_jemalloc - -/* Define to `unsigned int' if does not define. */ -#undef size_t - -/* Define to the type of an unsigned integer type of width exactly 16 bits if - such a type exists and the standard includes do not define it. */ -#undef uint16_t - -/* Define to the type of an unsigned integer type of width exactly 32 bits if - such a type exists and the standard includes do not define it. */ -#undef uint32_t - -/* Define to the type of an unsigned integer type of width exactly 64 bits if - such a type exists and the standard includes do not define it. */ -#undef uint64_t - -/* Define as `fork' if `vfork' does not work. */ -#undef vfork diff --git a/configure.ac b/configure.ac index 58eaea0..7911a0f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,9 +2,9 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT(radiance, 1.1.3) +AC_INIT(radiance, 1.1.4) AC_CONFIG_SRCDIR([src]) -AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_HEADERS([autoconf.h]) # Checks for programs. AC_PROG_CXX @@ -72,9 +72,11 @@ fi AC_ARG_ENABLE([debug], [ --enable-debug build with additional debugging code], [ - CFLAGS='-g'; - LDFLAGS="${LDFLAGS} -ldl"; - AC_DEFINE([__DEBUG_BUILD__], [], [enable debug build]) + CFLAGS='-g -pg -ggdb'; + LDFLAGS="${LDFLAGS} -ldl -lprofiler"; + LIBS="$LIBS -lprofiler"; + AC_DEFINE([__DEBUG_BUILD__], [true], [enable debug build]) + AC_MSG_NOTICE($(tput setaf 1)"DEBUG BUILD ENABLED!!!"$(tput sgr0)) ] ) diff --git a/depcomp b/depcomp deleted file mode 100755 index fc98710..0000000 --- a/depcomp +++ /dev/null @@ -1,791 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2013-05-30.07; # UTC - -# Copyright (C) 1999-2014 Free Software Foundation, Inc. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try '$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by 'PROGRAMS ARGS'. - object Object file output by 'PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputting dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -# Get the directory component of the given path, and save it in the -# global variables '$dir'. Note that this directory component will -# be either empty or ending with a '/' character. This is deliberate. -set_dir_from () -{ - case $1 in - */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; - *) dir=;; - esac -} - -# Get the suffix-stripped basename of the given path, and save it the -# global variable '$base'. -set_base_from () -{ - base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` -} - -# If no dependency file was actually created by the compiler invocation, -# we still have to create a dummy depfile, to avoid errors with the -# Makefile "include basename.Plo" scheme. -make_dummy_depfile () -{ - echo "#dummy" > "$depfile" -} - -# Factor out some common post-processing of the generated depfile. -# Requires the auxiliary global variable '$tmpdepfile' to be set. -aix_post_process_depfile () -{ - # If the compiler actually managed to produce a dependency file, - # post-process it. - if test -f "$tmpdepfile"; then - # Each line is of the form 'foo.o: dependency.h'. - # Do two passes, one to just change these to - # $object: dependency.h - # and one to simply output - # dependency.h: - # which is needed to avoid the deleted-header problem. - { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" - sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" - } > "$depfile" - rm -f "$tmpdepfile" - else - make_dummy_depfile - fi -} - -# A tabulation character. -tab=' ' -# A newline character. -nl=' -' -# Character ranges might be problematic outside the C locale. -# These definitions help. -upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ -lower=abcdefghijklmnopqrstuvwxyz -digits=0123456789 -alpha=${upper}${lower} - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Avoid interferences from the environment. -gccflag= dashmflag= - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -cygpath_u="cygpath -u -f -" -if test "$depmode" = msvcmsys; then - # This is just like msvisualcpp but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvisualcpp -fi - -if test "$depmode" = msvc7msys; then - # This is just like msvc7 but w/o cygpath translation. - # Just convert the backslash-escaped backslashes to single forward - # slashes to satisfy depend.m4 - cygpath_u='sed s,\\\\,/,g' - depmode=msvc7 -fi - -if test "$depmode" = xlc; then - # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. - gccflag=-qmakedep=gcc,-MF - depmode=gcc -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. -## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. -## (see the conditional assignment to $gccflag above). -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). Also, it might not be -## supported by the other compilers which use the 'gcc' depmode. -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The second -e expression handles DOS-style file names with drive - # letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the "deleted header file" problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. -## Some versions of gcc put a space before the ':'. On the theory -## that the space means something, we add a space to the output as -## well. hp depmode also adds that space, but also prefixes the VPATH -## to the object. Take care to not repeat it in the output. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like '#:fec' to the end of the - # dependency line. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ - | tr "$nl" ' ' >> "$depfile" - echo >> "$depfile" - # The second pass generates a dummy entry for each header file. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" - ;; - -xlc) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts '$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - aix_post_process_depfile - ;; - -tcc) - # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 - # FIXME: That version still under development at the moment of writing. - # Make that this statement remains true also for stable, released - # versions. - # It will wrap lines (doesn't matter whether long or short) with a - # trailing '\', as in: - # - # foo.o : \ - # foo.c \ - # foo.h \ - # - # It will put a trailing '\' even on the last line, and will use leading - # spaces rather than leading tabs (at least since its commit 0394caf7 - # "Emit spaces for -MD"). - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. - # We have to change lines of the first kind to '$object: \'. - sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" - # And for each line of the second kind, we have to emit a 'dep.h:' - # dummy dependency, to avoid the deleted-header problem. - sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" - rm -f "$tmpdepfile" - ;; - -## The order of this option in the case statement is important, since the -## shell code in configure will try each of these formats in the order -## listed in this file. A plain '-MD' option would be understood by many -## compilers, so we must ensure this comes after the gcc and icc options. -pgcc) - # Portland's C compiler understands '-MD'. - # Will always output deps to 'file.d' where file is the root name of the - # source file under compilation, even if file resides in a subdirectory. - # The object file name does not affect the name of the '.d' file. - # pgcc 10.2 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using '\' : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - set_dir_from "$object" - # Use the source, not the object, to determine the base name, since - # that's sadly what pgcc will do too. - set_base_from "$source" - tmpdepfile=$base.d - - # For projects that build the same source file twice into different object - # files, the pgcc approach of using the *source* file root name can cause - # problems in parallel builds. Use a locking strategy to avoid stomping on - # the same $tmpdepfile. - lockdir=$base.d-lock - trap " - echo '$0: caught signal, cleaning up...' >&2 - rmdir '$lockdir' - exit 1 - " 1 2 13 15 - numtries=100 - i=$numtries - while test $i -gt 0; do - # mkdir is a portable test-and-set. - if mkdir "$lockdir" 2>/dev/null; then - # This process acquired the lock. - "$@" -MD - stat=$? - # Release the lock. - rmdir "$lockdir" - break - else - # If the lock is being held by a different process, wait - # until the winning process is done or we timeout. - while test -d "$lockdir" && test $i -gt 0; do - sleep 1 - i=`expr $i - 1` - done - fi - i=`expr $i - 1` - done - trap - 1 2 13 15 - if test $i -le 0; then - echo "$0: failed to acquire lock after $numtries attempts" >&2 - echo "$0: check lockdir '$lockdir'" >&2 - exit 1 - fi - - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - set_dir_from "$object" - set_base_from "$object" - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" - # Add 'dependent.h:' lines. - sed -ne '2,${ - s/^ *// - s/ \\*$// - s/$/:/ - p - }' "$tmpdepfile" >> "$depfile" - else - make_dummy_depfile - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in 'foo.d' instead, so we check for that too. - # Subdirectories are respected. - set_dir_from "$object" - set_base_from "$object" - - if test "$libtool" = yes; then - # Libtool generates 2 separate objects for the 2 libraries. These - # two compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir$base.o.d # libtool 1.5 - tmpdepfile2=$dir.libs/$base.o.d # Likewise. - tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -ne 0; then - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - # Same post-processing that is required for AIX mode. - aix_post_process_depfile - ;; - -msvc7) - if test "$libtool" = yes; then - showIncludes=-Wc,-showIncludes - else - showIncludes=-showIncludes - fi - "$@" $showIncludes > "$tmpdepfile" - stat=$? - grep -v '^Note: including file: ' "$tmpdepfile" - if test $stat -ne 0; then - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - # The first sed program below extracts the file names and escapes - # backslashes for cygpath. The second sed program outputs the file - # name when reading, but also accumulates all include files in the - # hold buffer in order to output them again at the end. This only - # works with sed implementations that can handle large buffers. - sed < "$tmpdepfile" -n ' -/^Note: including file: *\(.*\)/ { - s//\1/ - s/\\/\\\\/g - p -}' | $cygpath_u | sort -u | sed -n ' -s/ /\\ /g -s/\(.*\)/'"$tab"'\1 \\/p -s/.\(.*\) \\/\1:/ -H -$ { - s/.*/'"$tab"'/ - G - p -}' >> "$depfile" - echo >> "$depfile" # make sure the fragment doesn't end with a backslash - rm -f "$tmpdepfile" - ;; - -msvc7msys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for ':' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. - "$@" $dashmflag | - sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this sed invocation - # correctly. Breaking it into two sed invocations is a workaround. - tr ' ' "$nl" < "$tmpdepfile" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no eat=no - for arg - do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - if test $eat = yes; then - eat=no - continue - fi - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -arch) - eat=yes ;; - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix=`echo "$object" | sed 's/^.*\././'` - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - # makedepend may prepend the VPATH from the source file name to the object. - # No need to regex-escape $object, excess matching of '.' is harmless. - sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process the last invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed '1,2d' "$tmpdepfile" \ - | tr ' ' "$nl" \ - | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ - | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - # Remove '-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E \ - | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - | sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test "X$1" != 'X--mode=compile'; do - shift - done - shift - fi - - IFS=" " - for arg - do - case "$arg" in - -o) - shift - ;; - $object) - shift - ;; - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E 2>/dev/null | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" - echo "$tab" >> "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvcmsys) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/install-sh b/install-sh deleted file mode 100755 index 59990a1..0000000 --- a/install-sh +++ /dev/null @@ -1,508 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2014-09-12.12; # UTC - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# 'make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. - -tab=' ' -nl=' -' -IFS=" $tab$nl" - -# Set DOITPROG to "echo" to test this script. - -doit=${DOITPROG-} -doit_exec=${doit:-exec} - -# Put in absolute file names if you don't have them in your path; -# or use environment vars. - -chgrpprog=${CHGRPPROG-chgrp} -chmodprog=${CHMODPROG-chmod} -chownprog=${CHOWNPROG-chown} -cmpprog=${CMPPROG-cmp} -cpprog=${CPPROG-cp} -mkdirprog=${MKDIRPROG-mkdir} -mvprog=${MVPROG-mv} -rmprog=${RMPROG-rm} -stripprog=${STRIPPROG-strip} - -posix_mkdir= - -# Desired mode of installed file. -mode=0755 - -chgrpcmd= -chmodcmd=$chmodprog -chowncmd= -mvcmd=$mvprog -rmcmd="$rmprog -f" -stripcmd= - -src= -dst= -dir_arg= -dst_arg= - -copy_on_change=false -is_target_a_directory=possibly - -usage="\ -Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: - --help display this help and exit. - --version display version info and exit. - - -c (ignored) - -C install only if different (preserve the last data modification time) - -d create directories instead of installing files. - -g GROUP $chgrpprog installed files to GROUP. - -m MODE $chmodprog installed files to MODE. - -o USER $chownprog installed files to USER. - -s $stripprog installed files. - -t DIRECTORY install into DIRECTORY. - -T report an error if DSTFILE is a directory. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG - RMPROG STRIPPROG -" - -while test $# -ne 0; do - case $1 in - -c) ;; - - -C) copy_on_change=true;; - - -d) dir_arg=true;; - - -g) chgrpcmd="$chgrpprog $2" - shift;; - - --help) echo "$usage"; exit $?;; - - -m) mode=$2 - case $mode in - *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; - - -o) chowncmd="$chownprog $2" - shift;; - - -s) stripcmd=$stripprog;; - - -t) - is_target_a_directory=always - dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; - - -T) is_target_a_directory=never;; - - --version) echo "$0 $scriptversion"; exit $?;; - - --) shift - break;; - - -*) echo "$0: invalid option: $1" >&2 - exit 1;; - - *) break;; - esac - shift -done - -# We allow the use of options -d and -T together, by making -d -# take the precedence; this is for compatibility with GNU install. - -if test -n "$dir_arg"; then - if test -n "$dst_arg"; then - echo "$0: target directory not allowed when installing a directory." >&2 - exit 1 - fi -fi - -if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then - # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dst_arg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dst_arg" - shift # fnord - fi - shift # arg - dst_arg=$arg - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - done -fi - -if test $# -eq 0; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call 'install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -if test -z "$dir_arg"; then - if test $# -gt 1 || test "$is_target_a_directory" = always; then - if test ! -d "$dst_arg"; then - echo "$0: $dst_arg: Is not a directory." >&2 - exit 1 - fi - fi -fi - -if test -z "$dir_arg"; then - do_exit='(exit $ret); exit $ret' - trap "ret=129; $do_exit" 1 - trap "ret=130; $do_exit" 2 - trap "ret=141; $do_exit" 13 - trap "ret=143; $do_exit" 15 - - # Set umask so as not to create temps with too-generous modes. - # However, 'strip' requires both read and write access to temps. - case $mode in - # Optimize common cases. - *644) cp_umask=133;; - *755) cp_umask=22;; - - *[0-7]) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw='% 200' - fi - cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; - *) - if test -z "$stripcmd"; then - u_plus_rw= - else - u_plus_rw=,u+rw - fi - cp_umask=$mode$u_plus_rw;; - esac -fi - -for src -do - # Protect names problematic for 'test' and other utilities. - case $src in - -* | [=\(\)!]) src=./$src;; - esac - - if test -n "$dir_arg"; then - dst=$src - dstdir=$dst - test -d "$dstdir" - dstdir_status=$? - else - - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dst_arg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - dst=$dst_arg - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test "$is_target_a_directory" = never; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 - fi - dstdir=$dst - dst=$dstdir/`basename "$src"` - dstdir_status=0 - else - dstdir=`dirname "$dst"` - test -d "$dstdir" - dstdir_status=$? - fi - fi - - obsolete_mkdir_used=false - - if test $dstdir_status != 0; then - case $posix_mkdir in - '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - # $RANDOM is not portable (e.g. dash); use it when possible to - # lower collision chance - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 - - # As "mkdir -p" follows symlinks and we work in /tmp possibly; so - # create the $tmpdir first (and fail if unsuccessful) to make sure - # that nobody tries to guess the $tmpdir name. - if (umask $mkdir_umask && - $mkdirprog $mkdir_mode "$tmpdir" && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - test_tmpdir="$tmpdir/a" - ls_ld_tmpdir=`ls -ld "$test_tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null - fi - trap '' 0;; - esac;; - esac - - if - $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" - ) - then : - else - - # The umask is ridiculous, or mkdir does not conform to POSIX, - # or it failed possibly due to a race condition. Create the - # directory the slow way, step by step, checking for races as we go. - - case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; - esac - - oIFS=$IFS - IFS=/ - set -f - set fnord $dstdir - shift - set +f - IFS=$oIFS - - prefixes= - - for d - do - test X"$d" = X && continue - - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ - done - - if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true - fi - fi - fi - - if test -n "$dir_arg"; then - { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && - { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || - test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 - else - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - - # Copy the file name to the temp name. - (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && - { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && - { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && - { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && - - # If -C, don't bother to copy if it wouldn't change the file. - if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - set -f && - set X $old && old=:$2:$4:$5:$6 && - set X $new && new=:$2:$4:$5:$6 && - set +f && - test "$old" = "$new" && - $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 - then - rm -f "$dsttmp" - else - # Rename the file to the real destination. - $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || - - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" - } - fi || exit 1 - - trap '' 0 - fi -done - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/install/radiance.conf b/install/radiance.conf index f601c9e..62e4c47 100644 --- a/install/radiance.conf +++ b/install/radiance.conf @@ -15,9 +15,9 @@ announce_interval = 1800 max_request_size = 4096 numwant_limit = 50 -mysql_host = -mysql_username = -mysql_password = +mysql_host = +mysql_username = +mysql_password = mysql_db = # The passwords must be 32 characters and match the Gazelle config @@ -37,4 +37,3 @@ syslog_level = info pid_file = radiance.pid [tester] - diff --git a/missing b/missing deleted file mode 100755 index f62bbae..0000000 --- a/missing +++ /dev/null @@ -1,215 +0,0 @@ -#! /bin/sh -# Common wrapper for a few potentially missing GNU programs. - -scriptversion=2013-10-28.13; # UTC - -# Copyright (C) 1996-2014 Free Software Foundation, Inc. -# Originally written by Fran,cois Pinard , 1996. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try '$0 --help' for more information" - exit 1 -fi - -case $1 in - - --is-lightweight) - # Used by our autoconf macros to check whether the available missing - # script is modern enough. - exit 0 - ;; - - --run) - # Back-compat with the calling convention used by older automake. - shift - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due -to PROGRAM being missing or too old. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal autoconf autoheader autom4te automake makeinfo - bison yacc flex lex help2man - -Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and -'g' are ignored when checking the name. - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: unknown '$1' option" - echo 1>&2 "Try '$0 --help' for more information" - exit 1 - ;; - -esac - -# Run the given program, remember its exit status. -"$@"; st=$? - -# If it succeeded, we are done. -test $st -eq 0 && exit 0 - -# Also exit now if we it failed (or wasn't found), and '--version' was -# passed; such an option is passed most likely to detect whether the -# program is present and works. -case $2 in --version|--help) exit $st;; esac - -# Exit code 63 means version mismatch. This often happens when the user -# tries to use an ancient version of a tool on a file that requires a -# minimum version. -if test $st -eq 63; then - msg="probably too old" -elif test $st -eq 127; then - # Program was missing. - msg="missing on your system" -else - # Program was found and executed, but failed. Give up. - exit $st -fi - -perl_URL=http://www.perl.org/ -flex_URL=http://flex.sourceforge.net/ -gnu_software_URL=http://www.gnu.org/software - -program_details () -{ - case $1 in - aclocal|automake) - echo "The '$1' program is part of the GNU Automake package:" - echo "<$gnu_software_URL/automake>" - echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/autoconf>" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - autoconf|autom4te|autoheader) - echo "The '$1' program is part of the GNU Autoconf package:" - echo "<$gnu_software_URL/autoconf/>" - echo "It also requires GNU m4 and Perl in order to run:" - echo "<$gnu_software_URL/m4/>" - echo "<$perl_URL>" - ;; - esac -} - -give_advice () -{ - # Normalize program name to check for. - normalized_program=`echo "$1" | sed ' - s/^gnu-//; t - s/^gnu//; t - s/^g//; t'` - - printf '%s\n' "'$1' is $msg." - - configure_deps="'configure.ac' or m4 files included by 'configure.ac'" - case $normalized_program in - autoconf*) - echo "You should only need it if you modified 'configure.ac'," - echo "or m4 files included by it." - program_details 'autoconf' - ;; - autoheader*) - echo "You should only need it if you modified 'acconfig.h' or" - echo "$configure_deps." - program_details 'autoheader' - ;; - automake*) - echo "You should only need it if you modified 'Makefile.am' or" - echo "$configure_deps." - program_details 'automake' - ;; - aclocal*) - echo "You should only need it if you modified 'acinclude.m4' or" - echo "$configure_deps." - program_details 'aclocal' - ;; - autom4te*) - echo "You might have modified some maintainer files that require" - echo "the 'autom4te' program to be rebuilt." - program_details 'autom4te' - ;; - bison*|yacc*) - echo "You should only need it if you modified a '.y' file." - echo "You may want to install the GNU Bison package:" - echo "<$gnu_software_URL/bison/>" - ;; - lex*|flex*) - echo "You should only need it if you modified a '.l' file." - echo "You may want to install the Fast Lexical Analyzer package:" - echo "<$flex_URL>" - ;; - help2man*) - echo "You should only need it if you modified a dependency" \ - "of a man page." - echo "You may want to install the GNU Help2man package:" - echo "<$gnu_software_URL/help2man/>" - ;; - makeinfo*) - echo "You should only need it if you modified a '.texi' file, or" - echo "any other file indirectly affecting the aspect of the manual." - echo "You might want to install the Texinfo package:" - echo "<$gnu_software_URL/texinfo/>" - echo "The spurious makeinfo call might also be the consequence of" - echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" - echo "want to install GNU make:" - echo "<$gnu_software_URL/make/>" - ;; - *) - echo "You might have modified some files without having the proper" - echo "tools for further handling them. Check the 'README' file, it" - echo "often tells you about the needed prerequisites for installing" - echo "this package. You may also peek at any GNU archive site, in" - echo "case some other package contains this missing '$1' program." - ;; - esac -} - -give_advice "$1" | sed -e '1s/^/WARNING: /' \ - -e '2,$s/^/ /' >&2 - -# Propagate the correct exit status (expected to be 127 for a program -# not found, 63 for a program that failed due to version mismatch). -exit $st - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: diff --git a/src/Makefile.am b/src/Makefile.am index 34343ea..190a383 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ sbin_PROGRAMS = radiance -radiance_SOURCES = ../config.h config.cpp config.h logger.h logger.cpp db.cpp db.h events.cpp events.h misc_functions.cpp \ +radiance_SOURCES = ../config.h config.cpp config.h logger.h logger.cpp database.cpp database.h events.cpp events.h misc_functions.cpp \ misc_functions.h radiance.cpp radiance.h report.cpp report.h response.cpp response.h domain.h debug.h debug.cpp\ domain.cpp schedule.cpp schedule.h site_comm.cpp site_comm.h user.cpp user.h worker.cpp worker.h diff --git a/src/config.cpp b/src/config.cpp index e141e92..4138a8a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include "config.h" #include "misc_functions.h" @@ -100,6 +100,8 @@ void settings::init() { add("mysql_path", ""); add("mysql_username", ""); add("mysql_password", ""); + add("mysql_connections", 8u); + add("mysql_timeout", 30u); // Site communication add("site_host", "127.0.0.1"); @@ -109,13 +111,14 @@ void settings::init() { add("report_password", "00000000000000000000000000000000"); // General Control - add("readonly", false); - add("load_peerlists", false); - add("daemonize", false); - add("syslog_path", "off"); - add("syslog_level", "trace"); - add("pid_file", "./radiance.pid"); - add("daemon_user", "root"); + add("readonly", false); + add("clear_peerlists", true); + add("load_peerlists", false); + add("daemonize", false); + add("syslog_path", "off"); + add("syslog_level", "info"); + add("pid_file", "./radiance.pid"); + add("daemon_user", "root"); } void options::init() { diff --git a/src/config.h b/src/config.h index 42bbdf1..722bb47 100644 --- a/src/config.h +++ b/src/config.h @@ -2,6 +2,9 @@ #define RADIANCE_CONFIG_H #include +#include +#include +#include #include class confval { diff --git a/src/db.cpp b/src/database.cpp similarity index 61% rename from src/db.cpp rename to src/database.cpp index 6a9cd14..a63426a 100644 --- a/src/db.cpp +++ b/src/database.cpp @@ -1,17 +1,5 @@ -#include -#include -#include -#include -#include "radiance.h" -#include "logger.h" -#include "db.h" -#include "user.h" -#include "misc_functions.h" -#include "config.h" -#include "logger.h" #include #include -#include #include #include #include @@ -19,61 +7,138 @@ #include #include +#include "radiance.h" +#include "logger.h" +#include "database.h" +#include "user.h" +#include "misc_functions.h" +#include "config.h" + #define DB_LOCK_TIMEOUT 50 -mysql::mysql() : u_active(false), t_active(false), p_active(false), s_active(false), h_active(false), tok_active(false) { +dbConnectionPool::dbConnectionPool() { load_config(); + if (mysql_db == "") { syslog(info) << "No database selected"; return; } +} + +dbConnectionPool::~dbConnectionPool() { + in_use_connections.clear(); + clear(true); +} + +mysqlpp::Connection* dbConnectionPool::grab() { + syslog(trace) << "MySQL connection grab called"; + while (in_use_connections.size() >= mysql_connections) { + syslog(error) << "MySQL Connection Pool Exhausted: " << mysqlpp::ConnectionPool::size() << " (" << in_use_connections.size() << ")";; + sleep(1); + } + + syslog(trace) << "MySQL connection issued: " << mysqlpp::ConnectionPool::size() << " (" << in_use_connections.size() << ")"; + mysqlpp::Connection* conn = mysqlpp::ConnectionPool::grab(); + std::lock_guard grab_lock(pool_lock); + in_use_connections.insert(conn); + return conn; +} + +void dbConnectionPool::release(const mysqlpp::ScopedConnection* conn) { + dbConnectionPool::release((mysqlpp::Connection*)conn); +} + +void dbConnectionPool::release(const mysqlpp::Connection* conn) { + syslog(trace) << "MySQL connection release called"; + std::lock_guard release_lock(pool_lock); + auto conn_index = in_use_connections.find((mysqlpp::Connection*)conn); + if (conn_index != in_use_connections.end()) { + in_use_connections.erase(conn_index); + } + mysqlpp::ConnectionPool::release(conn); + syslog(trace) << "MySQL connection released: " << mysqlpp::ConnectionPool::size() << " (" << in_use_connections.size() << ")"; +} + +mysqlpp::Connection* dbConnectionPool::create() { + syslog(trace) << "MySQL connection create called"; + mysqlpp::Connection* conn = new mysqlpp::Connection(); try { - conn.set_option(new mysqlpp::ReconnectOption(true)); - conn.connect(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); + conn->set_option(new mysqlpp::ReconnectOption(true)); + conn->connect(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), mysql_port); } catch (const mysqlpp::Exception &er) { syslog(error) << "Failed to connect to MySQL (" << er.what() << ')'; - return; + return NULL; } - syslog(info) << "Connected to MySQL"; + syslog(trace) << "MySQL connection created: " << mysqlpp::ConnectionPool::size() << " (" << in_use_connections.size() << ")"; + + return conn; +} + +mysqlpp::Connection* dbConnectionPool::exchange(const mysqlpp::Connection* conn) { + syslog(trace) << "MySQL connection exchange called"; + return mysqlpp::ConnectionPool::exchange((mysqlpp::Connection*)conn); +} + +mysqlpp::Connection* dbConnectionPool::exchange(const mysqlpp::ScopedConnection* conn) { + return dbConnectionPool::exchange((mysqlpp::Connection*)conn); +} + - if (!readonly && !load_peerlists) { - syslog(info) << "Clearing xbt_files_users and resetting peer counts..."; +void dbConnectionPool::destroy(mysqlpp::Connection* conn) { + delete conn; +} + +unsigned int dbConnectionPool::max_idle_time() { + return mysql_timeout; +} + +void dbConnectionPool::load_config() { + mysql_db = conf->get_str("mysql_db"); + mysql_host = conf->get_str("mysql_host"); + mysql_username = conf->get_str("mysql_username"); + mysql_password = conf->get_str("mysql_password"); + mysql_port = conf->get_uint("mysql_port"); + mysql_connections = conf->get_uint("mysql_connections"); + mysql_timeout = conf->get_uint("mysql_timeout"); +} + +database::database() : u_active(false), t_active(false), p_active(false), s_active(false), h_active(false), tok_active(false) { + load_config(); + pool = new dbConnectionPool; + + if (!readonly && !load_peerlists && clear_peerlists) { + syslog(info) << "Clearing peerlists and resetting peer counts..."; clear_peer_data(); syslog(info) << "done"; } } -void mysql::shutdown() { - conn.disconnect(); - conn.thread_end(); +void database::shutdown() { + delete pool; mysql_library_end(); } -void mysql::load_config() { - mysql_db = conf->get_str("mysql_db"); - mysql_host = conf->get_str("mysql_host"); - mysql_username = conf->get_str("mysql_username"); - mysql_password = conf->get_str("mysql_password"); - readonly = conf->get_bool("readonly"); - load_peerlists = conf->get_bool("load_peerlists"); +void database::load_config() { + readonly = conf->get_bool("readonly"); + clear_peerlists = conf->get_bool("clear_peerlists"); + load_peerlists = conf->get_bool("load_peerlists"); } -void mysql::reload_config() { +void database::reload_config() { load_config(); } -bool mysql::connected() { - return conn.connected(); -} - -void mysql::clear_peer_data() { +void database::clear_peer_data() { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to clear peer data"; + mysqlpp::ScopedConnection conn(*pool, true); try { - mysqlpp::Query query = conn.query("TRUNCATE xbt_files_users;"); + mysqlpp::Query query = conn->query("TRUNCATE xbt_files_users;"); if (!query.exec()) { syslog(error) << "Unable to truncate xbt_files_users!"; } - query = conn.query("UPDATE torrents SET Seeders = 0, Leechers = 0;"); + query = conn->query("UPDATE torrents SET Seeders = 0, Leechers = 0;"); if (!query.exec()) { syslog(error) << "Unable to reset seeder and leecher count!"; } @@ -82,12 +147,18 @@ void mysql::clear_peer_data() { } catch (const mysqlpp::Exception &er) { syslog(error) << "Query error in clear_peer_data: " << er.what(); } + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_site_options() { +void database::load_site_options() { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load site options"; + mysqlpp::ScopedConnection conn(*pool, true); for(auto &opt: opts->get_settings()) { try { - mysqlpp::Query query = conn.query(); + syslog(trace) << "Querying DB for " << opt.first << " option"; + mysqlpp::Query query = conn->query(); query << "SELECT Value FROM options WHERE Name=" << mysqlpp::quote << opt.first; if(mysqlpp::StoreQueryResult res = query.store()) { for (size_t i = 0; i < res.num_rows(); i++) { @@ -103,11 +174,16 @@ void mysql::load_site_options() { syslog(error) << "Query error in load_site_options: " << er.what(); } } + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_torrents(torrent_list &torrents) { - mysqlpp::Query query = conn.query("SELECT ID, info_hash, freetorrent, doubletorrent, Snatched FROM torrents ORDER BY ID;"); +void database::load_torrents(torrent_list &torrents) { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load torrents"; + mysqlpp::ScopedConnection conn(*pool, true); try { + mysqlpp::Query query = conn->query("SELECT ID, info_hash, freetorrent, doubletorrent, Snatched FROM torrents ORDER BY ID;"); mysqlpp::StoreQueryResult res = query.store(); std::unordered_set cur_keys; size_t num_rows = res.num_rows(); @@ -177,12 +253,16 @@ void mysql::load_torrents(torrent_list &torrents) { return; } syslog(trace) << "Loaded " << torrents.size() << " torrents"; - load_tokens(torrents); + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_users(user_list &users) { - mysqlpp::Query query = conn.query("SELECT um.ID, can_leech, torrent_pass, (Visible='0' OR u.IPID IS NULL) AS Protected, track_ipv6, personal_freeleech, personal_doubleseed FROM users_main AS um JOIN users AS u ON um.ID=u.ID WHERE Enabled='1'"); +void database::load_users(user_list &users) { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load users"; + mysqlpp::ScopedConnection conn(*pool, true); try { + mysqlpp::Query query = conn->query("SELECT um.ID, can_leech, torrent_pass, (Visible='0' OR u.IPID IS NULL) AS Protected, track_ipv6, personal_freeleech, personal_doubleseed FROM users_main AS um JOIN users AS u ON um.ID=u.ID WHERE Enabled='1'"); mysqlpp::StoreQueryResult res = query.store(); size_t num_rows = res.num_rows(); std::unordered_set cur_keys; @@ -230,21 +310,26 @@ void mysql::load_users(user_list &users) { syslog(error) << "Query error in load_users: " << er.what(); } syslog(trace) << "Loaded " << users.size() << " users"; + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_peers(torrent_list &torrents, user_list &users) { +void database::load_peers(torrent_list &torrents, user_list &users) { if (!load_peerlists) return; load_seeders(torrents, users); load_leechers(torrents, users); } -void mysql::load_seeders(torrent_list &torrents, user_list &users) { +void database::load_seeders(torrent_list &torrents, user_list &users) { if (!load_peerlists) return; size_t num_seeders = 0; + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load seeders"; + mysqlpp::ScopedConnection conn(*pool, true); try { for (auto &torrent_it: torrents) { torrent torrent = torrent_it.second; - mysqlpp::Query query = conn.query(); + mysqlpp::Query query = conn->query(); query << "SELECT um.torrent_pass, xfu.peer_id, xfu.port, xfu.ipv4, xfu.ipv6, xfu.uploaded," << " xfu.downloaded, xfu.remaining, xfu.corrupt, xfu.announced, xfu.ctime, xfu.mtime" << " FROM xbt_files_users AS xfu INNER JOIN users_main AS um ON xfu.uid=um.ID" @@ -329,15 +414,20 @@ void mysql::load_seeders(torrent_list &torrents, user_list &users) { syslog(error) << "Query error in load_seeders: " << er.what(); } syslog(trace) << "Loaded " << num_seeders << " seeders"; + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_leechers(torrent_list &torrents, user_list &users) { +void database::load_leechers(torrent_list &torrents, user_list &users) { if (!load_peerlists) return; size_t num_leechers = 0; + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load leechers"; + mysqlpp::ScopedConnection conn(*pool, true); try { for (auto &torrent_it: torrents) { torrent torrent = torrent_it.second; - mysqlpp::Query query = conn.query(); + mysqlpp::Query query = conn->query(); query << "SELECT um.torrent_pass, xfu.peer_id, xfu.port, xfu.ipv4, xfu.ipv6, xfu.uploaded," << " xfu.downloaded, xfu.remaining, xfu.corrupt, xfu.announced, xfu.ctime, xfu.mtime" << " FROM xbt_files_users AS xfu INNER JOIN users_main AS um ON xfu.uid=um.ID" @@ -422,9 +512,11 @@ void mysql::load_leechers(torrent_list &torrents, user_list &users) { syslog(error) << "Query error in load_leechers: " << er.what(); } syslog(trace) << "Loaded " << num_leechers << " leechers"; + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -peer_list::iterator mysql::add_peer(peer_list &peer_list, const std::string &peer_key) { +peer_list::iterator database::add_peer(peer_list &peer_list, const std::string &peer_key) { peer new_peer; auto it = peer_list.insert(std::pair(peer_key, new_peer)); return it.first; @@ -432,14 +524,17 @@ peer_list::iterator mysql::add_peer(peer_list &peer_list, const std::string &pee /* Peers should be invisible if they are a leecher without download privs or their IP is invalid */ -bool mysql::peer_is_visible(user_ptr &u, peer *p) { +bool database::peer_is_visible(user_ptr &u, peer *p) { return (p->left == 0 || u->can_leech()); } -void mysql::load_tokens(torrent_list &torrents) { - mysqlpp::Query query = conn.query("SELECT us.UserID, us.FreeLeech, us.DoubleSeed, t.info_hash FROM users_slots AS us JOIN torrents AS t ON t.ID = us.TorrentID WHERE FreeLeech >= NOW() OR DoubleSeed >= NOW();"); +void database::load_tokens(torrent_list &torrents) { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load tokens"; + mysqlpp::ScopedConnection conn(*pool, true); int token_count = 0; try { + mysqlpp::Query query = conn->query("SELECT us.UserID, us.FreeLeech, us.DoubleSeed, t.info_hash FROM users_slots AS us JOIN torrents AS t ON t.ID = us.TorrentID WHERE FreeLeech >= NOW() OR DoubleSeed >= NOW();"); mysqlpp::StoreQueryResult res = query.store(); size_t num_rows = res.num_rows(); std::lock_guard tl_lock(torrent_list_mutex); @@ -464,12 +559,17 @@ void mysql::load_tokens(torrent_list &torrents) { return; } syslog(trace) << "Loaded " << token_count << " tokens"; + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::load_blacklist(std::vector &blacklist) { - mysqlpp::Query query = conn.query("SELECT peer_id FROM xbt_client_blacklist;"); +void database::load_blacklist(std::vector &blacklist) { + mysqlpp::Connection::thread_start(); + syslog(trace) << "Connecting to DB to load blacklist"; + mysqlpp::ScopedConnection conn(*pool, true); try { + mysqlpp::Query query = conn->query("SELECT peer_id FROM xbt_client_blacklist;"); mysqlpp::StoreQueryResult res = query.store(); size_t num_rows = res.num_rows(); std::lock_guard wl_lock(blacklist_mutex); @@ -488,23 +588,25 @@ void mysql::load_blacklist(std::vector &blacklist) { } else { syslog(trace) << "Loaded " << blacklist.size() << " clients into the blacklist"; } + pool->release(&conn); + mysqlpp::Connection::thread_end(); } -void mysql::record_token(const std::string &record) { +void database::record_token(const std::string &record) { if (update_token_buffer != "") { update_token_buffer += ","; } update_token_buffer += record; } -void mysql::record_user(const std::string &record) { +void database::record_user(const std::string &record) { if (update_user_buffer != "") { update_user_buffer += ","; } update_user_buffer += record; } -void mysql::record_torrent(const std::string &record) { +void database::record_torrent(const std::string &record) { std::lock_guard tb_lock(torrent_buffer_lock); if (update_torrent_buffer != "") { update_torrent_buffer += ","; @@ -512,51 +614,55 @@ void mysql::record_torrent(const std::string &record) { update_torrent_buffer += record; } -void mysql::record_peer(const std::string &record, const std::string &ipv4, const std::string &ipv6, int port, const std::string &peer_id, const std::string &useragent) { +void database::record_peer(const std::string &record, const std::string &ipv4, const std::string &ipv6, int port, const std::string &peer_id, const std::string &useragent) { std::lock_guard pb_lock(peer_queue_lock); if (update_peer_heavy_buffer != "") { update_peer_heavy_buffer += ","; } - mysqlpp::Query q = conn.query(); - q << record << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ',' << port << ',' << mysqlpp::quote << peer_id << ',' << mysqlpp::quote << useragent << ')'; + // Null query for quoting + mysqlpp::Query query(NULL); + query << record << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ',' << port << ',' << mysqlpp::quote << peer_id << ',' << mysqlpp::quote << useragent << ')'; - update_peer_heavy_buffer += q.str(); + update_peer_heavy_buffer += query.str(); } -void mysql::record_peer(const std::string &record, const std::string &peer_id) { +void database::record_peer(const std::string &record, const std::string &peer_id) { std::lock_guard pb_lock(peer_queue_lock); if (update_peer_light_buffer != "") { update_peer_light_buffer += ","; } - mysqlpp::Query q = conn.query(); - q << record << mysqlpp::quote << peer_id << ')'; + // Null query for quoting + mysqlpp::Query query(NULL); + query << record << mysqlpp::quote << peer_id << ')'; - update_peer_light_buffer += q.str(); + update_peer_light_buffer += query.str(); } -void mysql::record_peer_hist(const std::string &record, const std::string &peer_id, const std::string &ipv4, const std::string &ipv6, int tid){ +void database::record_peer_hist(const std::string &record, const std::string &peer_id, const std::string &ipv4, const std::string &ipv6, int tid){ std::lock_guard ph_lock(peer_hist_queue_lock); if (update_peer_hist_buffer != "") { update_peer_hist_buffer += ","; } - mysqlpp::Query q = conn.query(); - q << record << ',' << mysqlpp::quote << peer_id << ',' << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ',' << tid << ',' << time(NULL) << ')'; - update_peer_hist_buffer += q.str(); + // Null query for quoting + mysqlpp::Query query(NULL); + query << record << ',' << mysqlpp::quote << peer_id << ',' << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ',' << tid << ',' << time(NULL) << ')'; + update_peer_hist_buffer += query.str(); } -void mysql::record_snatch(const std::string &record, const std::string &ipv4, const std::string &ipv6) { +void database::record_snatch(const std::string &record, const std::string &ipv4, const std::string &ipv6) { if (update_snatch_buffer != "") { update_snatch_buffer += ","; } - mysqlpp::Query q = conn.query(); - q << record << ',' << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ')'; - update_snatch_buffer += q.str(); + // Null query for quoting + mysqlpp::Query query(NULL); + query << record << ',' << mysqlpp::quote << ipv4 << ',' << mysqlpp::quote << ipv6 << ')'; + update_snatch_buffer += query.str(); } -bool mysql::all_clear() { +bool database::all_clear() { return (user_queue.empty() && torrent_queue.empty() && peer_queue.empty() && snatch_queue.empty() && token_queue.empty()); } -void mysql::flush() { +void database::flush() { flush_users(); flush_torrents(); flush_snatches(); @@ -565,7 +671,7 @@ void mysql::flush() { flush_tokens(); } -void mysql::flush_users() { +void database::flush_users() { if (readonly) { update_user_buffer.clear(); return; @@ -589,14 +695,15 @@ void mysql::flush_users() { " UploadedDaily = UploadedDaily + VALUES(UploadedDaily)," + " DownloadedDaily = DownloadedDaily + VALUES(DownloadedDaily)"; user_queue.push(sql); + stats.user_queue++; update_user_buffer.clear(); if (u_active == false) { - std::thread thread(&mysql::do_flush_users, this); + std::thread thread(&database::do_flush, this, std::ref(u_active), std::ref(user_queue), std::ref(user_queue_lock), std::ref(stats.user_queue), "user"); thread.detach(); } } -void mysql::flush_torrents() { +void database::flush_torrents() { std::lock_guard tb_lock(torrent_buffer_lock); if (readonly) { update_torrent_buffer.clear(); @@ -619,17 +726,19 @@ void mysql::flush_torrents() { "Snatched=Snatched+VALUES(Snatched), Balance=VALUES(Balance), last_action = " + "IF(VALUES(Seeders) > 0, NOW(), last_action)"; torrent_queue.push(sql); + stats.torrent_queue++; update_torrent_buffer.clear(); sql.clear(); sql = "DELETE FROM torrents WHERE info_hash = ''"; + stats.torrent_queue++; torrent_queue.push(sql); if (t_active == false) { - std::thread thread(&mysql::do_flush_torrents, this); + std::thread thread(&database::do_flush, this, std::ref(t_active), std::ref(torrent_queue), std::ref(torrent_queue_lock), std::ref(stats.torrent_queue), "torrent"); thread.detach(); } } -void mysql::flush_snatches() { +void database::flush_snatches() { if (readonly) { update_snatch_buffer.clear(); return; @@ -645,14 +754,15 @@ void mysql::flush_snatches() { } sql = "INSERT INTO xbt_snatched (uid, fid, tstamp, ipv4, ipv6) VALUES " + update_snatch_buffer; snatch_queue.push(sql); + stats.snatch_queue++; update_snatch_buffer.clear(); if (s_active == false) { - std::thread thread(&mysql::do_flush_snatches, this); + std::thread thread(&database::do_flush, this, std::ref(s_active), std::ref(snatch_queue), std::ref(snatch_queue_lock), std::ref(stats.snatch_queue), "snatch"); thread.detach(); } } -void mysql::flush_peers() { +void database::flush_peers() { if (readonly) { update_peer_light_buffer.clear(); update_peer_heavy_buffer.clear(); @@ -677,6 +787,7 @@ void mysql::flush_peers() { // but that's better than an oom crash if (qsize >= 1000) { peer_queue.pop(); + stats.peer_queue--; } sql = "INSERT INTO xbt_files_users (uid,fid,active,uploaded,downloaded,upspeed,downspeed,remaining,corrupt," + std::string("timespent,ctime,mtime,announced,ipv4,ipv6,port,peer_id,useragent) VALUES ") + update_peer_heavy_buffer + @@ -686,6 +797,7 @@ void mysql::flush_peers() { "corrupt=VALUES(corrupt), timespent=VALUES(timespent), " + "announced=VALUES(announced), mtime=VALUES(mtime), port=VALUES(port)"; peer_queue.push(sql); + stats.peer_queue++; update_peer_heavy_buffer.clear(); sql.clear(); } @@ -693,23 +805,25 @@ void mysql::flush_peers() { // See comment above if (qsize >= 1000) { peer_queue.pop(); + stats.peer_queue--; } sql = "INSERT INTO xbt_files_users (uid,fid,timespent,mtime,announced,peer_id) VALUES " + update_peer_light_buffer + " ON DUPLICATE KEY UPDATE upspeed=0, downspeed=0, timespent=VALUES(timespent), " + "announced=VALUES(announced), mtime=VALUES(mtime)"; peer_queue.push(sql); + stats.peer_queue++; update_peer_light_buffer.clear(); sql.clear(); } if (p_active == false) { - std::thread thread(&mysql::do_flush_peers, this); + std::thread thread(&database::do_flush, this, std::ref(p_active), std::ref(peer_queue), std::ref(peer_queue_lock), std::ref(stats.peer_queue), "peer"); thread.detach(); } } -void mysql::flush_peer_hist() { +void database::flush_peer_hist() { if (readonly) { update_token_buffer.clear(); return; @@ -722,14 +836,15 @@ void mysql::flush_peer_hist() { sql = "INSERT IGNORE INTO xbt_peers_history (uid, downloaded, remaining, uploaded, upspeed, downspeed, timespent, peer_id, ipv4, ipv6, fid, mtime) VALUES " + update_peer_hist_buffer; peer_hist_queue.push(sql); + stats.peer_hist_queue++; update_peer_hist_buffer.clear(); if (h_active == false) { - std::thread thread(&mysql::do_flush_peer_hist, this); + std::thread thread(&database::do_flush, this, std::ref(h_active), std::ref(peer_hist_queue), std::ref(peer_hist_queue_lock), std::ref(stats.peer_hist_queue), "peer history"); thread.detach(); } } -void mysql::flush_tokens() { +void database::flush_tokens() { if (readonly) { update_token_buffer.clear(); return; @@ -746,271 +861,59 @@ void mysql::flush_tokens() { sql = "INSERT INTO users_freeleeches (UserID, TorrentID, Downloaded, Uploaded) VALUES " + update_token_buffer + " ON DUPLICATE KEY UPDATE Downloaded = Downloaded + VALUES(Downloaded), Uploaded = Uploaded + VALUES(Uploaded)"; token_queue.push(sql); + stats.token_queue++; update_token_buffer.clear(); if (tok_active == false) { - std::thread thread(&mysql::do_flush_tokens, this); + std::thread thread(&database::do_flush, this, std::ref(tok_active), std::ref(token_queue), std::ref(token_queue_lock), std::ref(stats.token_queue), "token"); thread.detach(); } } -void mysql::do_flush_users() { - u_active = true; +void database::do_flush(bool &active, std::queue &queue, std::mutex &lock, std::atomic &queue_size, const std::string queue_name) { + active = true; + mysqlpp::Connection::thread_start(); try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!user_queue.empty()) { + while (!queue.empty()) { + syslog(trace) << "Connecting to DB to flush " << queue_name << "s"; + mysqlpp::ScopedConnection conn(*pool, true); try { - std::string sql = user_queue.front(); + std::string sql = queue.front(); if (sql == "") { - user_queue.pop(); + queue.pop(); + queue_size--; continue; } - mysqlpp::Query query = c.query(sql); + mysqlpp::Query query = conn->query(sql); auto start_time = std::chrono::high_resolution_clock::now(); if (!query.exec()) { - syslog(error) << "User flush failed (" << user_queue.size() << " remain)"; + syslog(error) << queue_name << " flush failed (" << queue.size() << " remain)"; + pool->release(&conn); sleep(3); continue; } else { - std::lock_guard uq_lock(user_queue_lock); - user_queue.pop(); + std::lock_guard local_lock(lock); + queue.pop(); + queue_size--; } auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Users flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; + syslog(trace) << queue_name << "s flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; } catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush users with a qlength: " << user_queue.front().size() << " queue size: " << user_queue.size(); + syslog(error) << "Query error: " << er.what() << " in flush " << queue_name << "s with a qlength: " << queue.front().size() << " queue size: " << queue.size(); + pool->release(&conn); sleep(3); continue; } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush users with a qlength: " << user_queue.front().size() << " queue size: " << user_queue.size(); + syslog(error) << "Query error: " << er.what() << " in flush " << queue_name << "s with a qlength: " << queue.front().size() << " queue size: " << queue.size(); + pool->release(&conn); sleep(3); continue; } } - c.thread_end(); } catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_users: " << er.what(); + syslog(error) << "MySQL error in flush " << queue_name << "s: " << er.what(); } - u_active = false; -} - -void mysql::do_flush_torrents() { - t_active = true; - try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!torrent_queue.empty()) { - try { - std::string sql = torrent_queue.front(); - if (sql == "") { - torrent_queue.pop(); - continue; - } - mysqlpp::Query query = c.query(sql); - auto start_time = std::chrono::high_resolution_clock::now(); - if (!query.exec()) { - syslog(error) << "Torrent flush failed (" << torrent_queue.size() << " remain)"; - sleep(3); - continue; - } else { - std::lock_guard tq_lock(torrent_queue_lock); - torrent_queue.pop(); - } - auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Torrents flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; - } - catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush torrents with a qlength: " << torrent_queue.front().size() << " queue size: " << torrent_queue.size(); - sleep(3); - continue; - } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush torrents with a qlength: " << torrent_queue.front().size() << " queue size: " << torrent_queue.size(); - sleep(3); - continue; - } - } - c.thread_end(); - } - catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_torrents: " << er.what(); - } - t_active = false; -} - -void mysql::do_flush_peers() { - p_active = true; - try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!peer_queue.empty()) { - try { - std::string sql = peer_queue.front(); - if (sql == "") { - peer_queue.pop(); - continue; - } - mysqlpp::Query query = c.query(sql); - auto start_time = std::chrono::high_resolution_clock::now(); - if (!query.exec()) { - syslog(error) << "Peer flush failed (" << peer_queue.size() << " remain)"; - sleep(3); - continue; - } else { - std::lock_guard pq_lock(peer_queue_lock); - peer_queue.pop(); - } - auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Peers flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; - } - catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush peers with a qlength: " << peer_queue.front().size() << " queue size: " << peer_queue.size(); - sleep(3); - continue; - } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush peers with a qlength: " << peer_queue.front().size() << " queue size: " << peer_queue.size(); - sleep(3); - continue; - } - } - c.thread_end(); - } - catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_peers: " << er.what(); - } - p_active = false; -} - - -void mysql::do_flush_peer_hist() { - h_active = true; - try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!peer_hist_queue.empty()) { - try { - std::string sql = peer_hist_queue.front(); - if (sql == "") { - peer_hist_queue.pop(); - continue; - } - mysqlpp::Query query = c.query(sql); - auto start_time = std::chrono::high_resolution_clock::now(); - if (!query.exec()) { - syslog(error) << "Peer history flush failed (" << peer_hist_queue.size() << " remain)"; - sleep(3); - continue; - } else { - std::lock_guard ph_lock(peer_hist_queue_lock); - peer_hist_queue.pop(); - } - auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Peer History flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; - } - catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush peer history with a qlength: " << peer_hist_queue.front().size() << " queue size: " << peer_hist_queue.size(); - sleep(3); - continue; - } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush peer history with a qlength: " << peer_hist_queue.front().size() << " queue size: " << peer_hist_queue.size(); - sleep(3); - continue; - } - } - c.thread_end(); - } - catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_peer_hist: " << er.what(); - } - h_active = false; -} - -void mysql::do_flush_snatches() { - s_active = true; - try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!snatch_queue.empty()) { - try { - std::string sql = snatch_queue.front(); - if (sql == "") { - snatch_queue.pop(); - continue; - } - mysqlpp::Query query = c.query(sql); - auto start_time = std::chrono::high_resolution_clock::now(); - if (!query.exec()) { - syslog(error) << "Snatch flush failed (" << snatch_queue.size() << " remain)"; - sleep(3); - continue; - } else { - std::lock_guard sq_lock(snatch_queue_lock); - snatch_queue.pop(); - } - auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Snatches flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; - } - catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush snatches with a qlength: " << snatch_queue.front().size() << " queue size: " << snatch_queue.size(); - sleep(3); - continue; - } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush snatches with a qlength: " << snatch_queue.front().size() << " queue size: " << snatch_queue.size(); - sleep(3); - continue; - } - } - c.thread_end(); - } - catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_snatches: " << er.what(); - } - s_active = false; -} - -void mysql::do_flush_tokens() { - tok_active = true; - try { - mysqlpp::Connection c(mysql_db.c_str(), mysql_host.c_str(), mysql_username.c_str(), mysql_password.c_str(), 0); - while (!token_queue.empty()) { - try { - std::string sql = token_queue.front(); - if (sql == "") { - token_queue.pop(); - continue; - } - mysqlpp::Query query = c.query(sql); - auto start_time = std::chrono::high_resolution_clock::now(); - if (!query.exec()) { - syslog(error) << "Token flush failed (" << token_queue.size() << " remain)"; - sleep(3); - continue; - } else { - std::lock_guard tq_lock(token_queue_lock); - token_queue.pop(); - } - auto end_time = std::chrono::high_resolution_clock::now(); - syslog(trace) << "Tokens flushed in " << std::chrono::duration_cast(end_time - start_time).count() << " microseconds."; - } - catch (const mysqlpp::BadQuery &er) { - syslog(error) << "Query error: " << er.what() << " in flush tokens with a qlength: " << token_queue.front().size() << " queue size: " << token_queue.size(); - sleep(3); - continue; - } catch (const mysqlpp::Exception &er) { - syslog(error) << "Query error: " << er.what() << " in flush tokens with a qlength: " << token_queue.front().size() << " queue size: " << token_queue.size(); - sleep(3); - continue; - } - } - c.thread_end(); - } - catch (const mysqlpp::Exception &er) { - syslog(error) << "MySQL error in flush_tokens: " << er.what(); - } - tok_active = false; -} - -void mysql::report() { - stats.db.torrent_queue = torrent_queue.size(); - stats.db.user_queue = user_queue.size(); - stats.db.peer_queue = peer_queue.size(); - stats.db.peer_hist_queue = peer_hist_queue.size(); - stats.db.snatch_queue = snatch_queue.size(); - stats.db.token_queue = token_queue.size(); + mysqlpp::Connection::thread_end(); + active = false; } diff --git a/src/db.h b/src/database.h similarity index 76% rename from src/db.h rename to src/database.h index 67f2d54..bf73875 100644 --- a/src/db.h +++ b/src/database.h @@ -4,13 +4,36 @@ #include #include #include +#include #include #include -#include "config.h" -class mysql { +class dbConnectionPool : public mysqlpp::ConnectionPool { private: - mysqlpp::Connection conn; + void load_config(); + unsigned int mysql_port, mysql_connections, mysql_timeout; + std::string mysql_db, mysql_host, mysql_username, mysql_password; + std::unordered_set in_use_connections; + std::mutex pool_lock; + + public: + dbConnectionPool(); + ~dbConnectionPool(); + mysqlpp::Connection* grab(); + mysqlpp::Connection* exchange(const mysqlpp::Connection* conn); + mysqlpp::Connection* exchange(const mysqlpp::ScopedConnection* conn); + void release(const mysqlpp::Connection* conn); + void release(const mysqlpp::ScopedConnection* conn); + + protected: + mysqlpp::Connection* create(); + void destroy(mysqlpp::Connection* conn); + unsigned int max_idle_time(); +}; + +class database { + private: + dbConnectionPool* pool; std::string update_user_buffer; std::string update_torrent_buffer; std::string update_peer_heavy_buffer; @@ -26,9 +49,8 @@ class mysql { std::queue snatch_queue; std::queue token_queue; - std::string mysql_db, mysql_host, mysql_username, mysql_password; bool u_active, t_active, p_active, s_active, h_active, tok_active; - bool readonly, load_peerlists; + bool readonly, load_peerlists, clear_peerlists; // These locks prevent more than one thread from reading/writing the buffers. // These should be held for the minimum time possible. @@ -41,14 +63,7 @@ class mysql { std::mutex token_queue_lock; void load_config(); - void load_tokens(torrent_list &torrents); - void do_flush_users(); - void do_flush_torrents(); - void do_flush_snatches(); - void do_flush_peers(); - void do_flush_peer_hist(); - void do_flush_tokens(); void flush_users(); void flush_torrents(); @@ -56,18 +71,19 @@ class mysql { void flush_peers(); void flush_peer_hist(); void flush_tokens(); + void do_flush(bool &active, std::queue &queue, std::mutex &lock, std::atomic &queue_size, const std::string queue_name); void clear_peer_data(); peer_list::iterator add_peer(peer_list &peer_list, const std::string &peer_id); static inline bool peer_is_visible(user_ptr &u, peer *p); public: - mysql(); + database(); void shutdown(); void reload_config(); - bool connected(); void load_site_options(); void load_torrents(torrent_list &torrents); + void load_tokens(torrent_list &torrents); void load_users(user_list &users); void load_peers(torrent_list &torrents, user_list &users); void load_seeders(torrent_list &torrents, user_list &users); @@ -83,11 +99,8 @@ class mysql { void record_token(const std::string &record); void flush(); - bool all_clear(); - void report(); - std::mutex torrent_list_mutex; std::mutex user_list_mutex; std::mutex domain_list_mutex; diff --git a/src/debug.cpp b/src/debug.cpp index bfacb6c..01f0c52 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -1,6 +1,9 @@ #include +#include "../autoconf.h" +#include "debug.h" -#if(__DEBUG_BUILD__) +#if defined(__DEBUG_BUILD__) +#include #include #include #include diff --git a/src/debug.h b/src/debug.h index 625001e..c215cfb 100644 --- a/src/debug.h +++ b/src/debug.h @@ -2,6 +2,8 @@ #define DEBUG__H #include +#if defined(__DEBUG_BUILD__) std::string backtrace(int skip); +#endif #endif diff --git a/src/domain.cpp b/src/domain.cpp index 2d28c48..ac12e8d 100644 --- a/src/domain.cpp +++ b/src/domain.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "domain.h" domain::domain(std::string host) : host(host) {} diff --git a/src/domain.h b/src/domain.h index f814b5f..3acb5dd 100644 --- a/src/domain.h +++ b/src/domain.h @@ -1,9 +1,6 @@ #ifndef DOMAIN_H #define DOMAIN_H -#include -#include "radiance.h" - class domain { public: std::string host; diff --git a/src/events.cpp b/src/events.cpp index 0cda2b1..2f098e0 100644 --- a/src/events.cpp +++ b/src/events.cpp @@ -1,13 +1,17 @@ #include #include #include +#include #include + #include "radiance.h" -#include "config.h" -#include "worker.h" -#include "schedule.h" #include "response.h" #include "events.h" +#include "worker.h" +#include "schedule.h" +#include "site_comm.h" +#include "config.h" +#include "logger.h" // Define the connection mother (first half) and connection middlemen (second half) diff --git a/src/events.h b/src/events.h index d142c38..fbbb71b 100644 --- a/src/events.h +++ b/src/events.h @@ -11,21 +11,10 @@ #include #include -#include "config.h" -#include "worker.h" -#include "schedule.h" -#include "site_comm.h" - -/* -TODO find out what these do -#include -#include -#include -*/ - - - - +// Forward declarations +class worker; +class schedule; +class site_comm; /* We have three classes - the mother, the middlemen, and the worker @@ -44,9 +33,6 @@ THE WORKER see worker.h for the worker. */ - - - // THE MOTHER - Spawns connection middlemen class connection_mother { private: diff --git a/src/logger.cpp b/src/logger.cpp index 6b9d23e..75f10d7 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -1,6 +1,9 @@ #define BOOST_LOG_DYN_LINK 1 +#include "../autoconf.h" #include "radiance.h" +#include "logger.h" +#include "config.h" #include #include #include @@ -32,7 +35,7 @@ void init_log(void) { boost::log::core::get()->add_global_attribute("Scope", boost::log::attributes::named_scope()); - auto severity = boost::log::trivial::trace; + auto severity = boost::log::trivial::info; if(conf->get_str("syslog_level") == "trace") severity=boost::log::trivial::trace; else if(conf->get_str("syslog_level") == "debug") severity=boost::log::trivial::debug; else if(conf->get_str("syslog_level") == "info") severity=boost::log::trivial::info; @@ -76,7 +79,7 @@ void init_log(void) { ); fsSink->set_formatter(fileLogFmt); - #if(__DEBUG_BUILD__) + #if defined(__DEBUG_BUILD__) fsSink->locked_backend()->auto_flush(true); #endif } else { diff --git a/src/logger.h b/src/logger.h index f5bb739..5c2b76a 100644 --- a/src/logger.h +++ b/src/logger.h @@ -3,20 +3,7 @@ #ifndef RADIANCE_LOGGER_H #define RADIANCE_LOGGER_H -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include enum severity_level { diff --git a/src/misc_functions.cpp b/src/misc_functions.cpp index 5a3c15c..13d6605 100644 --- a/src/misc_functions.cpp +++ b/src/misc_functions.cpp @@ -5,6 +5,8 @@ #include #include +#include "misc_functions.h" + static int lockReg(int fd, int cmd, int type, int whence, int start, off_t len) { struct flock fl; fl.l_type = type; diff --git a/src/radiance.cpp b/src/radiance.cpp index e3d2845..42f5c60 100644 --- a/src/radiance.cpp +++ b/src/radiance.cpp @@ -5,21 +5,21 @@ #include #include +#include "../autoconf.h" #include "radiance.h" -#include "logger.h" -#include "config.h" -#include "db.h" +#include "database.h" #include "worker.h" #include "events.h" #include "schedule.h" #include "site_comm.h" #include "misc_functions.h" #include "debug.h" -#include "../config.h" // Used to fetch PACKAGE_VERSION string +#include "config.h" +#include "logger.h" static connection_mother *mother; static worker *work; -static mysql *db; +static database *db; static site_comm *sc; static schedule *sched; @@ -111,7 +111,7 @@ static void sig_handler(int sig) { syslog(info) << "Reloading from database"; std::thread w_thread(&worker::reload_lists, work); w_thread.detach(); -#if(__DEBUG_BUILD__) +#if defined(__DEBUG_BUILD__) } else if (sig == SIGSEGV) { // print out all the frames to stderr syslog(fatal) << "SegFault:" << '\n' << backtrace(1); @@ -141,7 +141,7 @@ int main(int argc, char **argv) { conf_arg = true; conf_file_path = argv[++i]; } else { - std::cout << "Usage: " << argv[0] << " [-d] [-c configfile]" << std::endl; + std::cout << "Usage: " << argv[0] << "[-v] [-d] [-c configfile]" << std::endl; return 0; } } @@ -193,13 +193,7 @@ int main(int argc, char **argv) { syslog(info) << "Running in Foreground"; } - db = new mysql(); - - if (!db->connected()) { - syslog(info) << "Exiting"; - return 0; - } - + db = new database(); sc = new site_comm(); users_list = new user_list; @@ -210,6 +204,7 @@ int main(int argc, char **argv) { db->load_site_options(); db->load_users(*users_list); db->load_torrents(*torrents_list); + db->load_tokens(*torrents_list); db->load_peers(*torrents_list, *users_list); db->load_blacklist(blacklist); @@ -226,12 +221,12 @@ int main(int argc, char **argv) { stats.bytes_read = 0; stats.bytes_written = 0; - stats.db.torrent_queue = 0; - stats.db.user_queue = 0; - stats.db.peer_queue = 0; - stats.db.peer_hist_queue = 0; - stats.db.snatch_queue = 0; - stats.db.token_queue = 0; + stats.torrent_queue = 0; + stats.user_queue = 0; + stats.peer_queue = 0; + stats.peer_hist_queue = 0; + stats.snatch_queue = 0; + stats.token_queue = 0; stats.start_time = time(NULL); diff --git a/src/radiance.h b/src/radiance.h index 48b32bb..8ea5178 100644 --- a/src/radiance.h +++ b/src/radiance.h @@ -1,6 +1,9 @@ #ifndef RADIANCE_H #define RADIANCE_H +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + #include #include #include @@ -14,9 +17,6 @@ #include #include -#include "config.h" -#include "logger.h" - typedef uint32_t torid_t; typedef uint32_t userid_t; @@ -26,6 +26,12 @@ typedef std::shared_ptr user_ptr; class domain; typedef std::shared_ptr domain_ptr; +class settings; +extern settings *conf; + +class options; +extern options *opts; + typedef struct { int64_t uploaded; int64_t downloaded; @@ -114,14 +120,6 @@ typedef std::unordered_map user_list; typedef std::unordered_map domain_list; typedef std::unordered_map params_type; -struct stats_db_t { - std::atomic torrent_queue; - std::atomic user_queue; - std::atomic peer_queue; - std::atomic peer_hist_queue; - std::atomic snatch_queue; - std::atomic token_queue; -}; struct stats_t { std::atomic open_connections; @@ -138,10 +136,13 @@ struct stats_t { std::atomic bytes_written; std::atomic ipv6_peers; std::atomic ipv4_peers; - stats_db_t db; + std::atomic torrent_queue; + std::atomic user_queue; + std::atomic peer_queue; + std::atomic peer_hist_queue; + std::atomic snatch_queue; + std::atomic token_queue; time_t start_time; }; extern struct stats_t stats; -extern settings *conf; -extern options *opts; #endif diff --git a/src/report.cpp b/src/report.cpp index 537584f..04952eb 100644 --- a/src/report.cpp +++ b/src/report.cpp @@ -1,7 +1,6 @@ #include #include #include -#include "radiance.h" #include "misc_functions.h" #include "report.h" #include "response.h" @@ -46,12 +45,12 @@ std::string report(params_type ¶ms, user_list &users_list, domain_list &doma << "}" << std::endl; } else if (action == "db") { output << "{" << std::endl - << R"( "torrent_queue": )" << stats.db.torrent_queue << ',' << std::endl - << R"( "user_queue": )" << stats.db.user_queue << ',' << std::endl - << R"( "peer_queue": )" << stats.db.peer_queue << ',' << std::endl - << R"( "peer_hist_queue": )" << stats.db.peer_hist_queue << ',' << std::endl - << R"( "snatch_queue": )" << stats.db.snatch_queue << ',' << std::endl - << R"( "token_queue": )" << stats.db.token_queue << std::endl + << R"( "torrent_queue": )" << stats.torrent_queue << ',' << std::endl + << R"( "user_queue": )" << stats.user_queue << ',' << std::endl + << R"( "peer_queue": )" << stats.peer_queue << ',' << std::endl + << R"( "peer_hist_queue": )" << stats.peer_hist_queue << ',' << std::endl + << R"( "snatch_queue": )" << stats.snatch_queue << ',' << std::endl + << R"( "token_queue": )" << stats.token_queue << std::endl << "}" << std::endl; } else if (action == "domain") { output << "{" << std::endl; diff --git a/src/response.cpp b/src/response.cpp index 6cdb12b..290a0dd 100644 --- a/src/response.cpp +++ b/src/response.cpp @@ -2,9 +2,10 @@ #include #include #include + +#include "../autoconf.h" #include "response.h" #include "misc_functions.h" -#include "../config.h" // Used to fetch PACKAGE_VERSION string const std::string response(const std::string &body, client_opts_t &client_opts, uint16_t response) { std::string out; diff --git a/src/schedule.cpp b/src/schedule.cpp index 39d9af2..0d29367 100644 --- a/src/schedule.cpp +++ b/src/schedule.cpp @@ -1,13 +1,15 @@ #include +#include "../autoconf.h" #include "radiance.h" #include "config.h" -#include "db.h" +#include "database.h" #include "worker.h" #include "logger.h" +#include "site_comm.h" #include "schedule.h" -schedule::schedule(worker * worker_obj, mysql * db_obj, site_comm * sc_obj) : work(worker_obj), db(db_obj), sc(sc_obj) { +schedule::schedule(worker * worker_obj, database * db_obj, site_comm * sc_obj) : work(worker_obj), db(db_obj), sc(sc_obj) { load_config(); counter = 0; last_opened_connections = 0; @@ -38,7 +40,7 @@ void schedule::handle(ev::timer &watcher, int events_flags) { if (work->get_status() == CLOSING && db->all_clear() && sc->all_clear()) { db->shutdown(); -#if(__DEBUG_BUILD__) +#if defined(__DEBUG_BUILD__) delete work; // delete sched; // delete mother; @@ -55,7 +57,6 @@ void schedule::handle(ev::timer &watcher, int events_flags) { last_opened_connections = stats.opened_connections; last_request_count = stats.requests; - db->report(); db->flush(); sc->flush_tokens(); diff --git a/src/schedule.h b/src/schedule.h index a299a4f..5c0941d 100644 --- a/src/schedule.h +++ b/src/schedule.h @@ -8,14 +8,14 @@ class schedule { unsigned int reap_peers_interval; worker * work; - mysql * db; + database * db; site_comm * sc; uint64_t last_opened_connections; uint64_t last_request_count; unsigned int counter; int next_reap_peers; public: - schedule(worker * worker_obj, mysql * db_obj, site_comm * sc_obj); + schedule(worker * worker_obj, database * db_obj, site_comm * sc_obj); void reload_config(); void handle(ev::timer &watcher, int events_flags); diff --git a/src/site_comm.cpp b/src/site_comm.cpp index bb2055d..ee49ccb 100644 --- a/src/site_comm.cpp +++ b/src/site_comm.cpp @@ -9,8 +9,9 @@ #include #include "radiance.h" -#include "config.h" #include "site_comm.h" +#include "config.h" +#include "logger.h" using boost::asio::ip::tcp; diff --git a/src/site_comm.h b/src/site_comm.h index 0fcf1fa..42b2fb0 100644 --- a/src/site_comm.h +++ b/src/site_comm.h @@ -5,8 +5,6 @@ #include #include -#include "config.h" - using boost::asio::ip::tcp; class site_comm { diff --git a/src/worker.cpp b/src/worker.cpp index cf433f2..4045391 100644 --- a/src/worker.cpp +++ b/src/worker.cpp @@ -13,19 +13,20 @@ #include #include -#include "radiance.h" +#include "../autoconf.h" #include "config.h" -#include "db.h" #include "worker.h" -#include "misc_functions.h" +#include "database.h" #include "site_comm.h" +#include "misc_functions.h" #include "response.h" #include "report.h" #include "user.h" #include "domain.h" +#include "logger.h" //---------- Worker - does stuff with input -worker::worker(torrent_list &torrents, user_list &users, domain_list &domains, std::vector &_blacklist, mysql * db_obj, site_comm * sc) : +worker::worker(torrent_list &torrents, user_list &users, domain_list &domains, std::vector &_blacklist, database * db_obj, site_comm * sc) : db(db_obj), s_comm(sc), torrents_list(torrents), users_list(users), domains_list(domains), blacklist(_blacklist), status(OPEN), reaper_active(false) { load_config(); @@ -64,6 +65,9 @@ void worker::reload_lists() { bool worker::shutdown() { if (status == OPEN) { status = CLOSING; + while(reaper_active) { + sleep(1); + } torrents_list.clear(); users_list.clear(); domains_list.clear(); @@ -71,7 +75,7 @@ bool worker::shutdown() { delete &torrents_list; delete &users_list; delete &domains_list; - syslog(info) << "closing tracker... press Ctrl-C again to terminate"; + syslog(info) << "flushing DB buffers... press Ctrl-C again to terminate immediately"; return false; } else if (status == CLOSING) { syslog(info) << "shutting down uncleanly"; @@ -193,7 +197,7 @@ std::string worker::work(const std::string &input, std::string &ip, uint16_t &ip bool found_data = false; for (; pos < input_length; ++pos) { - if (std::strncmp(&input[pos], ": ", 2) == 0) { // Look for `: "` explicitly + if (unlikely(std::strncmp(&input[pos], ": ", 2) == 0)) { // Look for `: "` explicitly parsing_key = false; ++pos; // skip space after : } else if (input[pos] == '\n' || input[pos] == '\r') { @@ -906,7 +910,7 @@ std::string worker::announce(const std::string &input, torrent &tor, user_ptr &u inet_pton(AF_INET6, str, &(sa6.sin6_addr)); if (ipv6_is_public(sa6.sin6_addr)) { stats.ipv6_peers++; - syslog(trace) << "Peer with IPv6 address " << str << " added." << std::endl; + syslog(trace) << "Peer with IPv6 address " << str << " added."; } } if(!p->ipv4.empty()){ @@ -916,7 +920,7 @@ std::string worker::announce(const std::string &input, torrent &tor, user_ptr &u inet_pton(AF_INET, str, &(sa.sin_addr)); if (ipv4_is_public(sa.sin_addr)) { stats.ipv4_peers++; - syslog(trace) << "Peer with IPv4 address " << str << " added." << std::endl; + syslog(trace) << "Peer with IPv4 address " << str << " added."; } } } @@ -928,7 +932,7 @@ std::string worker::announce(const std::string &input, torrent &tor, user_ptr &u inet_pton(AF_INET6, str, &(sa6.sin6_addr)); if (ipv6_is_public(sa6.sin6_addr)) { stats.ipv6_peers--; - syslog(trace) << "Peer with IPv6 address " << str << " removed." << std::endl; + syslog(trace) << "Peer with IPv6 address " << str << " removed." ; } } if(!p->ipv4.empty()){ @@ -938,7 +942,7 @@ std::string worker::announce(const std::string &input, torrent &tor, user_ptr &u inet_pton(AF_INET, str, &(sa.sin_addr)); if (ipv4_is_public(sa.sin_addr)) { stats.ipv4_peers--; - syslog(trace) << "Peer with IPv4 address " << str << " removed." << std::endl; + syslog(trace) << "Peer with IPv4 address " << str << " removed."; } } } @@ -1430,84 +1434,98 @@ void worker::do_start_reaper() { } void worker::reap_peers() { - syslog(trace) << "Starting peer reaper"; + syslog(debug) << "Starting peer reaper"; cur_time = time(NULL); - unsigned int reaped_l = 0, reaped_s = 0, reaped_fl = 0; + unsigned int reaped_l = 0, reaped_v4l = 0, reaped_v6l = 0; + unsigned int reaped_s = 0, reaped_v4s = 0, reaped_v6s = 0; + unsigned int reaped_fl = 0; unsigned int cleared_torrents = 0; - for (auto t = torrents_list.begin(); t != torrents_list.end(); ++t) { + for (auto torrent = torrents_list.begin(); torrent != torrents_list.end(); torrent++) { bool reaped_this = false; // True if at least one peer was deleted from the current torrent - auto p = t->second.leechers.begin(); + auto p = torrent->second.leechers.begin(); peer_list::iterator del_p; - while (p != t->second.leechers.end()) { + while (p != torrent->second.leechers.end()) { if (p->second.last_announced + peers_timeout < cur_time) { std::lock_guard tl_lock(db->torrent_list_mutex); + if(!p->second.ipv6.empty()) reaped_v6l++; + if(!p->second.ipv4.empty()) reaped_v4l++; + reaped_l++; + reaped_this = true; del_p = p++; del_p->second.user->decr_leeching(); - t->second.leechers.erase(del_p); - reaped_this = true; - stats.leechers--; - if(!p->second.ipv6.empty()) stats.ipv6_peers--; - if(!p->second.ipv4.empty()) stats.ipv4_peers--; + torrent->second.leechers.erase(del_p); } else { ++p; } } - p = t->second.seeders.begin(); - while (p != t->second.seeders.end()) { + p = torrent->second.seeders.begin(); + while (p != torrent->second.seeders.end()) { if (p->second.last_announced + peers_timeout < cur_time) { std::lock_guard tl_lock(db->torrent_list_mutex); + if(!p->second.ipv6.empty()) reaped_v6s++; + if(!p->second.ipv4.empty()) reaped_v4s++; + reaped_s++; + reaped_this = true; del_p = p++; del_p->second.user->decr_seeding(); - t->second.seeders.erase(del_p); - reaped_this = true; - stats.seeders--; - if(!p->second.ipv6.empty()) stats.ipv6_peers--; - if(!p->second.ipv4.empty()) stats.ipv4_peers--; + torrent->second.seeders.erase(del_p); } else { ++p; } } - auto fl = t->second.tokened_users.begin(); + auto fl = torrent->second.tokened_users.begin(); slots_list::iterator del_fl; - while (fl != t->second.tokened_users.end()) { + while (fl != torrent->second.tokened_users.end()) { if (fl->second.free_leech < cur_time && fl->second.double_seed < cur_time) { std::lock_guard tl_lock(db->torrent_list_mutex); del_fl = fl++; - t->second.tokened_users.erase(del_fl); + torrent->second.tokened_users.erase(del_fl); reaped_this = true; reaped_fl++; } else { ++fl; } } - if (reaped_this && t->second.seeders.empty() && t->second.leechers.empty()) { + if (reaped_this) { + syslog(trace) << "Reaped peers for torrent: " << torrent->second.id; + } else { + syslog(trace) << "Skipped torrent: " << torrent->second.id; + } + if (reaped_this && torrent->second.seeders.empty() && torrent->second.leechers.empty()) { std::stringstream record; - record << '(' << t->second.id << ",0,0,0," << t->second.balance << ')'; + record << '(' << torrent->second.id << ",0,0,0," << torrent->second.balance << ')'; std::string record_str = record.str(); db->record_torrent(record_str); cleared_torrents++; } } - syslog(trace) << "Reaped " << reaped_l << " leechers, " << reaped_s << " seeders and " << reaped_fl << " tokens. Reset " << cleared_torrents << " torrents"; + + if (reaped_l || reaped_v4l || reaped_v6l || reaped_s || reaped_v4s || reaped_v6s) { + stats.leechers -= reaped_l; + stats.seeders -= reaped_s; + stats.ipv4_peers -= (reaped_v4l + reaped_v4s); + stats.ipv6_peers -= (reaped_v6l + reaped_v6s); + } + + syslog(debug) << "Reaped " << reaped_l << " leechers, " << reaped_s << " seeders and " << reaped_fl << " tokens. Reset " << cleared_torrents << " torrents"; } void worker::reap_del_reasons() { - syslog(trace) << "Starting del reason reaper"; + syslog(debug) << "Starting del reason reaper"; time_t max_time = time(NULL) - del_reason_lifetime; - auto it = del_reasons.begin(); unsigned int reaped = 0; - for (; it != del_reasons.end(); ) { - if (it->second.time <= max_time) { - auto del_it = it++; + for (auto reason = del_reasons.begin(); reason != del_reasons.end();) { + if (reason->second.time <= max_time) { + auto del_it = reason++; std::lock_guard dr_lock(del_reasons_lock); del_reasons.erase(del_it); reaped++; continue; } - ++it; + reason++; } - syslog(trace) << "Reaped " << reaped << " del reasons"; + syslog(debug) << "Reaped " << reaped << " del reasons"; } std::string worker::get_del_reason(int code) @@ -1623,13 +1641,13 @@ std::string worker::bencode_str(std::string data) { return bencoded_str; } -#if(__DEBUG_BUILD__) +#if defined(__DEBUG_BUILD__) /* * Allow any addresses in a debug build, it's expected * that we will generate local traffic for testing. */ bool worker::ipv4_is_public(in_addr addr){return true;} -bool worker::ipv6_is_public(in_addr addr){return true;} +bool worker::ipv6_is_public(in6_addr addr){return true;} #else bool worker::ipv4_is_public(in_addr addr){ diff --git a/src/worker.h b/src/worker.h index 8ed08fb..afe3aa3 100644 --- a/src/worker.h +++ b/src/worker.h @@ -8,15 +8,16 @@ #include #include #include -#include "db.h" -#include "site_comm.h" + #include "radiance.h" +class database; +class site_comm; enum tracker_status { OPEN, PAUSED, CLOSING }; // tracker status class worker { private: - mysql * db; + database * db; site_comm * s_comm; torrent_list &torrents_list; user_list &users_list; @@ -50,7 +51,7 @@ class worker { std::string bencode_str(std::string data); public: - worker(torrent_list &torrents, user_list &users, domain_list &domains, std::vector &_blacklist, mysql * db_obj, site_comm * sc); + worker(torrent_list &torrents, user_list &users, domain_list &domains, std::vector &_blacklist, database * db_obj, site_comm * sc); void reload_config(); std::string work(const std::string &input, std::string &ip, uint16_t &ip_ver, client_opts_t &client_opts); std::string announce(const std::string &input, torrent &tor, user_ptr &u, domain_ptr &d, params_type ¶ms, params_type &headers, std::string &ip, uint16_t &ip_ver, client_opts_t &client_opts);