31 Commits
Author SHA1 Message Date
Spine d4aaff7bb5 refactor tracker report functionality 2024-03-10 21:13:13 +01:00
Spine 37685bd8da add resource usage to grafana and report endpoints 2024-03-10 21:12:45 +01:00
Spine ce2192c018 detabbed source code, no code changes 2024-02-15 16:05:57 +01:00
Spine 2a8a7eb24b Merge branch 'announce-jitter' into 'master'
redesign announce jitter to better spread the load after startup

See merge request tracker/ocelot!8
2024-02-11 15:04:57 +00:00
Spine 4a5687b607 redesign announce jitter to better spread the load after startup 2024-02-11 15:39:22 +01:00
Spine f80f37c025 Merge branch 'torrent-info' into 'master'
output user report and info_torrent as JSON

See merge request tracker/ocelot!7
2024-02-10 15:26:59 +00:00
Spine 51c5f64a8e output user report and info_torrent as JSON 2024-01-28 12:38:25 +01:00
Spider 59a91200fa Update docker base image 2023-10-14 20:57:34 +02:00
sheepish 665e8b7a24 track queue sizes in stats 2023-10-14 20:25:15 +02:00
sheepish 7efb98654a sleep if api returns error 2023-10-14 20:25:15 +02:00
sheepish c4153d7585 fix queue worker threads getting stuck if connection fails 2023-10-14 20:25:15 +02:00
sheepish f42c7cdf47 add grafana dashboard 2023-10-14 20:19:50 +02:00
sheepish e5d20d7851 add prometheus-compatible stats reporting 2023-10-14 20:19:46 +02:00
itismadness cd1b031d4f Add curl to Dockerfile for downstream health checks
(cherry picked from commit fac0fd1686)
2023-10-14 20:19:32 +02:00
itismadness d2bae2622a Ignore build output files for docker
(cherry picked from commit 23e5b92b2a)
2023-10-14 20:19:29 +02:00
itismadness ad9fb66efa add image.source label to Dockerfile
(cherry picked from commit fc56c7a35a)
2023-10-14 20:19:25 +02:00
itismadness b248a4c766 improve dev workflow
(cherry picked from commit 50a08a2b66)
2023-10-14 20:19:14 +02:00
undertheironbridge e04b30366e Small CMakeLists.txt cleanup (#19)
Co-authored-by: strangeways <[email protected]>
(cherry picked from commit 5412bee85a)
2023-10-14 20:18:46 +02:00
itismadness 38ac1af7a2 use chrono to sleep in threads
(cherry picked from commit 3a430a9a1c)
2023-10-14 20:16:58 +02:00
Spine 9c2051ef71 change xbt_snatched insert to allow a primary key to be added 2020-04-22 01:24:02 +01:00
itismadness febde1daf7 use string empty method for checking empty strings 2020-04-22 01:23:52 +01:00
itismadness 465c23ad5d should have been 2.0.0 release 2019-10-22 23:43:11 +01:00
itismadness 023b33c5a5 1.2.0 release 2019-10-22 23:34:58 +01:00
Spine 8964322da5 write activity into leech stats tables (#2) 2019-10-20 10:12:42 +00:00
itismadness 4268d19188 Commit CMakeLists.txt and renamed CMake find files 2019-06-16 23:09:37 -01:00
itismadness 99f58dc0d9 Add site_service config option to allow setting gazelle port 2019-06-14 07:19:43 +08:00
Hierra Strunger 6d8f859455 Create ocelot.service (#14)
Systemd init file for ocelot to put on /lib/systemd/system/
2019-06-03 07:25:07 -04:00
itismadness 861ccf7eae Add changelog line for 1.2, update README 2019-05-26 17:11:21 -04:00
itismadness 3b2d8253fb Remove Vagrantfile in favor of Dockerfile 2019-05-26 17:02:53 -04:00
itismadness a7d8e5744f Migrate ocelot to build using cmake, add support for jemalloc 2019-05-26 17:00:53 -04:00
SebbaGerra d1a88b1ae1 Some changes to build on FreeBSD (#12)
* Update events.h

* Update ocelot.h

* Update schedule.h

* Update README.md
2018-11-24 08:44:28 -05:00
109 changed files with 5439 additions and 8124 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
.vscode/
build/
/ocelot
+9 -2
View File
@@ -1,4 +1,5 @@
.idea/
.vscode/
.vagrant/
*.tar.*
MakeFile.in
@@ -10,5 +11,11 @@ autom4te.cache/
Makefile
.deps/
src/ocelot
CMakeLists.txt
/ocelot.conf
/ocelot.conf
build/
/ocelot
CMakeFiles/
CMakeCache.txt
cmake_install.cmake
*.cbp
.DS_Store
+51 -1
View File
@@ -1,8 +1,58 @@
-- 2.1.3 (2024-03-09)
BREAKING
* API user endpoint output changed to JSON
FEATURES
* Peak number of simultaneous open connections is now tracked.
* Maximum size of client http request is now tracked.
* Number of errors (bad tracker secrets, bad client requests) is now tracked.
* Show jemalloc stats in Gazelle and Grafana report endpoints.
BUILD
* refactor report functions to produce only report payload
-- 2.1.2 (2024-02-17)
FEATURES
* show resource usage in Gazelle and Grafana report endpoints
-- 2.1.1 (2024-02-15)
BUILD
* Detabbed source code in first step towards having the code lint cleanly, no code changes
-- 2.1.0 (2024-02-11)
FEATURES
* announce jitter is now a uniform distribution and can be modified on the fly
-- 2.0.1 (2024-02-10)
BREAKING
* API torrent endpoint output changed to JSON
* API user endpoint shows more information about a user in JSON format
FEATURES
* Mysql port may be specified in configuration file
* API stats report contains Ocelot version
* Queue sizes are reported in stats
* Sleep if Gazelle API is down
* Handle DB connection problems gracefully
* Add Prometheus and Grafana support
BUILD
* Docker image based on Bookworm
-- 2.0.0 (2019-10-22)
BREAKING
* Write leech stats into their own dedicated tables (users_leech_stats, torrents_leech_stats)
* Move to CMake for building project instead of autotools
FEATURES
* Add support for building against jemalloc (http://jemalloc.net/)
* Add systemd service file for ocelot (thanks @HierraStrunger)
Add site_service config option to set the service/port ocelot runs on (defaults to "http")
BUGFIXES
* Fix FreeBSD support (thanks @HierraStrunger)
BUILD
* Drop Vagranfile in favor of only supporting the Dockerfile
-- 1.1 (2018-10-29)
Move to spdlog (https://github.com/gabime/spdlog)to handle logging instead of cout
spdlog is vendored under src/, currently using v0.13.0
Add logging directive to config to configure how Ocelot logs and where it logs
Add deamon (--daemon, -d) to run Ocelot as a daemon
Add daemon switch (--daemon, -d) to run Ocelot as a daemon
Move source code into src/ directory
Add Vagrantfile and Dockerfile for running Ocelot
+48
View File
@@ -0,0 +1,48 @@
# From: https://raw.githubusercontent.com/STEllAR-GROUP/hpx/master/cmake/FindJemalloc.cmake
# Copyright (c) 2014 Thomas Heller
# Copyright (c) 2007-2012 Hartmut Kaiser
# Copyright (c) 2010-2011 Matt Anderson
# Copyright (c) 2011 Bryce Lelbach
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
find_package(PkgConfig)
pkg_check_modules(PC_JEMALLOC QUIET libjemalloc)
find_path(JEMALLOC_INCLUDE_DIR jemalloc/jemalloc.h
HINTS
${JEMALLOC_ROOT} ENV JEMALLOC_ROOT
${PC_JEMALLOC_MINIMAL_INCLUDEDIR}
${PC_JEMALLOC_MINIMAL_INCLUDE_DIRS}
${PC_JEMALLOC_INCLUDEDIR}
${PC_JEMALLOC_INCLUDE_DIRS}
PATH_SUFFIXES include)
find_library(JEMALLOC_LIBRARY NAMES jemalloc libjemalloc
HINTS
${JEMALLOC_ROOT} ENV JEMALLOC_ROOT
${PC_JEMALLOC_MINIMAL_LIBDIR}
${PC_JEMALLOC_MINIMAL_LIBRARY_DIRS}
${PC_JEMALLOC_LIBDIR}
${PC_JEMALLOC_LIBRARY_DIRS}
PATH_SUFFIXES lib lib64)
if(JEMALLOC_LIBRARY AND JEMALLOC_INCLUDE_DIR)
set(JEMALLOC_FOUND TRUE)
message(STATUS "Found jemalloc: ${JEMALLOC_LIBRARY}")
find_package_handle_standard_args(Jemalloc DEFAULT_MSG
JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR)
get_property(_type CACHE JEMALLOC_ROOT PROPERTY TYPE)
if(_type)
set_property(CACHE JEMALLOC_ROOT PROPERTY ADVANCED 1)
if("x${_type}" STREQUAL "xUNINITIALIZED")
set_property(CACHE JEMALLOC_ROOT PROPERTY TYPE PATH)
endif()
endif()
else()
set(JEMALLOC_FOUND FALSE)
endif()
mark_as_advanced(JEMALLOC_ROOT JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR)
+38
View File
@@ -0,0 +1,38 @@
# - Try to find libev
# Once done this will define
# LIBEV_FOUND - System has libev
# LIBEV_INCLUDE_DIRS - The libev include directories
# LIBEV_LIBRARIES - The libraries needed to use libev
find_path(LIBEV_INCLUDE_DIR
NAMES ev.h
)
find_library(LIBEV_LIBRARY
NAMES ev
)
if(LIBEV_INCLUDE_DIR)
file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
LIBEV_VERSION_MAJOR REGEX "^#define[ \t]+EV_VERSION_MAJOR[ \t]+[0-9]+")
file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
LIBEV_VERSION_MINOR REGEX "^#define[ \t]+EV_VERSION_MINOR[ \t]+[0-9]+")
string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MAJOR "${LIBEV_VERSION_MAJOR}")
string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MINOR "${LIBEV_VERSION_MINOR}")
set(LIBEV_VERSION "${LIBEV_VERSION_MAJOR}.${LIBEV_VERSION_MINOR}")
unset(LIBEV_VERSION_MINOR)
unset(LIBEV_VERSION_MAJOR)
endif()
include(FindPackageHandleStandardArgs)
# handle the QUIETLY and REQUIRED arguments and set LIBEV_FOUND to TRUE
# if all listed variables are TRUE and the requested version matches.
find_package_handle_standard_args(Libev REQUIRED_VARS
LIBEV_LIBRARY LIBEV_INCLUDE_DIR
VERSION_VAR LIBEV_VERSION)
if(LIBEV_FOUND)
set(LIBEV_LIBRARIES ${LIBEV_LIBRARY})
set(LIBEV_INCLUDE_DIRS ${LIBEV_INCLUDE_DIR})
endif()
mark_as_advanced(LIBEV_INCLUDE_DIR LIBEV_LIBRARY)
+113
View File
@@ -0,0 +1,113 @@
#--------------------------------------------------------
# Copyright (C) 1995-2007 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# There are special exceptions to the terms and conditions of the GPL
# as it is applied to this software. View the full text of the exception
# in file LICENSE.exceptions in the top-level directory of this software
# distribution.
#
# 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, write to the Free Software
# Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
# The MySQL Connector/ODBC is licensed under the terms of the
# GPL, like most MySQL Connectors. There are special exceptions
# to the terms and conditions of the GPL as it is applied to
# this software, see the FLOSS License Exception available on
# mysql.com.
##########################################################################
#-------------- FIND MYSQL_INCLUDE_DIR ------------------
FIND_PATH(MYSQL_INCLUDE_DIR mysql.h
/usr/include/mysql
/usr/local/include/mysql
/opt/mysql/mysql/include
/opt/mysql/mysql/include/mysql
/opt/mysql/include
/opt/local/include/mysql5
/usr/local/mysql/include
/usr/local/mysql/include/mysql
$ENV{ProgramFiles}/MySQL/*/include
$ENV{SystemDrive}/MySQL/*/include)
#----------------- FIND MYSQL_LIB_DIR -------------------
IF (WIN32)
# Set lib path suffixes
# dist = for mysql binary distributions
# build = for custom built tree
IF (CMAKE_BUILD_TYPE STREQUAL Debug)
SET(libsuffixDist debug)
SET(libsuffixBuild Debug)
ELSE (CMAKE_BUILD_TYPE STREQUAL Debug)
SET(libsuffixDist opt)
SET(libsuffixBuild Release)
ADD_DEFINITIONS(-DDBUG_OFF)
ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug)
FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient
PATHS
$ENV{MYSQL_DIR}/lib/${libsuffixDist}
$ENV{MYSQL_DIR}/libmysql
$ENV{MYSQL_DIR}/libmysql/${libsuffixBuild}
$ENV{MYSQL_DIR}/client/${libsuffixBuild}
$ENV{MYSQL_DIR}/libmysql/${libsuffixBuild}
$ENV{ProgramFiles}/MySQL/*/lib/${libsuffixDist}
$ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist})
ELSE (WIN32)
FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient_r mysqlclient
PATHS
/usr/lib/mysql
/usr/local/lib/mysql
/usr/local/mysql/lib
/usr/local/mysql/lib/mysql
/opt/local/mysql5/lib
/opt/local/lib/mysql5/mysql
/opt/mysql/mysql/lib/mysql
/opt/mysql/lib/mysql)
ENDIF (WIN32)
IF(MYSQL_LIB)
GET_FILENAME_COMPONENT(MYSQL_LIB_DIR ${MYSQL_LIB} PATH)
ENDIF(MYSQL_LIB)
IF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR)
SET(MYSQL_FOUND TRUE)
INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR})
LINK_DIRECTORIES(${MYSQL_LIB_DIR})
FIND_LIBRARY(MYSQL_ZLIB zlib PATHS ${MYSQL_LIB_DIR})
FIND_LIBRARY(MYSQL_TAOCRYPT taocrypt PATHS ${MYSQL_LIB_DIR})
IF (MYSQL_LIB)
SET(MYSQL_CLIENT_LIBS ${MYSQL_LIB})
ELSE()
SET(MYSQL_CLIENT_LIBS mysqlclient_r)
ENDIF()
IF (MYSQL_ZLIB)
SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} zlib)
ENDIF (MYSQL_ZLIB)
IF (MYSQL_TAOCRYPT)
SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} taocrypt)
ENDIF (MYSQL_TAOCRYPT)
# Added needed mysqlclient dependencies on Windows
IF (WIN32)
SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} ws2_32)
ENDIF (WIN32)
MESSAGE(STATUS "MySQL Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}")
MESSAGE(STATUS "MySQL client libraries: ${MYSQL_CLIENT_LIBS}")
ELSEIF (MySQL_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Cannot find MySQL. Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}")
ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR)
+33
View File
@@ -0,0 +1,33 @@
# - Find MySQL++
# Find the MySQL++ includes and client library
# This module defines
# MYSQLPP_INCLUDE_DIR, where to find mysql.h
# MYSQLPP_LIBRARY, the libraries needed to use MySQL.
# MYSQLPP_FOUND, If false, do not try to use MySQL.
FIND_PATH(MYSQLPP_INCLUDE_DIR mysql++.h
/usr/include/mysql++
/usr/local/include/mysql++
/opt/mysql++/include/mysql++
/opt/mysqlpp/include/mysql++
/opt/mysqlpp/include/
)
FIND_LIBRARY(MYSQLPP_LIBRARY mysqlpp
PATHS
/usr/lib
/usr/local/lib
/opt/mysql++
/opt/mysqlpp
/opt/mysqlpp/lib
)
if(MYSQLPP_INCLUDE_DIR AND MYSQLPP_LIBRARY)
set(MYSQLPP_FOUND TRUE)
message(STATUS "Found MySQL++: ${MYSQLPP_INCLUDE_DIR}, ${MYSQLPP_LIBRARY}")
else()
set(MYSQLPP_FOUND FALSE)
message(STATUS "MySQL++ was not found.")
endif()
mark_as_advanced(MYSQLPP_INCLUDE_DIR MYSQLPP_LIBRARY)
+42
View File
@@ -0,0 +1,42 @@
# - Find Tcmalloc
# Find the native Tcmalloc includes and library
#
# TCMALLOC_INCLUDE_DIR - where to find Tcmalloc.h, etc.
# TCMALLOC_LIBRARIES - List of libraries when using Tcmalloc.
# TCMALLOC_FOUND - True if Tcmalloc found.
find_path(TCMALLOC_INCLUDE_DIR google/tcmalloc.h
NO_DEFAULT_PATH
PATHS
/usr/include
/usr/local/include
/opt/local/include
)
set(TCMALLOC_NAMES tcmalloc_minimal tcmalloc)
find_library(TCMALLOC_LIBRARY NO_DEFAULT_PATH
NAMES ${TCMALLOC_NAMES}
PATHS
/lib
/usr/lib
/usr/local/lib
/opt/local/lib
)
if(TCMALLOC_INCLUDE_DIR AND TCMALLOC_LIBRARY)
set(TCMALLOC_FOUND TRUE)
else()
set(TCMALLOC_FOUND FALSE)
endif()
if(TCMALLOC_FOUND)
message(STATUS "Found Tcmalloc: ${TCMALLOC_LIBRARY}")
else()
message(STATUS "Could not find tcmalloc")
endif()
mark_as_advanced(
TCMALLOC_LIBRARY
TCMALLOC_INCLUDE_DIR
)
+78
View File
@@ -0,0 +1,78 @@
cmake_minimum_required(VERSION 3.1)
project(ocelot
VERSION 2.0.0
)
# Make a subdirectory, and run cmake there (mkdir build; cd build; cmake ..)
if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR)
message(FATAL_ERROR "Source and build directories cannot be the same.")
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wfatal-errors")
message(STATUS "CMAKE_MODULE_PATH='${CMAKE_MODULE_PATH}'")
find_package(Jemalloc)
find_package(Tcmalloc)
if(JEMALLOC_FOUND)
option(USE_JEMALLOC "Use jemalloc instead of system-provided malloc" ON)
if(TCMALLOC_FOUND)
option(USE_TCMALLOC "Use tcmalloc (Google's thread-cacheing malloc) instead of system-provided malloc" OFF)
else()
set(USE_TCMALLOC OFF)
endif()
else()
set(USE_JEMALLOC OFF)
if(TCMALLOC_FOUND)
option(USE_TCMALLOC "Use tcmalloc (Google's thread-cacheing malloc) instead of system-provided malloc" ON)
else()
set(USE_TCMALLOC OFF)
endif()
endif()
#AM_LDFLAGS = -Wl,-O1 -Wl,--as-needed
find_package(Boost COMPONENTS system iostreams REQUIRED)
message(STATUS "Boost_INCLUDE_DIRS='${Boost_INCLUDE_DIRS}'")
message(STATUS "Boost_LIBRARIES='${Boost_LIBRARIES}'")
include_directories(${Boost_INCLUDE_DIRS})
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
find_package(MYSQL REQUIRED)
find_package(MYSQLPP REQUIRED)
find_package(LibEv REQUIRED)
include_directories(${LIBEV_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/libs)
file(GLOB HEADERS src/*.h)
file(GLOB SOURCES src/*.cpp)
add_executable(ocelot ${HEADERS} ${SOURCES})
SET(LINK_LIBRARIES
${Boost_SYSTEM_LIBRARY}
${Boost_IOSTREAMS_LIBRARY}
${LIBEV_LIBRARY}
${MYSQLPP_LIBRARY}
Threads::Threads
)
if (USE_JEMALLOC)
message(STATUS "Build with jemalloc")
list(APPEND LINK_LIBRARIES ${JEMALLOC_LIBRARY})
elseif (USE_TCMALLOC)
message(STATUS "Build with tcmalloc")
list(APPEND LINK_LIBRARIES ${TCMALLOC_LIBRARY})
endif()
target_link_libraries(
ocelot
${LINK_LIBRARIES}
)
+37
View File
@@ -0,0 +1,37 @@
FROM debian:bookworm-slim
LABEL org.opencontainers.image.source=https://github.com/OPSnet/Ocelot
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
build-essential \
cmake \
default-libmysqlclient-dev \
libboost-iostreams-dev \
libboost-system-dev \
libev-dev \
libjemalloc-dev \
libmysql++-dev \
netcat-traditional \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
COPY . /srv
WORKDIR /srv
RUN cmake -Wno-dev -S /srv -B /srv/build \
&& make -C build \
&& apt-get purge -y \
build-essential \
cmake \
pkg-config \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& mkdir -p /tmp/ocelot \
&& mv /srv/build/ocelot /srv/ocelot \
&& mv /srv/ocelot.conf.dist /srv/ocelot.conf
# default listen_port value in ocelot.conf
EXPOSE 34000
CMD ["/srv/ocelot"]
-7
View File
@@ -1,7 +0,0 @@
ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = CHANGES LICENSE README.md ocelot.conf.dist
SUBDIRS = src
dist-hook:
touch ${distdir}/configure
patch -p2 -d ${distdir} --no-backup-if-mismatch < ../dist.patch
+38 -11
View File
@@ -1,31 +1,56 @@
# Ocelot
Ocelot is a BitTorrent tracker written in C++ for the [Gazelle](http://whatcd.github.io/Gazelle/) project. It supports requests over TCP and can only track IPv4 peers.
Ocelot is a BitTorrent tracker written in C++ for the [Gazelle](http://github.com/OPSnet/Gazelle) project.
It supports requests over TCP and can only track IPv4 peers.
## Ocelot Compile-time Dependencies
* [GCC/G++](http://gcc.gnu.org/) (4.7+ required; 4.8.1+ recommended)
* [Boost](http://www.boost.org/) (1.55.0+ required)
* [GCC/G++](http://gcc.gnu.org/) (11+ required; 11.4.0+ recommended)
* [Boost](http://www.boost.org/) (1.74.0+ required)
* [libev](http://software.schmorp.de/pkg/libev.html) (required)
* [spdlog](https://github.com/gabime/spdlog) (required)
* [MySQL++](http://tangentsoft.net/mysql++/) (3.2.0+ required)
* [TCMalloc](http://goog-perftools.sourceforge.net/doc/tcmalloc.html) (optional, but strongly recommended)
* [jemalloc](http://jemalloc.net/) (optional, but strongly recommended)
* [TCMalloc](http://goog-perftools.sourceforge.net/doc/tcmalloc.html) (optional)
## Installation
### Debian Stretch
### Debian Bookworm
```bash
sudo apt-get install pkg-config libev-dev libboost-all-dev
./configure --with-boost-libdir=/usr/lib/x86_64-linux-gnu
sudo apt-get install \
build-essential \
cmake \
default-libmysqlclient-dev \
libboost-iostreams-dev \
libboost-system-dev \
libev-dev \
libjemalloc-dev \
libmysql++-dev \
netcat-traditional \
pkg-config
cmake -Wno-dev . -B build
make -C build
```
The [Gazelle installation guides](https://github.com/WhatCD/Gazelle/wiki/Gazelle-installation) include instructions for installing Ocelot as a part of the Gazelle project.
### Docker
```bash
docker build . -t ocelot
docker run -v $(pwd)/ocelot.conf:/srv/ocelot.conf ocelot
```
### Standalone Installation
* Prepare the build environment. (This must be re-executed when new source files are added).
cmake -Wno-dev . -B build
* Create the following tables according to the [Gazelle database schema](https://raw.githubusercontent.com/WhatCD/Gazelle/master/gazelle.sql):
- `torrents`
- `torrents_leech_stats`
- `users_freeleeches`
- `users_leech_stats`
- `users_main`
- `xbt_client_whitelist`
- `xbt_files_users`
@@ -35,9 +60,7 @@ The [Gazelle installation guides](https://github.com/WhatCD/Gazelle/wiki/Gazelle
* Build Ocelot:
./configure
make
make install
make -C build
## Running Ocelot
@@ -46,6 +69,10 @@ The [Gazelle installation guides](https://github.com/WhatCD/Gazelle/wiki/Gazelle
* `-c <path/to/ocelot.conf>` - Path to config file. If unspecified, the current working directory is used.
* `-v` - Print queue status every time a flush is initiated.
You can run a test ocelot daemon alongside a production daemon by specifying
a separate configuration file, and setting `readonly = true`. This will
prevent the database peer tables from being reset.
### Signals
* `SIGHUP` - Reload config
Vendored
-26
View File
@@ -1,26 +0,0 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
$script = <<SCRIPT
apt-get update
apt-get -y install \
autoconf \
build-essential \
default-libmysqlclient-dev \
libboost-iostreams-dev \
libboost-system-dev \
libev-dev \
libmysql++-dev \
pkg-config \
mariadb-client \
mariadb-server
SCRIPT
Vagrant.configure("2") do |config|
config.vm.box = "debian/contrib-stretch64"
config.vm.synced_folder ".", "/vagrant"
config.vm.provision "shell", inline: $script
config.vbguest.installer_arguments = ['--nox11 -- --force']
end
Vendored
-1158
View File
File diff suppressed because it is too large. Load diff
-347
View File
@@ -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 <[email protected]>.
#
# 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 <http://www.gnu.org/licenses/>.
# 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 <[email protected]> or send patches to
# <[email protected]>.
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 <[email protected]>.
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:
-26
View File
@@ -1,26 +0,0 @@
# Ocelot Configure script
# Generate ./configure using autoreconf (or autoconf for the brave)
AC_INIT(ocelot, 1.1)
AC_CONFIG_SRCDIR([src/ocelot.h])
AC_CONFIG_MACRO_DIRS([m4])
AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
AC_CHECK_FUNCS([ftruncate memset socket strerror])
AM_INIT_AUTOMAKE([1.11 no-define foreign])
AC_PROG_CXX
AC_CONFIG_FILES([Makefile src/Makefile])
AC_LANG([C++])
AX_CXX_COMPILE_STDCXX(11, noext, mandatory)
AX_BOOST_BASE([1.37], [], [AC_MSG_ERROR(Need boost >= 1.37)])
AX_BOOST_IOSTREAMS
AX_BOOST_SYSTEM
AX_PTHREAD([], AC_MSG_FAILURE([pthread library is required]))
EV_DEVEL
MYSQL_C_API_LOCATION
MYSQLPP_DEVEL
TCMALLOC
AC_OUTPUT
File diff suppressed because it is too large. Load diff
-791
View File
@@ -1,791 +0,0 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2013-05-30.07; # UTC
# Copyright (C) 1999-2013 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 <http://www.gnu.org/licenses/>.
# 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 <[email protected]>.
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 <[email protected]>.
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:
+176
View File
@@ -0,0 +1,176 @@
SET FOREIGN_KEY_CHECKS = 0;
CREATE DATABASE gazelle CHARACTER SET utf8 COLLATE utf8_swedish_ci;
USE gazelle;
CREATE TABLE `torrents` (
`ID` int(10) NOT NULL AUTO_INCREMENT,
`GroupID` int(10) NOT NULL,
`UserID` int(10) DEFAULT NULL,
`Media` varchar(20) DEFAULT NULL,
`Format` varchar(10) DEFAULT NULL,
`Encoding` varchar(15) DEFAULT NULL,
`Remastered` enum('0','1') NOT NULL DEFAULT '0',
`RemasterYear` int(4) DEFAULT NULL,
`RemasterTitle` varchar(80) NOT NULL DEFAULT '',
`RemasterCatalogueNumber` varchar(80) NOT NULL DEFAULT '',
`RemasterRecordLabel` varchar(80) NOT NULL DEFAULT '',
`Scene` enum('0','1') NOT NULL DEFAULT '0',
`HasLog` enum('0','1') NOT NULL DEFAULT '0',
`HasCue` enum('0','1') NOT NULL DEFAULT '0',
`HasLogDB` enum('0','1') NOT NULL DEFAULT '0',
`LogScore` int(6) NOT NULL DEFAULT '0',
`LogChecksum` enum('0','1') NOT NULL DEFAULT '1',
`info_hash` blob NOT NULL,
`FileCount` int(6) NOT NULL,
`FileList` mediumtext NOT NULL,
`FilePath` varchar(255) NOT NULL DEFAULT '',
`Size` bigint(12) NOT NULL,
`Leechers` int(6) NOT NULL DEFAULT '0',
`Seeders` int(6) NOT NULL DEFAULT '0',
`last_action` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`FreeTorrent` enum('0','1','2') NOT NULL DEFAULT '0',
`FreeLeechType` enum('0','1','2','3','4','5','6','7') NOT NULL DEFAULT '0',
`Time` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`Description` text,
`Snatched` int(10) unsigned NOT NULL DEFAULT '0',
`balance` bigint(20) NOT NULL DEFAULT '0',
`LastReseedRequest` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`TranscodedFrom` int(10) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
UNIQUE KEY `InfoHash` (`info_hash`(40)),
KEY `GroupID` (`GroupID`),
KEY `UserID` (`UserID`),
KEY `Media` (`Media`),
KEY `Format` (`Format`),
KEY `Encoding` (`Encoding`),
KEY `Year` (`RemasterYear`),
KEY `FileCount` (`FileCount`),
KEY `Size` (`Size`),
KEY `Seeders` (`Seeders`),
KEY `Leechers` (`Leechers`),
KEY `Snatched` (`Snatched`),
KEY `last_action` (`last_action`),
KEY `Time` (`Time`),
KEY `FreeTorrent` (`FreeTorrent`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `users_freeleeches` (
`UserID` int(10) NOT NULL,
`TorrentID` int(10) NOT NULL,
`Time` datetime NOT NULL,
`Expired` tinyint(1) NOT NULL DEFAULT '0',
`Downloaded` bigint(20) NOT NULL DEFAULT '0',
`Uses` int(10) NOT NULL DEFAULT '1',
PRIMARY KEY (`UserID`,`TorrentID`),
KEY `Time` (`Time`),
KEY `Expired_Time` (`Expired`,`Time`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `users_geodistribution` (
`Code` varchar(2) NOT NULL,
`Users` int(10) NOT NULL
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `users_history_emails` (
`UserID` int(10) NOT NULL,
`Email` varchar(255) DEFAULT NULL,
`Time` datetime DEFAULT NULL,
`IP` varchar(15) DEFAULT NULL,
KEY `UserID` (`UserID`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `users_main` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Username` varchar(20) NOT NULL,
`Email` varchar(255) NOT NULL,
`PassHash` varchar(60) NOT NULL,
`Secret` char(32) NOT NULL,
`IRCKey` char(32) DEFAULT NULL,
`LastLogin` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`LastAccess` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`IP` varchar(15) NOT NULL DEFAULT '0.0.0.0',
`Class` tinyint(2) NOT NULL DEFAULT '5',
`Uploaded` bigint(20) unsigned NOT NULL DEFAULT '0',
`Downloaded` bigint(20) unsigned NOT NULL DEFAULT '0',
`BonusPoints` float(20, 5) NOT NULL DEFAULT '0',
`Title` text NOT NULL,
`Enabled` enum('0','1','2') NOT NULL DEFAULT '0',
`Paranoia` text,
`Visible` enum('1','0') NOT NULL DEFAULT '1',
`Invites` int(10) unsigned NOT NULL DEFAULT '0',
`PermissionID` int(10) unsigned NOT NULL,
`CustomPermissions` text,
`can_leech` tinyint(4) NOT NULL DEFAULT '1',
`torrent_pass` char(32) NOT NULL,
`RequiredRatio` double(10,8) NOT NULL DEFAULT '0.00000000',
`RequiredRatioWork` double(10,8) NOT NULL DEFAULT '0.00000000',
`ipcc` varchar(2) NOT NULL DEFAULT '',
`FLTokens` int(10) NOT NULL DEFAULT '0',
`FLT_Given` int(10) NOT NULL DEFAULT '0',
`Invites_Given` int(10) NOT NULL DEFAULT '0',
`2FA_Key` VARCHAR(16),
`Recovery` text,
PRIMARY KEY (`ID`),
UNIQUE KEY `Username` (`Username`),
KEY `Email` (`Email`),
KEY `PassHash` (`PassHash`),
KEY `LastAccess` (`LastAccess`),
KEY `IP` (`IP`),
KEY `Class` (`Class`),
KEY `Uploaded` (`Uploaded`),
KEY `Downloaded` (`Downloaded`),
KEY `Enabled` (`Enabled`),
KEY `Invites` (`Invites`),
KEY `torrent_pass` (`torrent_pass`),
KEY `RequiredRatio` (`RequiredRatio`),
KEY `cc_index` (`ipcc`),
KEY `PermissionID` (`PermissionID`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `xbt_client_whitelist` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`peer_id` varchar(20) DEFAULT NULL,
`vstring` varchar(200) DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `peer_id` (`peer_id`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `xbt_files_users` (
`uid` int(11) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`announced` int(11) NOT NULL DEFAULT '0',
`completed` tinyint(1) NOT NULL DEFAULT '0',
`downloaded` bigint(20) NOT NULL DEFAULT '0',
`remaining` bigint(20) NOT NULL DEFAULT '0',
`uploaded` bigint(20) NOT NULL DEFAULT '0',
`upspeed` int(10) unsigned NOT NULL DEFAULT '0',
`downspeed` int(10) unsigned NOT NULL DEFAULT '0',
`corrupt` bigint(20) NOT NULL DEFAULT '0',
`timespent` int(10) unsigned NOT NULL DEFAULT '0',
`useragent` varchar(51) NOT NULL DEFAULT '',
`connectable` tinyint(4) NOT NULL DEFAULT '1',
`peer_id` binary(20) NOT NULL DEFAULT '\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
`fid` int(11) NOT NULL,
`mtime` int(11) NOT NULL DEFAULT '0',
`ip` varchar(15) NOT NULL DEFAULT '',
PRIMARY KEY (`peer_id`,`fid`,`uid`),
KEY `remaining_idx` (`remaining`),
KEY `fid_idx` (`fid`),
KEY `mtime_idx` (`mtime`),
KEY `uid_active` (`uid`,`active`)
) ENGINE=InnoDB CHARSET utf8;
CREATE TABLE `xbt_snatched` (
`uid` int(11) NOT NULL DEFAULT '0',
`tstamp` int(11) NOT NULL,
`fid` int(11) NOT NULL,
`IP` varchar(15) NOT NULL,
`seedtime` int(11) NOT NULL DEFAULT '0',
KEY `fid` (`fid`),
KEY `tstamp` (`tstamp`),
KEY `uid_tstamp` (`uid`,`tstamp`)
) ENGINE=InnoDB CHARSET utf8;
SET FOREIGN_KEY_CHECKS = 1;
-527
View File
@@ -1,527 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2011-11-20.07; # 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.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# 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_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
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
no_target_directory=
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
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
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
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 -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
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.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/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.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 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
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob 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` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob 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:
File renamed without changes.
@@ -70,4 +70,4 @@ private:
};
} // namespace spdlog
#include "details/async_logger_impl.h"
#include "spdlog/details/async_logger_impl.h"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,7 +4,7 @@
//
#pragma once
#include "../common.h"
#include "spdlog/common.h"
#include <algorithm>
#include <chrono>
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -17,8 +17,8 @@
#ifndef FMT_USE_WINDOWS_H
#define FMT_USE_WINDOWS_H 0
#endif
#include "bundled/core.h"
#include "bundled/format.h"
#include "spdlog/fmt/bundled/core.h"
#include "spdlog/fmt/bundled/format.h"
#else // external fmtlib
#include <fmt/core.h>
#include <fmt/format.h>
@@ -11,7 +11,7 @@
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include "bundled/ostream.h"
#include "spdlog/fmt/bundled/ostream.h"
#include "fmt.h"
#else
#include <fmt/ostream.h>
@@ -5,7 +5,7 @@
#pragma once
#include "fmt/fmt.h"
#include "spdlog/fmt/fmt.h"
#include "spdlog/details/log_msg.h"
namespace spdlog {
+1 -1
View File
@@ -164,4 +164,4 @@ protected:
};
} // namespace spdlog
#include "details/logger_impl.h"
#include "spdlog/details/logger_impl.h"
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-301
View File
@@ -1,301 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_boost_base.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# DESCRIPTION
#
# Test for the Boost C++ libraries of a particular version (or newer)
#
# If no path to the installed boost library is given the macro searchs
# under /usr, /usr/local, /opt and /opt/local and evaluates the
# $BOOST_ROOT environment variable. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
#
# And sets:
#
# HAVE_BOOST
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <[email protected]>
# Copyright (c) 2009 Peter Adolphs
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 42
# example boost program (need to pass version)
m4_define([_AX_BOOST_BASE_PROGRAM],
[AC_LANG_PROGRAM([[
#include <boost/version.hpp>
]],[[
(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))]));
]])])
AC_DEFUN([AX_BOOST_BASE],
[
AC_ARG_WITH([boost],
[AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
[use Boost library from a standard location (ARG=yes),
from the specified location (ARG=<path>),
or disable it (ARG=no)
@<:@ARG=yes@:>@ ])],
[
AS_CASE([$withval],
[no],[want_boost="no";_AX_BOOST_BASE_boost_path=""],
[yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""],
[want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"])
],
[want_boost="yes"])
AC_ARG_WITH([boost-libdir],
[AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
[Force given directory for boost libraries.
Note that this will override library path detection,
so use this parameter only if default library detection fails
and you know exactly where your boost libraries are located.])],
[
AS_IF([test -d "$withval"],
[_AX_BOOST_BASE_boost_lib_path="$withval"],
[AC_MSG_ERROR([--with-boost-libdir expected directory name])])
],
[_AX_BOOST_BASE_boost_lib_path=""])
BOOST_LDFLAGS=""
BOOST_CPPFLAGS=""
AS_IF([test "x$want_boost" = "xyes"],
[_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])])
AC_SUBST(BOOST_CPPFLAGS)
AC_SUBST(BOOST_LDFLAGS)
])
# convert a version string in $2 to numeric and affect to polymorphic var $1
AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[
AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"])
_AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'`
_AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'`
AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"],
[AC_MSG_ERROR([You should at least specify libboost major version])])
_AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'`
AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"],
[_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"])
_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"],
[_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"])
_AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor`
AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET)
])
dnl Run the detection of boost should be run only if $want_boost
AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
_AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1])
succeeded=no
AC_REQUIRE([AC_CANONICAL_HOST])
dnl On 64-bit systems check for system libraries in both lib64 and lib.
dnl The former is specified by FHS, but e.g. Debian does not adhere to
dnl this (as it rises problems for generic multi-arch support).
dnl The last entry in the list is chosen by default when no libraries
dnl are found, e.g. when only header-only libraries are installed!
AS_CASE([${host_cpu}],
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
[ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
[libsubdirs="lib"],
)
dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
dnl them priority over the other paths since, if libs are found there, they
dnl are almost assuredly the ones desired.
AS_CASE([${host_cpu}],
[i?86],[multiarch_libsubdir="lib/i386-${host_os}"],
[multiarch_libsubdir="lib/${host_cpu}-${host_os}"]
)
dnl first we check the system location for boost libraries
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[
AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"])
AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[
AC_MSG_RESULT([yes])
BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include"
for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do
AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"])
AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[
AC_MSG_RESULT([yes])
BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp";
break;
],
[AC_MSG_RESULT([no])])
done],[
AC_MSG_RESULT([no])])
],[
if test X"$cross_compiling" = Xyes; then
search_libsubdirs=$multiarch_libsubdir
else
search_libsubdirs="$multiarch_libsubdir $libsubdirs"
fi
for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then
for libsubdir in $search_libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir"
BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include"
break;
fi
done
])
dnl overwrite ld flags if we have required special directory with
dnl --with-boost-libdir parameter
AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"],
[BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"])
AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_REQUIRE([AC_PROG_CXX])
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
dnl if we found no boost with system layout we search for boost libraries
dnl built and installed without the --layout=system option or for a staged(not installed) version
if test "x$succeeded" != "xyes" ; then
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
BOOST_CPPFLAGS=
if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
BOOST_LDFLAGS=
fi
_version=0
if test -n "$_AX_BOOST_BASE_boost_path" ; then
if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then
for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "x$V_CHECK" = "x1" ; then
_version=$_version_tmp
fi
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE"
done
dnl if nothing found search for layout used in Windows distributions
if test -z "$BOOST_CPPFLAGS"; then
if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then
BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path"
fi
fi
dnl if we found something and BOOST_LDFLAGS was unset before
dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here.
if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then
for libsubdir in $libsubdirs ; do
if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir"
fi
fi
else
if test "x$cross_compiling" != "xyes" ; then
for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do
if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then
for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "x$V_CHECK" = "x1" ; then
_version=$_version_tmp
best_path=$_AX_BOOST_BASE_boost_path
fi
done
fi
done
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
for libsubdir in $libsubdirs ; do
if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
BOOST_LDFLAGS="-L$best_path/$libsubdir"
fi
fi
if test -n "$BOOST_ROOT" ; then
for libsubdir in $libsubdirs ; do
if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
V_CHECK=`expr $stage_version_shorten \>\= $_version`
if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
BOOST_CPPFLAGS="-I$BOOST_ROOT"
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
fi
fi
fi
fi
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
fi
if test "x$succeeded" != "xyes" ; then
if test "x$_version" = "x0" ; then
AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
else
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
fi
# execute ACTION-IF-NOT-FOUND (if present):
ifelse([$3], , :, [$3])
else
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
# execute ACTION-IF-FOUND (if present):
ifelse([$2], , :, [$2])
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
])
-116
View File
@@ -1,116 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_iostreams.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_IOSTREAMS
#
# DESCRIPTION
#
# Test for IOStreams library from the Boost C++ libraries. The macro
# requires a preceding call to AX_BOOST_BASE. Further documentation is
# available at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_IOSTREAMS_LIB)
#
# And sets:
#
# HAVE_BOOST_IOSTREAMS
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 20
AC_DEFUN([AX_BOOST_IOSTREAMS],
[
AC_ARG_WITH([boost-iostreams],
AS_HELP_STRING([--with-boost-iostreams@<:@=special-lib@:>@],
[use the IOStreams library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-iostreams=boost_iostreams-gcc-mt-d-1_33_1 ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_iostreams_lib=""
else
want_boost="yes"
ax_boost_user_iostreams_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::IOStreams library is available,
ax_cv_boost_iostreams,
[AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/iostreams/filtering_stream.hpp>
@%:@include <boost/range/iterator_range.hpp>
]],
[[std::string input = "Hello World!";
namespace io = boost::iostreams;
io::filtering_istream in(boost::make_iterator_range(input));
return 0;
]])],
ax_cv_boost_iostreams=yes, ax_cv_boost_iostreams=no)
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_iostreams" = "xyes"; then
AC_DEFINE(HAVE_BOOST_IOSTREAMS,,[define if the Boost::IOStreams library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
if test "x$ax_boost_user_iostreams_lib" = "x"; then
for libextension in `ls $BOOSTLIBDIR/libboost_iostreams*.so* $BOOSTLIBDIR/libboost_iostream*.dylib* $BOOSTLIBDIR/libboost_iostreams*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_iostreams.*\)\.so.*$;\1;' -e 's;^lib\(boost_iostream.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_iostreams.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
[link_iostreams="no"])
done
if test "x$link_iostreams" != "xyes"; then
for libextension in `ls $BOOSTLIBDIR/boost_iostreams*.dll* $BOOSTLIBDIR/boost_iostreams*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_iostreams.*\)\.dll.*$;\1;' -e 's;^\(boost_iostreams.*\)\.a.*$;\1;'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
[link_iostreams="no"])
done
fi
else
for ax_lib in $ax_boost_user_iostreams_lib boost_iostreams-$ax_boost_user_iostreams_lib; do
AC_CHECK_LIB($ax_lib, main,
[BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
[link_iostreams="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_iostreams" != "xyes"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])
-121
View File
@@ -1,121 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_boost_system.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_SYSTEM
#
# DESCRIPTION
#
# Test for System library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_SYSTEM_LIB)
#
# And sets:
#
# HAVE_BOOST_SYSTEM
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <[email protected]>
# Copyright (c) 2008 Michael Tindal
# Copyright (c) 2008 Daniel Casimiro <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 19
AC_DEFUN([AX_BOOST_SYSTEM],
[
AC_ARG_WITH([boost-system],
AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@],
[use the System library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-system=boost_system-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_system_lib=""
else
want_boost="yes"
ax_boost_user_system_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::System library is available,
ax_cv_boost_system,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
CXXFLAGS=
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
[[boost::system::error_category *a = 0;]])],
ax_cv_boost_system=yes, ax_cv_boost_system=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_system" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_system_lib" = "x"; then
for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
if test "x$link_system" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
fi
else
for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_system" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])
-72
View File
@@ -1,72 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the current language's compiler
# or gives an error. (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the current language's default
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <[email protected]>
# Copyright (c) 2011 Maarten Bosmans <[email protected]>
#
# 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 3 of the License, 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 <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 2
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS
-982
View File
@@ -1,982 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the specified
# version of the C++ standard. If necessary, add switches to CXX and
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
# or '14' (for the C++14 standard).
#
# The second argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
# -std=c++11). If neither is specified, you get whatever works, with
# preference for an extended mode.
#
# The third argument, if specified 'mandatory' or if left unspecified,
# indicates that baseline support for the specified C++ standard is
# required and that the macro should error out if no mode with that
# support is found. If specified 'optional', then configuration proceeds
# regardless, after defining HAVE_CXX${VERSION} if and only if a
# supporting mode is found.
#
# LICENSE
#
# Copyright (c) 2008 Benjamin Kosnik <[email protected]>
# Copyright (c) 2012 Zack Weinberg <[email protected]>
# Copyright (c) 2013 Roy Stogner <[email protected]>
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <[email protected]>
# Copyright (c) 2015 Paul Norman <[email protected]>
# Copyright (c) 2015 Moritz Klammler <[email protected]>
# Copyright (c) 2016 Krzesimir Nowak <[email protected]>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 7
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AX_REQUIRE_DEFINED([AC_MSG_WARN])
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
[$2], [noext], [],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
ax_cv_cxx_compile_cxx$1,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[ax_cv_cxx_compile_cxx$1=yes],
[ax_cv_cxx_compile_cxx$1=no])])
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
ac_success=yes
fi
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
for alternative in ${ax_cxx_compile_alternatives}; do
switch="-std=gnu++${alternative}"
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
fi])
m4_if([$2], [ext], [], [dnl
if test x$ac_success = xno; then
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
for alternative in ${ax_cxx_compile_alternatives}; do
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
[ac_save_CXX="$CXX"
CXX="$CXX $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXX="$ac_save_CXX"])
if eval test x\$$cachevar = xyes; then
CXX="$CXX $switch"
if test -n "$CXXCPP" ; then
CXXCPP="$CXXCPP $switch"
fi
ac_success=yes
break
fi
done
if test x$ac_success = xyes; then
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
fi
fi
if test x$ac_success = xno; then
HAVE_CXX$1=0
AC_MSG_NOTICE([No compiler with C++$1 support was found])
else
HAVE_CXX$1=1
AC_DEFINE(HAVE_CXX$1,1,
[define if the compiler supports basic C++$1 syntax])
fi
AC_SUBST(HAVE_CXX$1)
m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
])
dnl Test body for checking C++11 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
)
dnl Test body for checking C++14 support
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
)
dnl Tests for new features in C++11
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
// If the compiler admits that it is not ready for C++11, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201103L
#error "This is not a C++11 compiler"
#else
namespace cxx11
{
namespace test_static_assert
{
template <typename T>
struct check
{
static_assert(sizeof(int) <= sizeof(T), "not big enough");
};
}
namespace test_final_override
{
struct Base
{
virtual void f() {}
};
struct Derived : public Base
{
virtual void f() override {}
};
}
namespace test_double_right_angle_brackets
{
template < typename T >
struct check {};
typedef check<void> single_type;
typedef check<check<void>> double_type;
typedef check<check<check<void>>> triple_type;
typedef check<check<check<check<void>>>> quadruple_type;
}
namespace test_decltype
{
int
f()
{
int a = 1;
decltype(a) b = 2;
return a + b;
}
}
namespace test_type_deduction
{
template < typename T1, typename T2 >
struct is_same
{
static const bool value = false;
};
template < typename T >
struct is_same<T, T>
{
static const bool value = true;
};
template < typename T1, typename T2 >
auto
add(T1 a1, T2 a2) -> decltype(a1 + a2)
{
return a1 + a2;
}
int
test(const int c, volatile int v)
{
static_assert(is_same<int, decltype(0)>::value == true, "");
static_assert(is_same<int, decltype(c)>::value == false, "");
static_assert(is_same<int, decltype(v)>::value == false, "");
auto ac = c;
auto av = v;
auto sumi = ac + av + 'x';
auto sumf = ac + av + 1.0;
static_assert(is_same<int, decltype(ac)>::value == true, "");
static_assert(is_same<int, decltype(av)>::value == true, "");
static_assert(is_same<int, decltype(sumi)>::value == true, "");
static_assert(is_same<int, decltype(sumf)>::value == false, "");
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
return (sumf > 0.0) ? sumi : add(c, v);
}
}
namespace test_noexcept
{
int f() { return 0; }
int g() noexcept { return 0; }
static_assert(noexcept(f()) == false, "");
static_assert(noexcept(g()) == true, "");
}
namespace test_constexpr
{
template < typename CharT >
unsigned long constexpr
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
{
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
}
template < typename CharT >
unsigned long constexpr
strlen_c(const CharT *const s) noexcept
{
return strlen_c_r(s, 0UL);
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("1") == 1UL, "");
static_assert(strlen_c("example") == 7UL, "");
static_assert(strlen_c("another\0example") == 7UL, "");
}
namespace test_rvalue_references
{
template < int N >
struct answer
{
static constexpr int value = N;
};
answer<1> f(int&) { return answer<1>(); }
answer<2> f(const int&) { return answer<2>(); }
answer<3> f(int&&) { return answer<3>(); }
void
test()
{
int i = 0;
const int c = 0;
static_assert(decltype(f(i))::value == 1, "");
static_assert(decltype(f(c))::value == 2, "");
static_assert(decltype(f(0))::value == 3, "");
}
}
namespace test_uniform_initialization
{
struct test
{
static const int zero {};
static const int one {1};
};
static_assert(test::zero == 0, "");
static_assert(test::one == 1, "");
}
namespace test_lambdas
{
void
test1()
{
auto lambda1 = [](){};
auto lambda2 = lambda1;
lambda1();
lambda2();
}
int
test2()
{
auto a = [](int i, int j){ return i + j; }(1, 2);
auto b = []() -> int { return '0'; }();
auto c = [=](){ return a + b; }();
auto d = [&](){ return c; }();
auto e = [a, &b](int x) mutable {
const auto identity = [](int y){ return y; };
for (auto i = 0; i < a; ++i)
a += b--;
return x + identity(a + b);
}(0);
return a + b + c + d + e;
}
int
test3()
{
const auto nullary = [](){ return 0; };
const auto unary = [](int x){ return x; };
using nullary_t = decltype(nullary);
using unary_t = decltype(unary);
const auto higher1st = [](nullary_t f){ return f(); };
const auto higher2nd = [unary](nullary_t f1){
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
};
return higher1st(nullary) + higher2nd(nullary)(unary);
}
}
namespace test_variadic_templates
{
template <int...>
struct sum;
template <int N0, int... N1toN>
struct sum<N0, N1toN...>
{
static constexpr auto value = N0 + sum<N1toN...>::value;
};
template <>
struct sum<>
{
static constexpr auto value = 0;
};
static_assert(sum<>::value == 0, "");
static_assert(sum<1>::value == 1, "");
static_assert(sum<23>::value == 23, "");
static_assert(sum<1, 2>::value == 3, "");
static_assert(sum<5, 5, 11>::value == 21, "");
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
}
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
// because of this.
namespace test_template_alias_sfinae
{
struct foo {};
template<typename T>
using member = typename T::member_type;
template<typename T>
void func(...) {}
template<typename T>
void func(member<T>*) {}
void test();
void test() { func<foo>(0); }
}
} // namespace cxx11
#endif // __cplusplus >= 201103L
]])
dnl Tests for new features in C++14
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
// If the compiler admits that it is not ready for C++14, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus < 201402L
#error "This is not a C++14 compiler"
#else
namespace cxx14
{
namespace test_polymorphic_lambdas
{
int
test()
{
const auto lambda = [](auto&&... args){
const auto istiny = [](auto x){
return (sizeof(x) == 1UL) ? 1 : 0;
};
const int aretiny[] = { istiny(args)... };
return aretiny[0];
};
return lambda(1, 1L, 1.0f, '1');
}
}
namespace test_binary_literals
{
constexpr auto ivii = 0b0000000000101010;
static_assert(ivii == 42, "wrong value");
}
namespace test_generalized_constexpr
{
template < typename CharT >
constexpr unsigned long
strlen_c(const CharT *const s) noexcept
{
auto length = 0UL;
for (auto p = s; *p; ++p)
++length;
return length;
}
static_assert(strlen_c("") == 0UL, "");
static_assert(strlen_c("x") == 1UL, "");
static_assert(strlen_c("test") == 4UL, "");
static_assert(strlen_c("another\0test") == 7UL, "");
}
namespace test_lambda_init_capture
{
int
test()
{
auto x = 0;
const auto lambda1 = [a = x](int b){ return a + b; };
const auto lambda2 = [a = lambda1(x)](){ return a; };
return lambda2();
}
}
namespace test_digit_separators
{
constexpr auto ten_million = 100'000'000;
static_assert(ten_million == 100000000, "");
}
namespace test_return_type_deduction
{
auto f(int& x) { return x; }
decltype(auto) g(int& x) { return x; }
template < typename T1, typename T2 >
struct is_same
{
static constexpr auto value = false;
};
template < typename T >
struct is_same<T, T>
{
static constexpr auto value = true;
};
int
test()
{
auto x = 0;
static_assert(is_same<int, decltype(f(x))>::value, "");
static_assert(is_same<int&, decltype(g(x))>::value, "");
return x;
}
}
} // namespace cxx14
#endif // __cplusplus >= 201402L
]])
dnl Tests for new features in C++17
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
// If the compiler admits that it is not ready for C++17, why torture it?
// Hopefully, this will speed up the test.
#ifndef __cplusplus
#error "This is not a C++ compiler"
#elif __cplusplus <= 201402L
#error "This is not a C++17 compiler"
#else
#if defined(__clang__)
#define REALLY_CLANG
#else
#if defined(__GNUC__)
#define REALLY_GCC
#endif
#endif
#include <initializer_list>
#include <utility>
#include <type_traits>
namespace cxx17
{
#if !defined(REALLY_CLANG)
namespace test_constexpr_lambdas
{
// TODO: test it with clang++ from git
constexpr int foo = [](){return 42;}();
}
#endif // !defined(REALLY_CLANG)
namespace test::nested_namespace::definitions
{
}
namespace test_fold_expression
{
template<typename... Args>
int multiply(Args... args)
{
return (args * ... * 1);
}
template<typename... Args>
bool all(Args... args)
{
return (args && ...);
}
}
namespace test_extended_static_assert
{
static_assert (true);
}
namespace test_auto_brace_init_list
{
auto foo = {5};
auto bar {5};
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
static_assert(std::is_same<int, decltype(bar)>::value);
}
namespace test_typename_in_template_template_parameter
{
template<template<typename> typename X> struct D;
}
namespace test_fallthrough_nodiscard_maybe_unused_attributes
{
int f1()
{
return 42;
}
[[nodiscard]] int f2()
{
[[maybe_unused]] auto unused = f1();
switch (f1())
{
case 17:
f1();
[[fallthrough]];
case 42:
f1();
}
return f1();
}
}
namespace test_extended_aggregate_initialization
{
struct base1
{
int b1, b2 = 42;
};
struct base2
{
base2() {
b3 = 42;
}
int b3;
};
struct derived : base1, base2
{
int d;
};
derived d1 {{1, 2}, {}, 4}; // full initialization
derived d2 {{}, {}, 4}; // value-initialized bases
}
namespace test_general_range_based_for_loop
{
struct iter
{
int i;
int& operator* ()
{
return i;
}
const int& operator* () const
{
return i;
}
iter& operator++()
{
++i;
return *this;
}
};
struct sentinel
{
int i;
};
bool operator== (const iter& i, const sentinel& s)
{
return i.i == s.i;
}
bool operator!= (const iter& i, const sentinel& s)
{
return !(i == s);
}
struct range
{
iter begin() const
{
return {0};
}
sentinel end() const
{
return {5};
}
};
void f()
{
range r {};
for (auto i : r)
{
[[maybe_unused]] auto v = i;
}
}
}
namespace test_lambda_capture_asterisk_this_by_value
{
struct t
{
int i;
int foo()
{
return [*this]()
{
return i;
}();
}
};
}
namespace test_enum_class_construction
{
enum class byte : unsigned char
{};
byte foo {42};
}
namespace test_constexpr_if
{
template <bool cond>
int f ()
{
if constexpr(cond)
{
return 13;
}
else
{
return 42;
}
}
}
namespace test_selection_statement_with_initializer
{
int f()
{
return 13;
}
int f2()
{
if (auto i = f(); i > 0)
{
return 3;
}
switch (auto i = f(); i + 4)
{
case 17:
return 2;
default:
return 1;
}
}
}
#if !defined(REALLY_CLANG)
namespace test_template_argument_deduction_for_class_templates
{
// TODO: test it with clang++ from git
template <typename T1, typename T2>
struct pair
{
pair (T1 p1, T2 p2)
: m1 {p1},
m2 {p2}
{}
T1 m1;
T2 m2;
};
void f()
{
[[maybe_unused]] auto p = pair{13, 42u};
}
}
#endif // !defined(REALLY_CLANG)
namespace test_non_type_auto_template_parameters
{
template <auto n>
struct B
{};
B<5> b1;
B<'a'> b2;
}
#if !defined(REALLY_CLANG)
namespace test_structured_bindings
{
// TODO: test it with clang++ from git
int arr[2] = { 1, 2 };
std::pair<int, int> pr = { 1, 2 };
auto f1() -> int(&)[2]
{
return arr;
}
auto f2() -> std::pair<int, int>&
{
return pr;
}
struct S
{
int x1 : 2;
volatile double y1;
};
S f3()
{
return {};
}
auto [ x1, y1 ] = f1();
auto& [ xr1, yr1 ] = f1();
auto [ x2, y2 ] = f2();
auto& [ xr2, yr2 ] = f2();
const auto [ x3, y3 ] = f3();
}
#endif // !defined(REALLY_CLANG)
#if !defined(REALLY_CLANG)
namespace test_exception_spec_type_system
{
// TODO: test it with clang++ from git
struct Good {};
struct Bad {};
void g1() noexcept;
void g2();
template<typename T>
Bad
f(T*, T*);
template<typename T1, typename T2>
Good
f(T1*, T2*);
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
}
#endif // !defined(REALLY_CLANG)
namespace test_inline_variables
{
template<class T> void f(T)
{}
template<class T> inline T g(T)
{
return T{};
}
template<> inline void f<>(int)
{}
template<> int g<>(int)
{
return 5;
}
}
} // namespace cxx17
#endif // __cplusplus <= 201402L
]])
-332
View File
@@ -1,332 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION
#
# This macro figures out how to build C programs using POSIX threads. It
# sets the PTHREAD_LIBS output variable to the threads library and linker
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
# PTHREAD_CFLAGS.
#
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
# is not found. If ACTION-IF-FOUND is not specified, the default action
# will define HAVE_PTHREAD.
#
# Please let the authors know if this macro fails on any platform, or if
# you have any other suggestions or comments. This macro was based on work
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
# grateful for the helpful feedback of numerous users.
#
# Updated for Autoconf 2.68 by Daniel Richard G.
#
# LICENSE
#
# Copyright (c) 2008 Steven G. Johnson <[email protected]>
# Copyright (c) 2011 Daniel Richard G. <[email protected]>
#
# 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 3 of the License, 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 <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
fi
# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
# need a special flag -Kthread to make this header compile.)
# We check for pthread_join because it is in -lpthread on IRIX
# while pthread_create is in libc. We check for pthread_attr_init
# due to DEC craziness with -lpthreads. We check for
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { a = 0; }
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
pthread_join(th, 0);
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else
ax_pthread_ok=no
$2
fi
AC_LANG_POP
])dnl AX_PTHREAD
-134
View File
@@ -1,134 +0,0 @@
dnl @synopsis EV_DEVEL
dnl
dnl This macro tries to find the libev library and header files.
dnl
dnl We define the following configure script flags:
dnl
dnl --with-ev: Give prefix for both library and headers, and try
dnl to guess subdirectory names for each. (e.g. tack /lib and
dnl /include onto given dir name, and other common schemes.)
dnl --with-ev-lib: Similar to --with-ev, but for library only.
dnl --with-ev-include: Similar to --with-ev, but for headers
dnl only.
AC_DEFUN([EV_DEVEL],
[
dnl
dnl Set up configure script macros
dnl
AC_ARG_WITH(ev,
[AS_HELP_STRING([--with-ev=<path>],[path containing libev header and library subdirs])],
[EV_lib_check="$with_ev/lib64 $with_ev/lib $with_ev/lib64/libev $with_ev/lib/libev"
EV_inc_check="$with_ev/include $with_ev/include/libev"],
[EV_lib_check="/usr/local/libev/lib64 /usr/local/libev/lib /usr/local/lib64/libev /usr/local/lib/libev /opt/libev/lib64 /opt/libev/lib /usr/lib64/libev /usr/lib/libev /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib64/x86_64-linux-gnu"
EV_inc_check="/usr/local/libev/include /usr/local/include/libev /opt/libev/include /usr/local/include/libev /usr/local/include /usr/include/libev /usr/include"])
AC_ARG_WITH(ev-lib,
[AS_HELP_STRING([--with-ev-lib=<path>],[directory path of libev library])],
[EV_lib_check="$with_ev_lib $with_ev_lib/lib64 $with_ev_lib/lib $with_ev_lib/lib64/libev $with_ev_lib/lib/libev"])
AC_ARG_WITH(ev-include,
[AS_HELP_STRING([--with-ev-include=<path>],[directory path of libev headers])],
[EV_inc_check="$with_ev_include $with_ev_include/include $with_ev_include/include/libev"])
dnl
dnl Look for libev library
dnl
AC_CACHE_CHECK([for libev library location], [ac_cv_ev_lib],
[
for dir in $EV_lib_check
do
if test -d "$dir" && \
( test -f "$dir/libev.so" ||
test -f "$dir/libev.a" )
then
ac_cv_ev_lib=$dir
break
fi
done
if test -z "$ac_cv_ev_lib"
then
AC_MSG_RESULT([no])
AC_MSG_ERROR([Didn't find the libev library dir in '$EV_lib_check'])
fi
case "$ac_cv_ev_lib" in
/* )
;;
* )
AC_MSG_RESULT([])
AC_MSG_ERROR([The libev library directory ($ac_cv_ev_lib) must be an absolute path.])
;;
esac
])
AC_SUBST([EV_LIB_DIR],[$ac_cv_ev_lib])
dnl
dnl Look for libev header file directory
dnl
AC_CACHE_CHECK([for libev include path], [ac_cv_ev_inc],
[
for dir in $EV_inc_check
do
if test -d "$dir" && test -f "$dir/ev++.h"
then
ac_cv_ev_inc=$dir
break
fi
done
if test -z "$ac_cv_ev_inc"
then
AC_MSG_RESULT([no])
AC_MSG_ERROR([Didn't find the libev header dir in '$EV_inc_check'])
fi
case "$ac_cv_ev_inc" in
/* )
;;
* )
AC_MSG_RESULT([])
AC_MSG_ERROR([The libev header directory ($ac_cv_ev_inc) must be an absolute path.])
;;
esac
])
AC_SUBST([EV_INC_DIR],[$ac_cv_ev_inc])
dnl
dnl Now check that the above checks resulted in -I and -L flags that
dnl let us build actual programs against libev.
dnl
case "$ac_cv_ev_lib" in
/usr/lib)
;;
*)
LDFLAGS="$LDFLAGS -L${ac_cv_ev_lib}"
;;
esac
CPPFLAGS="$CPPFLAGS -I${ac_cv_ev_inc}"
AC_MSG_CHECKING([that we can build libev programs])
AC_EGREP_CPP(
[bad_gcc_libev_ver],
[
#include <ev.h>
#if __GNUC__ && (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 9) && EV_VERSION_MAJOR == 4 && EV_VERSION_MINOR == 18
bad_gcc_libev_ver
#endif
],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([GCC versions prior to 4.9 cannot compile libev 4.18])],
[],
)
LIBS="-lev $LIBS"
AC_LANG_PUSH([C++])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[#include <ev++.h>],
[ev::io i])
],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_FAILURE([Cannot build libev programs])]
)
AC_LANG_POP([C++])
]) dnl End EV_DEVEL
-150
View File
@@ -1,150 +0,0 @@
#-######################################################################
# mysql++.m4 - Example autoconf macro showing how to find MySQL++
# library and header files.
#
# Copyright (c) 2004-2009 by Educational Technology Resources, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
#-######################################################################
dnl @synopsis MYSQLPP_DEVEL
dnl
dnl This macro tries to find the MySQL++ library and header files.
dnl
dnl We define the following configure script flags:
dnl
dnl --with-mysqlpp: Give prefix for both library and headers, and try
dnl to guess subdirectory names for each. (e.g. tack /lib and
dnl /include onto given dir name, and other common schemes.)
dnl --with-mysqlpp-lib: Similar to --with-mysqlpp, but for library only.
dnl --with-mysqlpp-include: Similar to --with-mysqlpp, but for headers
dnl only.
dnl
dnl This macro depends on having the default compiler and linker flags
dnl set up for building programs against the MySQL C API. The mysql.m4
dnl macro in this directory fits this bill; run it first.
dnl
dnl @version 1.3, 2009/11/22
dnl @author Warren Young <[email protected]>
AC_DEFUN([MYSQLPP_DEVEL],
[
dnl
dnl Set up configure script macros
dnl
AC_ARG_WITH(mysqlpp,
[AS_HELP_STRING([--with-mysqlpp=<path>],[path containing MySQL++ header and library subdirs])],
[MYSQLPP_lib_check="$with_mysqlpp/lib64 $with_mysqlpp/lib $with_mysqlpp/lib64/mysql++ $with_mysqlpp/lib/mysql++"
MYSQLPP_inc_check="$with_mysqlpp/include $with_mysqlpp/include/mysql++"],
[MYSQLPP_lib_check="/usr/local/mysql++/lib64 /usr/local/mysql++/lib /usr/local/lib64/mysql++ /usr/local/lib/mysql++ /opt/mysql++/lib64 /opt/mysql++/lib /usr/lib64/mysql++ /usr/lib/mysql++ /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib"
MYSQLPP_inc_check="/usr/local/mysql++/include /usr/local/include/mysql++ /opt/mysql++/include /usr/local/include/mysql++ /usr/local/include /usr/include/mysql++ /usr/include"])
AC_ARG_WITH(mysqlpp-lib,
[AS_HELP_STRING([--with-mysqlpp-lib=<path>],[directory path of MySQL++ library])],
[MYSQLPP_lib_check="$with_mysqlpp_lib $with_mysqlpp_lib/lib64 $with_mysqlpp_lib/lib $with_mysqlpp_lib/lib64/mysql $with_mysqlpp_lib/lib/mysql"])
AC_ARG_WITH(mysqlpp-include,
[AS_HELP_STRING([--with-mysqlpp-include=<path>],[directory path of MySQL++ headers])],
[MYSQLPP_inc_check="$with_mysqlpp_include $with_mysqlpp_include/include $with_mysqlpp_include/include/mysql"])
dnl
dnl Look for MySQL++ library
dnl
AC_CACHE_CHECK([for MySQL++ library location], [ac_cv_mysqlpp_lib],
[
for dir in $MYSQLPP_lib_check
do
if test -d "$dir" && \
( test -f "$dir/libmysqlpp.so" ||
test -f "$dir/libmysqlpp.a" )
then
ac_cv_mysqlpp_lib=$dir
break
fi
done
if test -z "$ac_cv_mysqlpp_lib"
then
AC_MSG_RESULT([no])
AC_MSG_ERROR([Didn't find the MySQL++ library dir in '$MYSQLPP_lib_check'])
fi
case "$ac_cv_mysqlpp_lib" in
/* )
;;
* )
AC_MSG_RESULT([no])
AC_MSG_ERROR([The MySQL++ library directory ($ac_cv_mysqlpp_lib) must be an absolute path.])
;;
esac
])
AC_SUBST([MYSQLPP_LIB_DIR],[$ac_cv_mysqlpp_lib])
dnl
dnl Look for MySQL++ header file directory
dnl
AC_CACHE_CHECK([for MySQL++ include path], [ac_cv_mysqlpp_inc],
[
for dir in $MYSQLPP_inc_check
do
if test -d "$dir" && test -f "$dir/mysql++.h"
then
ac_cv_mysqlpp_inc=$dir
break
fi
done
if test -z "$ac_cv_mysqlpp_inc"
then
AC_MSG_RESULT([no])
AC_MSG_ERROR([Didn't find the MySQL++ header dir in '$MYSQLPP_inc_check'])
fi
case "$ac_cv_mysqlpp_inc" in
/* )
;;
* )
AC_MSG_RESULT([no])
AC_MSG_ERROR([The MySQL++ header directory ($ac_cv_mysqlpp_inc) must be an absolute path.])
;;
esac
])
AC_SUBST([MYSQLPP_INC_DIR],[$ac_cv_mysqlpp_inc])
dnl
dnl Now check that the above checks resulted in -I and -L flags that
dnl let us build actual programs against MySQL++.
dnl
case "$ac_cv_mysqlpp_lib" in
/usr/lib)
;;
*)
LDFLAGS="$LDFLAGS -L${ac_cv_mysqlpp_lib}"
;;
esac
CPPFLAGS="$CPPFLAGS -I${ac_cv_mysqlpp_inc}"
LIBS="-lmysqlpp $LIBS"
AC_LANG_PUSH([C++])
AC_MSG_CHECKING([that we can build MySQL++ programs])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[#include <mysql++.h>],
[mysqlpp::Connection c(false)]
)],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AC_MSG_ERROR([Cannot build MySQL++ programs])]
)
AC_LANG_POP([C++])
]) dnl End MYSQLPP_DEVEL
-137
View File
@@ -1,137 +0,0 @@
dnl @synopsis MYSQL_C_API_LOCATION
dnl
dnl This macro tries to find MySQL C API header and library locations.
dnl
dnl We define the following configure script flags:
dnl
dnl --with-mysql: Give prefix for both library and headers, and try
dnl to guess subdirectory names for each by tacking common
dnl suffixes on like /lib and /include.
dnl --with-mysql-lib: Same as --with-mysql, but for library only.
dnl --with-mysql-include: Same as --with-mysql, but for headers only.
dnl
dnl @version 1.4, 2009/05/28
dnl @author Warren Young <[email protected]>
AC_DEFUN([MYSQL_C_API_LOCATION],
[
#
# Set up configure script macros
#
AC_ARG_WITH(mysql,
[ --with-mysql=<path> root directory path of MySQL installation],
[MYSQL_lib_check="$with_mysql/lib/mysql $with_mysql/lib"
MYSQL_inc_check="$with_mysql/include $with_mysql/include/mysql"],
[MYSQL_lib_check="/usr/lib64 /usr/lib /usr/lib64/mysql /usr/lib/mysql /usr/local/lib64 /usr/local/lib /usr/local/lib/mysql /usr/local/mysql/lib /usr/local/mysql/lib/mysql /usr/mysql/lib/mysql /opt/mysql/lib /opt/mysql/lib/mysql /sw/lib /sw/lib/mysql /usr/lib/x86_64-linux-gnu"
MYSQL_inc_check="/usr/include/mysql /usr/local/include/mysql /usr/local/mysql/include /usr/local/mysql/include/mysql /usr/mysql/include/mysql /opt/mysql/include/mysql /sw/include/mysql"])
AC_ARG_WITH(mysql-lib,
[ --with-mysql-lib=<path> directory path of MySQL library installation],
[MYSQL_lib_check="$with_mysql_lib $with_mysql_lib/lib64 $with_mysql_lib/lib $with_mysql_lib/lib64/mysql $with_mysql_lib/lib/mysql"])
AC_ARG_WITH(mysql-include,
[ --with-mysql-include=<path> directory path of MySQL header installation],
[MYSQL_inc_check="$with_mysql_include $with_mysql_include/include $with_mysql_include/include/mysql"])
#
# Decide which C API library to use, based on thread support
#
if test "x$acx_pthread_ok" = xyes
then
MYSQL_C_LIB_NAME=mysqlclient_r
else
MYSQL_C_LIB_NAME=mysqlclient
fi
#
# Look for MySQL C API library
#
AC_MSG_CHECKING([for MySQL library directory])
MYSQL_C_LIB_DIR=
for m in $MYSQL_lib_check
do
if test -d "$m" && \
(test -f "$m/lib$MYSQL_C_LIB_NAME.so" || \
test -f "$m/lib$MYSQL_C_LIB_NAME.a")
then
MYSQL_C_LIB_DIR=$m
break
fi
done
if test -z "$MYSQL_C_LIB_DIR"
then
AC_MSG_ERROR([Didn't find $MYSQL_C_LIB_NAME library in '$MYSQL_lib_check'])
fi
case "$MYSQL_C_LIB_DIR" in
/* ) ;;
* ) AC_MSG_ERROR([The MySQL library directory ($MYSQL_C_LIB_DIR) must be an absolute path.]) ;;
esac
AC_MSG_RESULT([$MYSQL_C_LIB_DIR])
case "$MYSQL_C_LIB_DIR" in
/usr/lib)
MYSQL_C_LIB_DIR=
;;
*)
LDFLAGS="$LDFLAGS -L${MYSQL_C_LIB_DIR}"
;;
esac
#
# Look for MySQL C API headers
#
AC_MSG_CHECKING([for MySQL include directory])
MYSQL_C_INC_DIR=
for m in $MYSQL_inc_check
do
if test -d "$m" && test -f "$m/mysql.h"
then
MYSQL_C_INC_DIR=$m
break
fi
done
if test -z "$MYSQL_C_INC_DIR"
then
AC_MSG_ERROR([Didn't find the MySQL include dir in '$MYSQL_inc_check'])
fi
case "$MYSQL_C_INC_DIR" in
/* ) ;;
* ) AC_MSG_ERROR([The MySQL include directory ($MYSQL_C_INC_DIR) must be an absolute path.]) ;;
esac
AC_MSG_RESULT([$MYSQL_C_INC_DIR])
CPPFLAGS="$CPPFLAGS -I${MYSQL_C_INC_DIR}"
AC_MSG_CHECKING([if we can link to MySQL C API library directly])
save_LIBS=$LIBS
LIBS="$LIBS -l$MYSQL_C_LIB_NAME $MYSQLPP_EXTRA_LIBS"
AC_TRY_LINK(
[ #include <mysql.h> ],
[ mysql_store_result(0); ],
AC_MSG_RESULT([yes]),
[ AC_MSG_RESULT([no])
LIBS="$save_LIBS"
AC_CHECK_HEADERS(zlib.h, AC_CHECK_LIB(z, gzread, [],
[ AC_MSG_ERROR([zlib not found]) ]))
AC_MSG_CHECKING([whether adding -lz will let MySQL C API link succeed])
MYSQLPP_EXTRA_LIBS="$MYSQLPP_EXTRA_LIBS -lz"
LIBS="$save_LIBS -l$MYSQL_C_LIB_NAME $MYSQLPP_EXTRA_LIBS"
AC_TRY_LINK(
[ #include <mysql.h> ],
[ mysql_store_result(0); ],
AC_MSG_RESULT([yes]),
[ AC_MSG_RESULT([no])
AC_MSG_ERROR([Unable to link to MySQL client library!])
]
)
])
LIBS=$save_LIBS
AC_SUBST(MYSQL_C_INC_DIR)
AC_SUBST(MYSQL_C_LIB_DIR)
AC_SUBST(MYSQL_C_LIB_NAME)
]) dnl MYSQL_C_API_LOCATION
-11
View File
@@ -1,11 +0,0 @@
AC_DEFUN([TCMALLOC],
[AC_ARG_WITH(
[tcmalloc],
[AS_HELP_STRING([--with-tcmalloc], [use tcmalloc if it's available [default=yes]])],
[],
[with_tcmalloc=yes])
AS_IF([test "x$with_tcmalloc" != "xno"],
[AC_CHECK_LIB([tcmalloc], [tc_free])]
)]
)
-215
View File
@@ -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 <[email protected]>, 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 <http://www.gnu.org/licenses/>.
# 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 <[email protected]>."
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:
+11 -4
View File
@@ -11,14 +11,16 @@ connection_timeout = 10
keepalive_timeout = 0
announce_interval = 1800
announce_jitter = 240
max_request_size = 4096
numwant_limit = 50
request_log_size = 500
mysql_host =
mysql_username =
mysql_password =
mysql_db =
mysql_host = mysql
mysql_port = 36000
mysql_username = gazelle
mysql_password = password
mysql_db = gazelle
# The passwords must be 32 characters and match the Gazelle config
report_password = 00000000000000000000000000000000
@@ -32,4 +34,9 @@ schedule_interval = 3
log = false
log_path = /tmp/ocelot
# the report path should be placed on a tmpfs partition in production
report_path = /tmp/ocelot
# set to true if prevent peer data from being zeroed out on startup
# useful to test a new version alongside an instance running in production
readonly = false
+20
View File
@@ -0,0 +1,20 @@
[Unit]
Description=Ocelot Bittorrent Tracker
After=network.target
After=mysql.target
Requires=network.target
Requires=mysql.service
[Service]
Type=simple
TimeoutStartSec=0
ExecStart=/usr/local/bin/ocelot
ExecReload=/bin/kill -HUP $MAINPID
PIDFile=/var/run/ocelot.pid
RestartSec=20
TimeoutStopSec=60
TimeoutStartSec=360
Restart=always
[Install]
WantedBy=multi-user.target
-8
View File
@@ -1,8 +0,0 @@
bin_PROGRAMS = ocelot
ocelot_SOURCES = config.cpp config.h db.cpp db.h events.cpp events.h misc_functions.cpp misc_functions.h \
ocelot.cpp ocelot.h report.cpp report.h response.cpp response.h \
schedule.cpp schedule.h site_comm.cpp site_comm.h user.cpp user.h worker.cpp worker.h
AM_CXXFLAGS = -std=c++11 -march=native -O2 -fvisibility=hidden -fvisibility-inlines-hidden -fomit-frame-pointer -fno-ident -Wall -Wfatal-errors $(PTHREAD_CFLAGS) $(BOOST_CPPFLAGS)
ocelot_LDADD = $(PTHREAD_LIBS) $(BOOST_IOSTREAMS_LIB) $(BOOST_SYSTEM_LIB)
AM_LDFLAGS = -Wl,-O1 -Wl,--as-needed
+104 -94
View File
@@ -1,162 +1,172 @@
// Copyright [2017-2024] Orpheus
#include <spdlog/spdlog.h>
#include <iostream>
#include <fstream>
#include <string>
#include <spdlog/spdlog.h>
#include "config.h"
#include "misc_functions.h"
confval::confval() {
bool_val = 0;
uint_val = 0;
str_val = "";
val_type = CONF_NONEXISTENT;
bool_val = 0;
uint_val = 0;
str_val = "";
val_type = CONF_NONEXISTENT;
}
confval::confval(bool value) {
bool_val = value;
val_type = CONF_BOOL;
bool_val = value;
val_type = CONF_BOOL;
}
confval::confval(unsigned int value) {
uint_val = value;
val_type = CONF_UINT;
uint_val = value;
val_type = CONF_UINT;
}
confval::confval(const char * value) {
str_val = value;
val_type = CONF_STR;
str_val = value;
val_type = CONF_STR;
}
bool confval::get_bool() {
return bool_val;
return bool_val;
}
unsigned int confval::get_uint() {
return uint_val;
return uint_val;
}
std::string confval::get_str() {
return str_val;
return str_val;
}
void confval::set(const std::string &value) {
if (val_type == CONF_BOOL) {
bool_val = value == "1" || value == "true" || value == "yes";
} else if (val_type == CONF_UINT) {
uint_val = strtoint32(value);
} else if (val_type == CONF_STR) {
str_val = value;
}
if (val_type == CONF_BOOL) {
bool_val = value == "1" || value == "true" || value == "yes";
} else if (val_type == CONF_UINT) {
uint_val = strtoint32(value);
} else if (val_type == CONF_STR) {
str_val = value;
}
}
config::config() {
init();
dummy_setting = new confval(); // Safety value to use if we're accessing nonexistent settings
init();
dummy_setting = new confval(); // Safety value to use if we're accessing nonexistent settings
}
void config::init() {
// Internal stuff
add("listen_port", 34000u);
add("max_connections", 1024u);
add("max_middlemen", 20000u);
add("max_read_buffer", 4096u);
add("connection_timeout", 10u);
add("keepalive_timeout", 0u);
add("daemonize", false);
// Internal stuff
add("listen_port", 34000u);
add("max_connections", 1024u);
add("max_middlemen", 20000u);
add("max_read_buffer", 4096u);
add("connection_timeout", 10u);
add("keepalive_timeout", 0u);
add("daemonize", false);
// Tracker requests
add("announce_interval", 1800u);
add("max_request_size", 4096u);
add("numwant_limit", 50u);
add("request_log_size", 500u);
// Tracker requests
add("announce_interval", 1800u);
add("announce_jitter", 240u);
add("max_request_size", 4096u);
add("numwant_limit", 50u);
add("request_log_size", 500u);
// Timers
add("del_reason_lifetime", 86400u);
add("peers_timeout", 7200u);
add("reap_peers_interval", 1800u);
add("schedule_interval", 3u);
// Timers
add("del_reason_lifetime", 86400u);
add("peers_timeout", 7200u);
add("reap_peers_interval", 1800u);
add("schedule_interval", 3u);
// MySQL
add("mysql_db", "gazelle");
add("mysql_host", "localhost");
add("mysql_username", "");
add("mysql_password", "");
// MySQL
add("mysql_db", "gazelle");
add("mysql_host", "localhost");
add("mysql_port", 3306u);
add("mysql_username", "");
add("mysql_password", "");
add("mysql_port", 3306u);
// Site communication
add("site_host", "127.0.0.1");
add("site_path", "");
add("site_password", "00000000000000000000000000000000");
add("report_password", "00000000000000000000000000000000");
// Site communication
add("site_host", "127.0.0.1");
add("site_service", "http");
add("site_path", "");
add("site_password", "00000000000000000000000000000000");
add("report_password", "00000000000000000000000000000000");
// Logging
add("log", false);
add("log_path", "ocelot"); // path to where to write log + name of log (don't need to put file extension)
// Logging
add("log", false);
add("log_path", "ocelot"); // path to where to write log + name of log (don't need to put file extension)
// Debugging
add("readonly", false);
add("report_path", "/tmp"); // path for transfer to website (should be a tmpfs in production)
// Debugging
add("readonly", false);
}
confval * config::get(const std::string &setting_name) {
const auto setting = settings.find(setting_name);
if (setting == settings.end()) {
spdlog::get("logger")->info("WARNING: Unrecognized setting '" + setting_name + "'");
return dummy_setting;
}
return &setting->second;
const auto setting = settings.find(setting_name);
if (setting == settings.end()) {
spdlog::get("logger")->info("WARNING: Unrecognized setting '" + setting_name + "'");
return dummy_setting;
}
return &setting->second;
}
bool config::get_bool(const std::string &setting_name) {
return get(setting_name)->get_bool();
return get(setting_name)->get_bool();
}
unsigned int config::get_uint(const std::string &setting_name) {
return get(setting_name)->get_uint();
return get(setting_name)->get_uint();
}
std::string config::get_str(const std::string &setting_name) {
return get(setting_name)->get_str();
return get(setting_name)->get_str();
}
void config::set(const std::string &setting_name, const std::string &value) {
get(setting_name)->set(value);
get(setting_name)->set(value);
}
void config::load(const std::string &conf_file_path, std::istream &conf_file) {
load(conf_file);
add("conf_file_path", conf_file_path.c_str());
load(conf_file);
add("conf_file_path", conf_file_path.c_str());
}
void config::load(std::istream &conf_file) {
std::string line;
while (getline(conf_file, line)) {
size_t pos;
if (line[0] != '#' && (pos = line.find('=')) != std::string::npos) {
std::string key(trim(line.substr(0, pos)));
std::string value(trim(line.substr(pos + 1)));
set(key, value);
}
}
std::string line;
while (getline(conf_file, line)) {
size_t pos;
if (line[0] != '#' && (pos = line.find('=')) != std::string::npos) {
std::string key(trim(line.substr(0, pos)));
std::string value(trim(line.substr(pos + 1)));
set(key, value);
}
}
}
void config::reload() {
const std::string conf_file_path(get_str("conf_file_path"));
std::ifstream conf_file(conf_file_path);
if (conf_file.fail()) {
spdlog::get("logger")->error("Config file '" + conf_file_path + "' couldn't be opened");
} else {
init();
load(conf_file);
}
const std::string conf_file_path(get_str("conf_file_path"));
std::ifstream conf_file(conf_file_path);
if (conf_file.fail()) {
spdlog::get("logger")->error("Config file '" + conf_file_path + "' couldn't be opened");
} else {
init();
load(conf_file);
}
}
std::string config::trim(const std::string str) {
size_t ltrim = str.find_first_not_of(" \t");
if (ltrim == std::string::npos) {
ltrim = 0;
}
size_t rtrim = str.find_last_not_of(" \t");
if (ltrim != 0 || rtrim != str.length() - 1) {
return str.substr(ltrim, rtrim - ltrim + 1);
}
return str;
size_t ltrim = str.find_first_not_of(" \t");
if (ltrim == std::string::npos) {
ltrim = 0;
}
size_t rtrim = str.find_last_not_of(" \t");
if (ltrim != 0 || rtrim != str.length() - 1) {
return str.substr(ltrim, rtrim - ltrim + 1);
}
return str;
}
+43 -40
View File
@@ -1,52 +1,55 @@
#ifndef OCELOT_CONFIG_H
#define OCELOT_CONFIG_H
#ifndef SRC_CONFIG_H_
#define SRC_CONFIG_H_
// Copyright [2017-2024] Orpheus
#include <string>
#include <map>
class confval {
private:
bool bool_val;
uint32_t uint_val;
std::string str_val;
enum {
CONF_NONEXISTENT,
CONF_BOOL,
CONF_UINT,
CONF_STR,
} val_type;
public:
confval();
confval(bool value);
confval(uint32_t value);
confval(const char * value);
uint32_t get_uint();
bool get_bool();
std::string get_str();
void set(const std::string &val);
private:
bool bool_val;
uint32_t uint_val;
std::string str_val;
enum {
CONF_NONEXISTENT,
CONF_BOOL,
CONF_UINT,
CONF_STR,
} val_type;
public:
confval();
confval(bool value);
confval(uint32_t value);
confval(const char * value);
uint32_t get_uint();
bool get_bool();
std::string get_str();
void set(const std::string &val);
};
class config {
private:
template <typename T> void add(const std::string &setting_name, T value);
std::string trim(const std::string str);
void init();
confval * get(const std::string &setting_name);
std::map<std::string, confval> settings;
confval * dummy_setting;
public:
config();
void load(std::istream &conf_file);
void load(const std::string &conf_file_path, std::istream &conf_file);
void reload();
bool get_bool(const std::string &setting_name);
uint32_t get_uint(const std::string &setting_name);
std::string get_str(const std::string &setting_name);
void set(const std::string &setting_name, const std::string &value);
private:
template <typename T> void add(const std::string &setting_name, T value);
std::string trim(const std::string str);
void init();
confval * get(const std::string &setting_name);
std::map<std::string, confval> settings;
confval * dummy_setting;
public:
config();
void load(std::istream &conf_file);
void load(const std::string &conf_file_path, std::istream &conf_file);
void reload();
bool get_bool(const std::string &setting_name);
uint32_t get_uint(const std::string &setting_name);
std::string get_str(const std::string &setting_name);
void set(const std::string &setting_name, const std::string &value);
};
template <typename T> void config::add(const std::string &setting_name, T value) {
confval setting(value);
settings[setting_name] = setting;
confval setting(value);
settings[setting_name] = setting;
}
#endif
#endif // SRC_CONFIG_H_
+561 -532
View File
File diff suppressed because it is too large. Load diff
+77 -61
View File
@@ -1,86 +1,102 @@
#ifndef OCELOT_DB_H
#define OCELOT_DB_H
#ifndef SRC_DB_H_
#define SRC_DB_H_
// Copyright [2017-2024] Orpheus
#pragma GCC visibility push(default)
#include <mysql++/mysql++.h>
#include <spdlog/spdlog.h>
#include <string>
#include <unordered_map>
#include <queue>
#include <mutex>
#include <memory>
#include <vector>
#include "config.h"
class mysql {
private:
mysqlpp::Connection conn;
std::string update_user_buffer;
std::string update_torrent_buffer;
std::string update_heavy_peer_buffer;
std::string update_light_peer_buffer;
std::string update_snatch_buffer;
std::string update_token_buffer;
private:
mysqlpp::Connection conn;
std::string update_user_buffer;
std::string update_torrent_buffer;
std::string update_heavy_peer_buffer;
std::string update_light_peer_buffer;
std::string update_snatch_buffer;
std::string update_token_buffer;
std::queue<std::string> user_queue;
std::queue<std::string> torrent_queue;
std::queue<std::string> peer_queue;
std::queue<std::string> snatch_queue;
std::queue<std::string> token_queue;
std::queue<std::string> user_queue;
std::queue<std::string> torrent_queue;
std::queue<std::string> peer_queue;
std::queue<std::string> snatch_queue;
std::queue<std::string> token_queue;
std::string mysql_db, mysql_host, mysql_username, mysql_password;
bool u_active, t_active, p_active, s_active, tok_active;
bool readonly;
std::string mysql_db, mysql_host, mysql_username, mysql_password;
unsigned int mysql_port;
bool u_active, t_active, p_active, s_active, tok_active;
bool readonly;
// These locks prevent more than one thread from reading/writing the buffers.
// These should be held for the minimum time possible.
std::mutex user_queue_lock;
std::mutex torrent_buffer_lock;
std::mutex torrent_queue_lock;
std::mutex peer_queue_lock;
std::mutex snatch_queue_lock;
std::mutex token_queue_lock;
// These locks prevent more than one thread from reading/writing the buffers.
// These should be held for the minimum time possible.
std::mutex user_queue_lock;
std::mutex torrent_buffer_lock;
std::mutex torrent_queue_lock;
std::mutex peer_queue_lock;
std::mutex snatch_queue_lock;
std::mutex token_queue_lock;
std::shared_ptr<spdlog::logger> logger;
std::shared_ptr<spdlog::logger> logger;
void load_config(config * conf);
void load_tokens(torrent_list &torrents);
void load_config(config * conf);
void load_tokens(torrent_list &torrents);
mysqlpp::Connection create_connection();
void do_flush_users();
void do_flush_torrents();
void do_flush_snatches();
void do_flush_peers();
void do_flush_tokens();
void do_flush_users();
void do_flush_torrents();
void do_flush_snatches();
void do_flush_peers();
void do_flush_tokens();
void flush_users();
void flush_torrents();
void flush_snatches();
void flush_peers();
void flush_tokens();
void clear_peer_data();
void flush_users();
void flush_torrents();
void flush_snatches();
void flush_peers();
void flush_tokens();
void clear_peer_data();
public:
bool verbose_flush;
public:
bool verbose_flush;
mysql(config * conf);
void reload_config(config * conf);
bool connected();
void load_torrents(torrent_list &torrents);
void load_users(user_list &users);
void load_whitelist(std::vector<std::string> &whitelist);
mysql(config * conf);
void reload_config(config * conf);
void flush();
bool connected();
bool all_clear();
void load_torrents(torrent_list &torrents);
void load_users(user_list &users);
void load_whitelist(std::vector<std::string> &whitelist);
void record_user(const std::string &record); // (id,uploaded_change,downloaded_change)
void record_torrent(const std::string &record); // (id,seeders,leechers,snatched_change,balance)
void record_snatch(const std::string &record, const std::string &ip); // (uid,fid,tstamp)
void record_peer(const std::string &record, const std::string &ip, const std::string &peer_id, const std::string &useragent); // (uid,fid,active,peerid,useragent,ip,uploaded,downloaded,upspeed,downspeed,left,timespent,announces,tstamp)
void record_peer(const std::string &record, const std::string &peer_id); // (fid,peerid,timespent,announces,tstamp)
void record_token(const std::string &record);
// (id,uploaded_change,downloaded_change)
void record_user(const std::string &record);
void flush();
// (id,seeders,leechers,snatched_change,balance)
void record_torrent(const std::string &record);
bool all_clear();
// (uid,fid,tstamp)
void record_snatch(const std::string &record, const std::string &ip);
std::mutex torrent_list_mutex;
std::mutex user_list_mutex;
std::mutex whitelist_mutex;
// (uid,fid,active,peerid,useragent,ip,uploaded,downloaded,upspeed,downspeed,left,timespent,announces,tstamp)
void record_peer(const std::string &record, const std::string &ip, const std::string &peer_id, const std::string &useragent);
// (fid,peerid,timespent,announces,tstamp)
void record_peer(const std::string &record, const std::string &peer_id);
void record_token(const std::string &record);
std::mutex torrent_list_mutex;
std::mutex user_list_mutex;
std::mutex whitelist_mutex;
};
#pragma GCC visibility pop
#endif
#endif // SRC_DB_H_
+179 -170
View File
@@ -1,5 +1,9 @@
#include <cerrno>
// Copyright [2017-2024] Orpheus
#include <spdlog/spdlog.h>
#include <cerrno>
#include "ocelot.h"
#include "config.h"
#include "db.h"
@@ -8,237 +12,242 @@
#include "response.h"
#include "events.h"
// Define the connection mother (first half) and connection middlemen (second half)
std::mutex peak_open_mutex;
//TODO Better errors
// Define the connection mother (first half) and connection middlemen (second half)
//---------- Connection mother - spawns middlemen and lets them deal with the connection
connection_mother::connection_mother(config * conf, worker * worker_obj, mysql * db_obj, site_comm * sc_obj, schedule * sched) : work(worker_obj), db(db_obj) {
logger = spdlog::get("logger");
logger = spdlog::get("logger");
// Handle config stuff first
load_config(conf);
// Handle config stuff first
load_config(conf);
listen_socket = create_listen_socket();
listen_socket = create_listen_socket();
// We failed to create the socket, so no point in running Ocelot
if (listen_socket == 0) {
logger->critical("Failed to create socket for Ocelot. Exiting.");
exit(1);
}
// We failed to create the socket, so no point in running Ocelot
if (listen_socket == 0) {
logger->critical("Failed to create socket for Ocelot. Exiting.");
exit(1);
}
listen_event.set<connection_mother, &connection_mother::handle_connect>(this);
listen_event.start(listen_socket, ev::READ);
// Create libev timer
schedule_event.set<schedule, &schedule::handle>(sched);
schedule_event.start(sched->schedule_interval, sched->schedule_interval); // After interval, every interval
listen_event.set<connection_mother, &connection_mother::handle_connect>(this);
listen_event.start(listen_socket, ev::READ);
// Create libev timer
schedule_event.set<schedule, &schedule::handle>(sched);
schedule_event.start(sched->schedule_interval, sched->schedule_interval); // After interval, every interval
}
void connection_mother::load_config(config * conf) {
listen_port = conf->get_uint("listen_port");
max_connections = conf->get_uint("max_connections");
max_middlemen = conf->get_uint("max_middlemen");
connection_timeout = conf->get_uint("connection_timeout");
keepalive_timeout = conf->get_uint("keepalive_timeout");
max_read_buffer = conf->get_uint("max_read_buffer");
max_request_size = conf->get_uint("max_request_size");
listen_port = conf->get_uint("listen_port");
max_connections = conf->get_uint("max_connections");
max_middlemen = conf->get_uint("max_middlemen");
connection_timeout = conf->get_uint("connection_timeout");
keepalive_timeout = conf->get_uint("keepalive_timeout");
max_read_buffer = conf->get_uint("max_read_buffer");
max_request_size = conf->get_uint("max_request_size");
}
void connection_mother::reload_config(config * conf) {
unsigned int old_listen_port = listen_port;
unsigned int old_max_connections = max_connections;
load_config(conf);
if (old_listen_port != listen_port) {
logger->info("Changing listen port from " + std::to_string(old_listen_port) +" to " + std::to_string(listen_port));
int new_listen_socket = create_listen_socket();
if (new_listen_socket != 0) {
listen_event.stop();
listen_event.start(new_listen_socket, ev::READ);
close(listen_socket);
listen_socket = new_listen_socket;
} else {
logger->error("Couldn't create new listen socket when reloading config");
}
} else if (old_max_connections != max_connections) {
listen(listen_socket, max_connections);
}
unsigned int old_listen_port = listen_port;
unsigned int old_max_connections = max_connections;
load_config(conf);
if (old_listen_port != listen_port) {
logger->info("Changing listen port from " + std::to_string(old_listen_port) +" to " + std::to_string(listen_port));
int new_listen_socket = create_listen_socket();
if (new_listen_socket != 0) {
listen_event.stop();
listen_event.start(new_listen_socket, ev::READ);
close(listen_socket);
listen_socket = new_listen_socket;
} else {
logger->error("Couldn't create new listen socket when reloading config");
}
} else if (old_max_connections != max_connections) {
listen(listen_socket, max_connections);
}
}
int connection_mother::create_listen_socket() {
sockaddr_in address;
memset(&address, 0, sizeof(address));
int new_listen_socket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in address;
memset(&address, 0, sizeof(address));
int new_listen_socket = socket(AF_INET, SOCK_STREAM, 0);
// Stop old sockets from hogging the port
int yes = 1;
if (setsockopt(new_listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
logger->error("Could not reuse socket: " + std::string(strerror(errno)));
return 0;
}
// Stop old sockets from hogging the port
int yes = 1;
if (setsockopt(new_listen_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
logger->error("Could not reuse socket: " + std::string(strerror(errno)));
return 0;
}
// Get ready to bind
address.sin_family = AF_INET;
//address.sin_addr.s_addr = inet_addr(conf->host.c_str()); // htonl(INADDR_ANY)
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(listen_port);
// Get ready to bind
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(listen_port);
// Bind
if (bind(new_listen_socket, (sockaddr *) &address, sizeof(address)) == -1) {
logger->error("Bind failed: " + std::string(strerror(errno)));
return 0;
}
// Bind
if (bind(new_listen_socket, (sockaddr *) &address, sizeof(address)) == -1) {
logger->error("Bind failed: " + std::string(strerror(errno)));
return 0;
}
// Listen
if (listen(new_listen_socket, max_connections) == -1) {
logger->error("Listen failed: " + std::string(strerror(errno)));
return 0;
}
// Listen
if (listen(new_listen_socket, max_connections) == -1) {
logger->error("Listen failed: " + std::string(strerror(errno)));
return 0;
}
// Set non-blocking
int flags = fcntl(new_listen_socket, F_GETFL);
if (flags == -1) {
logger->error("Could not get socket flags: " + std::string(strerror(errno)));
return 0;
}
if (fcntl(new_listen_socket, F_SETFL, flags | O_NONBLOCK) == -1) {
logger->error("Could not set non-blocking: " + std::string(strerror(errno)));
return 0;
}
// Set non-blocking
int flags = fcntl(new_listen_socket, F_GETFL);
if (flags == -1) {
logger->error("Could not get socket flags: " + std::string(strerror(errno)));
return 0;
}
if (fcntl(new_listen_socket, F_SETFL, flags | O_NONBLOCK) == -1) {
logger->error("Could not set non-blocking: " + std::string(strerror(errno)));
return 0;
}
return new_listen_socket;
return new_listen_socket;
}
void connection_mother::run() {
logger->info("Sockets up on port " + std::to_string(listen_port) + ", starting event loop!");
ev_loop(ev_default_loop(0), 0);
logger->info("Sockets up on port " + std::to_string(listen_port) + ", starting event loop!");
ev_loop(ev_default_loop(0), 0);
}
void connection_mother::handle_connect(ev::io &watcher, int events_flags) {
// Spawn a new middleman
if (stats.open_connections < max_middlemen) {
stats.opened_connections++;
stats.open_connections++;
new connection_middleman(listen_socket, work, this);
}
// Spawn a new middleman
if (stats.open_connections < max_middlemen) {
stats.opened_connections++;
{
const std::lock_guard<std::mutex> lock(peak_open_mutex);
unsigned int current_open = stats.open_connections++;
if (stats.peak_connections < current_open) {
stats.peak_connections = current_open;
}
}
new connection_middleman(listen_socket, work, this);
}
}
connection_mother::~connection_mother()
{
close(listen_socket);
close(listen_socket);
}
//---------- Connection middlemen - these little guys live until their connection is closed
connection_middleman::connection_middleman(int &listen_socket, worker * new_work, connection_mother * mother_arg) :
written(0), mother(mother_arg), work(new_work)
written(0), mother(mother_arg), work(new_work)
{
auto logger = spdlog::get("logger");
connect_sock = accept(listen_socket, NULL, NULL);
if (connect_sock == -1) {
logger->error("Accept failed, errno " + std::to_string(errno) + ": " + std::string(strerror(errno)));
delete this;
return;
}
auto logger = spdlog::get("logger");
connect_sock = accept(listen_socket, NULL, NULL);
if (connect_sock == -1) {
logger->error("Accept failed, errno " + std::to_string(errno) + ": " + std::string(strerror(errno)));
delete this;
return;
}
// Set non-blocking
int flags = fcntl(connect_sock, F_GETFL);
if (flags == -1) {
logger->warn("Could not get connect socket flags");
}
if (fcntl(connect_sock, F_SETFL, flags | O_NONBLOCK) == -1) {
logger->warn("Could not set non-blocking");
}
// Set non-blocking
int flags = fcntl(connect_sock, F_GETFL);
if (flags == -1) {
logger->warn("Could not get connect socket flags");
}
if (fcntl(connect_sock, F_SETFL, flags | O_NONBLOCK) == -1) {
logger->warn("Could not set non-blocking");
}
// Get their info
request.reserve(mother->max_read_buffer);
written = 0;
// Get their info
request.reserve(mother->max_read_buffer);
written = 0;
read_event.set<connection_middleman, &connection_middleman::handle_read>(this);
read_event.start(connect_sock, ev::READ);
read_event.set<connection_middleman, &connection_middleman::handle_read>(this);
read_event.start(connect_sock, ev::READ);
// Let the socket timeout in timeout_interval seconds
timeout_event.set<connection_middleman, &connection_middleman::handle_timeout>(this);
timeout_event.set(mother->connection_timeout, mother->keepalive_timeout);
timeout_event.start();
// Let the socket timeout in timeout_interval seconds
timeout_event.set<connection_middleman, &connection_middleman::handle_timeout>(this);
timeout_event.set(mother->connection_timeout, mother->keepalive_timeout);
timeout_event.start();
}
connection_middleman::~connection_middleman() {
close(connect_sock);
stats.open_connections--;
close(connect_sock);
stats.open_connections--;
}
// Handler to read data from the socket, called by event loop when socket is readable
void connection_middleman::handle_read(ev::io &watcher, int events_flags) {
char buffer[mother->max_read_buffer + 1];
memset(buffer, 0, mother->max_read_buffer + 1);
int ret = recv(connect_sock, &buffer, mother->max_read_buffer, 0);
char buffer[mother->max_read_buffer + 1];
memset(buffer, 0, mother->max_read_buffer + 1);
int ret = recv(connect_sock, &buffer, mother->max_read_buffer, 0);
if (ret <= 0) {
delete this;
return;
}
stats.bytes_read += ret;
request.append(buffer, ret);
size_t request_size = request.size();
if (request_size > mother->max_request_size || (request_size >= 4 && request.compare(request_size - 4, std::string::npos, "\r\n\r\n") == 0)) {
stats.requests++;
read_event.stop();
client_opts.gzip = false;
client_opts.html = false;
client_opts.http_close = true;
if (ret <= 0) {
delete this;
return;
}
stats.bytes_read += ret;
request.append(buffer, ret);
size_t request_size = request.size();
if (request_size > mother->max_request_size || (request_size >= 4 && request.compare(request_size - 4, std::string::npos, "\r\n\r\n") == 0)) {
stats.requests++;
read_event.stop();
client_opts.gzip = false;
client_opts.html = false;
client_opts.http_close = true;
if (request_size > mother->max_request_size) {
shutdown(connect_sock, SHUT_RD);
response = error("GET string too long", client_opts);
} else {
char ip[INET_ADDRSTRLEN];
sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
getpeername(connect_sock, (sockaddr *) &client_addr, &addr_len);
inet_ntop(AF_INET, &(client_addr.sin_addr), ip, INET_ADDRSTRLEN);
std::string ip_str = ip;
if (request_size > mother->max_request_size) {
shutdown(connect_sock, SHUT_RD);
response = error("GET string too long", client_opts);
} else {
char ip[INET_ADDRSTRLEN];
sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
getpeername(connect_sock, (sockaddr *) &client_addr, &addr_len);
inet_ntop(AF_INET, &(client_addr.sin_addr), ip, INET_ADDRSTRLEN);
std::string ip_str = ip;
//--- CALL WORKER
response = work->work(request, ip_str, client_opts);
request.clear();
request_size = 0;
}
//--- CALL WORKER
response = work->work(request, ip_str, client_opts);
request.clear();
request_size = 0;
}
// Find out when the socket is writeable.
// The loop in connection_mother will call handle_write when it is.
write_event.set<connection_middleman, &connection_middleman::handle_write>(this);
write_event.start(connect_sock, ev::WRITE);
}
// Find out when the socket is writeable.
// The loop in connection_mother will call handle_write when it is.
write_event.set<connection_middleman, &connection_middleman::handle_write>(this);
write_event.start(connect_sock, ev::WRITE);
}
}
// Handler to write data to the socket, called by event loop when socket is writeable
void connection_middleman::handle_write(ev::io &watcher, int events_flags) {
int ret = send(connect_sock, response.c_str()+written, response.size()-written, MSG_NOSIGNAL);
if (ret == -1) {
return;
}
stats.bytes_written += ret;
written += ret;
if (written == response.size()) {
write_event.stop();
if (client_opts.http_close) {
timeout_event.stop();
delete this;
return;
}
timeout_event.again();
read_event.start();
response.clear();
written = 0;
}
int ret = send(connect_sock, response.c_str()+written, response.size()-written, MSG_NOSIGNAL);
if (ret == -1) {
return;
}
stats.bytes_written += ret;
written += ret;
if (written == response.size()) {
write_event.stop();
if (client_opts.http_close) {
timeout_event.stop();
delete this;
return;
}
timeout_event.again();
read_event.start();
response.clear();
written = 0;
}
}
// After a middleman has been alive for timout_interval seconds, this is called
void connection_middleman::handle_timeout(ev::timer &watcher, int events_flags) {
timeout_event.stop();
read_event.stop();
write_event.stop();
delete this;
timeout_event.stop();
read_event.stop();
write_event.stop();
delete this;
}
+72 -70
View File
@@ -1,16 +1,30 @@
#include <iostream>
#include <string>
#include <cstring>
#ifndef SRC_EVENTS_H_
#define SRC_EVENTS_H_
// Copyright [2017-2024] Orpheus
#ifdef EV_ERROR
#undef EV_ERROR
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0x2000 /* don't raise SIGPIPE */
#endif
// Sockets
#include <arpa/inet.h>
#include <fcntl.h>
#include <spdlog/spdlog.h>
#include <sys/socket.h>
#include <unistd.h>
// libev
#include <ev++.h>
// Sockets
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <cstring>
#include <memory>
#include <string>
#include "config.h"
#include "worker.h"
@@ -18,88 +32,76 @@
#include "db.h"
#include "site_comm.h"
/*
TODO find out what these do
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
*/
/*
We have three classes - the mother, the middlemen, and the worker
THE MOTHER
The mother is called when a client opens a connection to the server.
It creates a middleman for every new connection, which will be called
when its socket is ready for reading.
The mother is called when a client opens a connection to the server.
It creates a middleman for every new connection, which will be called
when its socket is ready for reading.
THE MIDDLEMEN
Each middleman hang around until data is written to its socket. It then
reads the data and sends it to the worker. When it gets the response, it
gets called to write its data back to the client.
Each middleman hang around until data is written to its socket. It then
reads the data and sends it to the worker. When it gets the response, it
gets called to write its data back to the client.
THE WORKER
The worker gets data from the middleman, and returns the response. It
doesn't concern itself with silly things like sockets.
The worker gets data from the middleman, and returns the response. It
doesn't concern itself with silly things like sockets.
see worker.h for the worker.
see worker.h for the worker.
*/
// THE MOTHER - Spawns connection middlemen
class connection_mother {
private:
void load_config(config * conf);
unsigned int listen_port;
unsigned int max_connections;
private:
void load_config(config * conf);
unsigned int listen_port;
unsigned int max_connections;
int listen_socket;
worker * work;
mysql * db;
ev::io listen_event;
ev::timer schedule_event;
std::shared_ptr<spdlog::logger> logger;
int listen_socket;
worker * work;
mysql * db;
ev::io listen_event;
ev::timer schedule_event;
std::shared_ptr<spdlog::logger> logger;
public:
connection_mother(config * conf, worker * worker_obj, mysql * db_obj, site_comm * sc_obj, schedule * sched_obj);
~connection_mother();
void reload_config(config * conf);
int create_listen_socket();
void run();
void handle_connect(ev::io &watcher, int events_flags);
public:
connection_mother(config * conf, worker * worker_obj, mysql * db_obj, site_comm * sc_obj, schedule * sched_obj);
~connection_mother();
void reload_config(config * conf);
int create_listen_socket();
void run();
void handle_connect(ev::io &watcher, int events_flags);
unsigned int max_middlemen;
unsigned int connection_timeout;
unsigned int keepalive_timeout;
unsigned int max_read_buffer;
unsigned int max_request_size;
unsigned int max_middlemen;
unsigned int connection_timeout;
unsigned int keepalive_timeout;
unsigned int max_read_buffer;
unsigned int max_request_size;
};
// THE MIDDLEMAN
// Created by connection_mother
// Add their own watchers to see when sockets become readable
class connection_middleman {
private:
int connect_sock;
client_opts_t client_opts;
unsigned int written;
ev::io read_event;
ev::io write_event;
ev::timer timeout_event;
std::string request;
std::string response;
private:
int connect_sock;
client_opts_t client_opts;
unsigned int written;
ev::io read_event;
ev::io write_event;
ev::timer timeout_event;
std::string request;
std::string response;
connection_mother * mother;
worker * work;
connection_mother * mother;
worker * work;
public:
connection_middleman(int &listen_socket, worker* work, connection_mother * mother_arg);
~connection_middleman();
public:
connection_middleman(int &listen_socket, worker* work, connection_mother * mother_arg);
~connection_middleman();
void handle_read(ev::io &watcher, int events_flags);
void handle_write(ev::io &watcher, int events_flags);
void handle_timeout(ev::timer &watcher, int events_flags);
void handle_read(ev::io &watcher, int events_flags);
void handle_write(ev::io &watcher, int events_flags);
void handle_timeout(ev::timer &watcher, int events_flags);
};
#endif // SRC_EVENTS_H_
+200
View File
@@ -0,0 +1,200 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jemalloc_parse.h"
/* parse a size_t decimal text representation */
const char *parse_sz(const char *in, const char *find, size_t *target) {
const char *p = strstr(in, find);
if (!p) {
// didn't find what we were looking for
return NULL;
}
p += strlen(find);
// copy the digits to a null-terminated string in order to pass it to strtoul()
// the largest unsigned long decimal representation is 4294967295 (10 bytes)
char convert[11];
char *c = convert;
while (isspace(*p)) {
p++;
}
while (isdigit(*p) && c < convert + sizeof(convert) - 1) {
*c++ = *p++;
}
*c = '\0';
*target = strtoul(convert, &c, 10);
return p + 1; // one past the last digit
}
/* parse an unsigned long long decimal text representation */
const char *parse_ull(const char *in, const char *find, unsigned long long *target) {
const char *p = strstr(in, find);
if (!p) {
// didn't find what we were looking for
return NULL;
}
p += strlen(find);
// copy the digits to a null-terminated string in order to pass it to strtoull()
// the largest unsigned long long decimal representation is 18446744073709551615 (21 bytes)
char convert[22];
char *c = convert;
while (isspace(*p)) {
p++;
}
while(isdigit(*p) && c < convert + sizeof(convert) - 1) {
*c++ = *p++;
}
*c = '\0';
*target = strtoull(convert, &c, 10);
return p + 1; // one past the last digit
}
int jemalloc_parse(const char *in, struct ocelot_alloc_info *out) {
/* Parse the output of jemalloc_status() plain output
* This is an ugly hack; it would be faster to build directly what we want
* rather than walk down a formatted string that has generated lots of
* information that is discarded.
* If the input breaks, the error code indicates where the parsing failed.
*/
// set everything to zero
memset (out, 0, sizeof(struct ocelot_alloc_info));
/*
___ Begin jemalloc statistics ___
Version: "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c"
Build-time option settings
...
Run-time option settings
...
Profiling settings
...
Arenas: 17
Quantum size: 16
Page size: 4096
Maximum thread-cached size class: 32768
Number of bin size classes: 36
Number of thread-cache bin size classes: 41
Number of large size classes: 196
*/
if (!(in = strstr(in, "___ Begin jemalloc statistics ___"))) {
return 1;
}
if (!(in = parse_sz(in, "Arenas: ", &out->nr_arena))) {
return 10;
}
if (!(in = parse_sz(in, "Number of bin size classes: ", &out->nr_bin_small))) {
return 11;
}
if (!(in = parse_sz(in, "Number of thread-cache bin size classes: ", &out->nr_bin_tc))) {
return 12;
}
if (!(in = parse_sz(in, "Number of large size classes: ", &out->nr_bin_large))) {
return 13;
}
// Allocated: 895744, active: 1024000, metadata: 3047664 (n_thp 0), resident: 3985408, mapped: 7315456, retained: 1073152
if (!(in = parse_ull(in, "Allocated: ", &out->mem_allocated))) {
return 20;
}
if (!(in = parse_ull(in, "active: ", &out->mem_active))) {
return 21;
}
if (!(in = parse_ull(in, "metadata: ", &out->mem_metadata))) {
return 22;
}
if (!(in = parse_ull(in, "resident: ", &out->mem_resident))) {
return 23;
}
if (!(in = parse_ull(in, "mapped: ", &out->mem_mapped))) {
return 24;
}
if (!(in = parse_ull(in, "retained: ", &out->mem_retained))) {
return 25;
}
/*
allocated nmalloc (#/sec) ndalloc (#/sec) nrequests (#/sec) nfill (#/sec) nflush (#/sec)
small: 247840 131452 0 129036 0 24219 0 2402 0 8543 0
large: 290816 815 0 808 0 971 0 815 0 2351 0
total: 538656 132267 0 129844 0
*/
if (!(in = strstr(in, "(#/sec)\nsmall:"))) {
return 30;
}
if (!(in = parse_sz(in, " ", &out->small.allocated))) {
return 40;
}
if (!(in = parse_sz(in, " ", &out->small.nmalloc_total))) {
return 41;
}
if (!(in = parse_sz(in, " ", &out->small.ndalloc_rate))) {
return 42;
}
if (!(in = parse_sz(in, " ", &out->small.ndalloc_total))) {
return 43;
}
if (!(in = parse_sz(in, " ", &out->small.nrequests_rate))) {
return 44;
}
if (!(in = parse_sz(in, " ", &out->small.nrequests_total))) {
return 45;
}
if (!(in = parse_sz(in, " ", &out->small.nfill_rate))) {
return 46;
}
if (!(in = parse_sz(in, " ", &out->small.nfill_total))) {
return 47;
}
if (!(in = parse_sz(in, " ", &out->small.nflush_rate))) {
return 48;
}
if (!(in = parse_sz(in, " ", &out->small.nflush_total))) {
return 49;
}
if (!(in = strstr(in, "\nlarge:"))) {
return 60;
}
if (!(in = parse_sz(in, " ", &out->large.allocated))) {
return 70;
}
if (!(in = parse_sz(in, " ", &out->large.nmalloc_total))) {
return 71;
}
if (!(in = parse_sz(in, " ", &out->large.ndalloc_rate))) {
return 72;
}
if (!(in = parse_sz(in, " ", &out->large.ndalloc_total))) {
return 73;
}
if (!(in = parse_sz(in, " ", &out->large.nrequests_rate))) {
return 74;
}
if (!(in = parse_sz(in, " ", &out->large.nrequests_total))) {
return 75;
}
if (!(in = parse_sz(in, " ", &out->large.nfill_rate))) {
return 76;
}
if (!(in = parse_sz(in, " ", &out->large.nfill_total))) {
return 77;
}
if (!(in = parse_sz(in, " ", &out->large.nflush_rate))) {
return 78;
}
if (!(in = parse_sz(in, " ", &out->large.nflush_total))) {
return 79;
}
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
#ifndef SRC_PARSE_JEMALLOC_H_
#define SRC_PARSE_JEMALLOC_H_
struct ocelot_alloc_stat {
size_t allocated;
size_t nmalloc_total;
size_t nmalloc_rate;
size_t ndalloc_total;
size_t ndalloc_rate;
size_t nrequests_total;
size_t nrequests_rate;
size_t nfill_total;
size_t nfill_rate;
size_t nflush_total;
size_t nflush_rate;
};
struct ocelot_alloc_info {
size_t nr_arena;
size_t nr_bin_small;
size_t nr_bin_tc;
size_t nr_bin_large;
unsigned long long mem_allocated;
unsigned long long mem_active;
unsigned long long mem_metadata;
unsigned long long mem_resident;
unsigned long long mem_mapped;
unsigned long long mem_retained;
struct ocelot_alloc_stat small;
struct ocelot_alloc_stat large;
};
int jemalloc_parse(const char *in, struct ocelot_alloc_info *out);
#endif // SRC_PARSE_JEMALLOC_H_
+66 -62
View File
@@ -1,81 +1,85 @@
#include <string>
// Copyright [2017-2024] Orpheus
#include <iostream>
#include <sstream>
#include <string>
#include "misc_functions.h"
int32_t strtoint32(const std::string& str) {
std::istringstream stream(str);
int32_t i = 0;
stream >> i;
return i;
std::istringstream stream(str);
int32_t i = 0;
stream >> i;
return i;
}
int64_t strtoint64(const std::string& str) {
std::istringstream stream(str);
int64_t i = 0;
stream >> i;
return i;
std::istringstream stream(str);
int64_t i = 0;
stream >> i;
return i;
}
std::string inttostr(const int i) {
std::string str;
std::stringstream out;
out << i;
str = out.str();
return str;
std::string str;
std::stringstream out;
out << i;
str = out.str();
return str;
}
std::string hex_decode(const std::string &in) {
std::string out;
out.reserve(20);
unsigned int in_length = in.length();
for (unsigned int i = 0; i < in_length; i++) {
unsigned char x = '0';
if (in[i] == '%' && (i + 2) < in_length) {
i++;
if (in[i] >= 'a' && in[i] <= 'f') {
x = static_cast<unsigned char>((in[i]-87) << 4);
} else if (in[i] >= 'A' && in[i] <= 'F') {
x = static_cast<unsigned char>((in[i]-55) << 4);
} else if (in[i] >= '0' && in[i] <= '9') {
x = static_cast<unsigned char>((in[i]-48) << 4);
}
std::string out;
out.reserve(20);
unsigned int in_length = in.length();
for (unsigned int i = 0; i < in_length; i++) {
unsigned char x = '0';
if (in[i] == '%' && (i + 2) < in_length) {
i++;
if (in[i] >= 'a' && in[i] <= 'f') {
x = static_cast<unsigned char>((in[i]-87) << 4);
} else if (in[i] >= 'A' && in[i] <= 'F') {
x = static_cast<unsigned char>((in[i]-55) << 4);
} else if (in[i] >= '0' && in[i] <= '9') {
x = static_cast<unsigned char>((in[i]-48) << 4);
}
i++;
if (in[i] >= 'a' && in[i] <= 'f') {
x += static_cast<unsigned char>(in[i]-87);
} else if (in[i] >= 'A' && in[i] <= 'F') {
x += static_cast<unsigned char>(in[i]-55);
} else if (in[i] >= '0' && in[i] <= '9') {
x += static_cast<unsigned char>(in[i]-48);
}
} else {
x = in[i];
}
out.push_back(x);
}
return out;
i++;
if (in[i] >= 'a' && in[i] <= 'f') {
x += static_cast<unsigned char>(in[i]-87);
} else if (in[i] >= 'A' && in[i] <= 'F') {
x += static_cast<unsigned char>(in[i]-55);
} else if (in[i] >= '0' && in[i] <= '9') {
x += static_cast<unsigned char>(in[i]-48);
}
} else {
x = in[i];
}
out.push_back(x);
}
return out;
}
std::string bintohex(const std::string &in) {
std::string out;
size_t length = in.length();
out.reserve(2*length);
for (unsigned int i = 0; i < length; i++) {
unsigned char x = static_cast<unsigned char>((in[i] & 0xF0) >> 4);
if (x > 9) {
x += 'a' - 10;
} else {
x += '0';
}
out.push_back(x);
x = in[i] & 0x0F;
if (x > 9) {
x += 'a' - 10;
} else {
x += '0';
}
out.push_back(x);
}
return out;
std::string out;
size_t length = in.length();
out.reserve(2*length);
for (unsigned int i = 0; i < length; i++) {
unsigned char x = static_cast<unsigned char>((in[i] & 0xF0) >> 4);
if (x > 9) {
x += 'a' - 10;
} else {
x += '0';
}
out.push_back(x);
x = in[i] & 0x0F;
if (x > 9) {
x += 'a' - 10;
} else {
x += '0';
}
out.push_back(x);
}
return out;
}
+6 -3
View File
@@ -1,5 +1,8 @@
#ifndef MISC_FUNCTIONS__H
#define MISC_FUNCTIONS__H
#ifndef SRC_MISC_FUNCTIONS_H_
#define SRC_MISC_FUNCTIONS_H_
// Copyright [2017-2024] Orpheus
#include <string>
int32_t strtoint32(const std::string& str);
@@ -8,4 +11,4 @@ std::string inttostr(int i);
std::string hex_decode(const std::string &in);
std::string bintohex(const std::string &in);
#endif
#endif // SRC_MISC_FUNCTIONS_H_
+167 -151
View File
@@ -1,12 +1,16 @@
// Copyright [2017-2024] Orpheus
#include <sys/stat.h>
#include <syslog.h>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/sinks/stdout_sinks.h>
#include <fstream>
#include <iostream>
#include <csignal>
#include <thread>
#include <sys/stat.h>
#include <syslog.h>
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/stdout_sinks.h"
#include "ocelot.h"
#include "config.h"
#include "db.h"
@@ -22,183 +26,195 @@ static schedule *sched;
struct stats_t stats;
static void create_daemon()
{
pid_t pid;
static void create_daemon() {
pid_t pid;
/* Fork off the parent process */
pid = fork();
/* Fork off the parent process */
pid = fork();
/* An error occurred */
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* An error occurred */
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* Success: Let the parent terminate */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* Success: Let the parent terminate */
if (pid > 0) {
exit(EXIT_SUCCESS);
}
/* On success: The child process becomes session leader */
if (setsid() < 0)
exit(EXIT_FAILURE);
/* On success: The child process becomes session leader */
if (setsid() < 0)
exit(EXIT_FAILURE);
/* Set new file permissions */
umask(0);
/* Set new file permissions */
umask(0);
/* Change the working directory to the root directory */
/* or another appropriated directory */
if (chdir("/") < 0) {
exit(EXIT_FAILURE);
}
/* Change the working directory to the root directory */
/* or another appropriated directory */
if (chdir("/") < 0) {
exit(EXIT_FAILURE);
}
/* Close all open file descriptors */
int x;
for (x = static_cast<int>(sysconf(_SC_OPEN_MAX)); x >= 0; x--) {
close (x);
}
/* Close all open file descriptors */
int x;
for (x = static_cast<int>(sysconf(_SC_OPEN_MAX)); x >= 0; x--) {
close(x);
}
/* Open the log file */
openlog("ocelot", LOG_PID, LOG_DAEMON);
/* Open the log file */
openlog("ocelot", LOG_PID, LOG_DAEMON);
}
static void sig_handler(int sig) {
std::shared_ptr<spdlog::logger> logger = spdlog::get("logger");
if (sig == SIGINT || sig == SIGTERM) {
logger->info("Caught SIGINT/SIGTERM");
if (work->shutdown()) {
exit(0);
}
} else if (sig == SIGHUP) {
logger->info("Reloading config");
logger->flush();
conf->reload();
db->reload_config(conf);
mother->reload_config(conf);
sc->reload_config(conf);
sched->reload_config(conf);
work->reload_config(conf);
logger->info("Done reloading config");
} else if (sig == SIGUSR1) {
logger->info("Reloading from database");
std::thread w_thread(&worker::reload_lists, work);
w_thread.detach();
}
std::shared_ptr<spdlog::logger> logger = spdlog::get("logger");
if (sig == SIGINT || sig == SIGTERM) {
logger->info("Caught SIGINT/SIGTERM");
if (work->shutdown()) {
exit(0);
}
} else if (sig == SIGHUP) {
logger->info("Reloading config");
logger->flush();
conf->reload();
db->reload_config(conf);
mother->reload_config(conf);
sc->reload_config(conf);
sched->reload_config(conf);
work->reload_config(conf);
logger->info("Done reloading config");
} else if (sig == SIGUSR1) {
logger->info("Reloading from database");
std::thread w_thread(&worker::reload_lists, work);
w_thread.detach();
}
}
int main(int argc, char **argv) {
// we don't use printf so make cout/cerr a little bit faster
std::ios_base::sync_with_stdio(false);
// we don't use printf so make cout/cerr a little bit faster
std::ios_base::sync_with_stdio(false);
conf = new config();
conf = new config();
bool verbose = false, conf_arg = false, daemonize = false;
std::string conf_file_path("./ocelot.conf");
bool conf_arg = false;
bool daemonize = false;
bool verbose = false;
std::string conf_file_path("./ocelot.conf");
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
verbose = true;
}
else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--daemonize") == 0) {
daemonize = true;
}
else if (strcmp(argv[i], "-c") == 0 && i < argc - 1) {
conf_arg = true;
conf_file_path = argv[++i];
}
else if(strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
std::cout << "Ocelot, version 1.1" << std::endl;
return 0;
}
else {
std::cout << "Usage: " << argv[0] << " [-v] [-c configfile]" << std::endl;
return 0;
}
}
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) {
verbose = true;
} else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--daemonize") == 0) {
daemonize = true;
} else if (strcmp(argv[i], "-c") == 0 && i < argc - 1) {
conf_arg = true;
conf_file_path = argv[++i];
} else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
// preprocessor concatenation
std::cout << "Ocelot version " OCELOT_VERSION ", compiled " __DATE__ " " __TIME__ << std::endl;
return 0;
} else {
std::cout << "Usage: " << argv[0] << " [-v] [-c configfile] [--daemonize]" << std::endl;
return 0;
}
}
std::ifstream conf_file(conf_file_path);
if (conf_file.fail()) {
std::cout << "Using default config because '" << conf_file_path << "' couldn't be opened" << std::endl;
if (!conf_arg) {
std::cout << "Start Ocelot with -c <path> to specify config file if necessary" << std::endl;
}
}
else {
conf->load(conf_file_path, conf_file);
}
std::ifstream conf_file(conf_file_path);
if (conf_file.fail()) {
std::cout << "Using default config because '" << conf_file_path << "' couldn't be opened" << std::endl;
if (!conf_arg) {
std::cout << "Start Ocelot with -c <path> to specify config file if necessary" << std::endl;
}
} else {
conf->load(conf_file_path, conf_file);
}
if (conf->get_bool("daemonize") || daemonize) {
create_daemon();
}
if (conf->get_bool("daemonize") || daemonize) {
create_daemon();
}
std::vector<spdlog::sink_ptr> sinks;
if (!conf->get_bool("daemonize") && !daemonize) {
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
}
if (conf->get_bool("log") && !conf->get_str("log_path").empty()) {
sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_mt>(conf->get_str("log_path"), 23, 59));
}
std::vector<spdlog::sink_ptr> sinks;
if (!conf->get_bool("daemonize") && !daemonize) {
sinks.push_back(std::make_shared<spdlog::sinks::stdout_sink_mt>());
}
if (conf->get_bool("log") && !conf->get_str("log_path").empty()) {
sinks.push_back(std::make_shared<spdlog::sinks::daily_file_sink_mt>(conf->get_str("log_path"), 23, 59));
}
auto combined_logger = std::make_shared<spdlog::logger>("logger", begin(sinks), end(sinks));
// If we don't set flush on info, the file log takes a long while to actually flush
combined_logger->flush_on(spdlog::level::info);
spdlog::register_logger(combined_logger);
auto combined_logger = std::make_shared<spdlog::logger>("logger", begin(sinks), end(sinks));
// If we don't set flush on info, the file log takes a long while to actually flush
combined_logger->flush_on(spdlog::level::info);
combined_logger->info(
"Ocelot version " OCELOT_VERSION ", compiled " __DATE__ " " __TIME__
);
spdlog::register_logger(combined_logger);
db = new mysql(conf);
db = new mysql(conf);
if (!db->connected()) {
combined_logger->critical("Could not connect to DB. Exiting!");
return 0;
}
db->verbose_flush = verbose;
if (!db->connected()) {
combined_logger->critical("Could not connect to DB. Exiting!");
return 0;
}
db->verbose_flush = verbose;
sc = new site_comm(conf);
sc->verbose_flush = verbose;
sc = new site_comm(conf);
sc->verbose_flush = verbose;
user_list users_list;
torrent_list torrents_list;
std::vector<std::string> whitelist;
db->load_users(users_list);
db->load_torrents(torrents_list);
db->load_whitelist(whitelist);
user_list users_list;
torrent_list torrents_list;
std::vector<std::string> whitelist;
db->load_users(users_list);
db->load_torrents(torrents_list);
db->load_whitelist(whitelist);
stats.open_connections = 0;
stats.opened_connections = 0;
stats.connection_rate = 0;
stats.requests = 0;
stats.request_rate = 0;
stats.leechers = 0;
stats.seeders = 0;
stats.announcements = 0;
stats.succ_announcements = 0;
stats.scrapes = 0;
stats.bytes_read = 0;
stats.bytes_written = 0;
stats.start_time = time(NULL);
stats.open_connections = 0;
stats.peak_connections = 0;
stats.opened_connections = 0;
stats.connection_rate = 0;
stats.requests = 0;
stats.request_rate = 0;
stats.leechers = 0;
stats.seeders = 0;
stats.user_queue_size = 0;
stats.torrent_queue_size = 0;
stats.peer_queue_size = 0;
stats.snatch_queue_size = 0;
stats.token_queue_size = 0;
stats.max_client_request_len = 0;
stats.announcements = 0;
stats.succ_announcements = 0;
stats.scrapes = 0;
stats.bytes_read = 0;
stats.bytes_written = 0;
stats.auth_error_secret = 0;
stats.auth_error_report = 0;
stats.auth_error_announce_key = 0;
stats.client_error = 0;
stats.http_error = 0;
stats.start_time = time(NULL);
// Create worker object, which handles announces and scrapes and all that jazz
work = new worker(conf, torrents_list, users_list, whitelist, db, sc);
// Create worker object, which handles announces and scrapes and all that jazz
work = new worker(conf, torrents_list, users_list, whitelist, db, sc);
// Create schedule object
sched = new schedule(conf, work, db, sc);
// Create schedule object
sched = new schedule(conf, work, db, sc);
// Create connection mother, which binds to its socket and handles the event stuff
mother = new connection_mother(conf, work, db, sc, sched);
// Create connection mother, which binds to its socket and handles the event stuff
mother = new connection_mother(conf, work, db, sc, sched);
// Add signal handlers now that all objects have been created
struct sigaction handler{}, ignore{};
ignore.sa_handler = SIG_IGN;
handler.sa_handler = sig_handler;
sigemptyset(&handler.sa_mask);
handler.sa_flags = 0;
// Add signal handlers now that all objects have been created
struct sigaction handler{}, ignore{};
ignore.sa_handler = SIG_IGN;
handler.sa_handler = sig_handler;
sigemptyset(&handler.sa_mask);
handler.sa_flags = 0;
sigaction(SIGINT, &handler, NULL);
sigaction(SIGTERM, &handler, NULL);
sigaction(SIGHUP, &handler, NULL);
sigaction(SIGUSR1, &handler, NULL);
sigaction(SIGUSR2, &ignore, NULL);
sigaction(SIGINT, &handler, NULL);
sigaction(SIGTERM, &handler, NULL);
sigaction(SIGHUP, &handler, NULL);
sigaction(SIGUSR1, &handler, NULL);
sigaction(SIGUSR2, &ignore, NULL);
mother->run();
mother->run();
return 0;
return 0;
}
+90 -66
View File
@@ -1,5 +1,15 @@
#ifndef OCELOT_H
#define OCELOT_H
#ifndef SRC_OCELOT_H_
#define SRC_OCELOT_H_
// Copyright [2017-2024] Orpheus
#define OCELOT_VERSION_MAJOR 2
#define OCELOT_VERSION_MINOR 1
#define OCELOT_VERSION_BUGFIX 3
#define OCELOT_VERSION_NREV 0
#define OCELOT_VERSION "2.1.3"
#include <time.h>
#include <string>
#include <map>
@@ -16,19 +26,19 @@ class user;
typedef std::shared_ptr<user> user_ptr;
typedef struct {
int64_t uploaded;
int64_t downloaded;
int64_t corrupt;
int64_t left;
time_t last_announced;
time_t first_announced;
uint32_t announces;
uint16_t port;
bool visible;
bool invalid_ip;
user_ptr user;
std::string ip_port;
std::string ip;
int64_t uploaded;
int64_t downloaded;
int64_t corrupt;
int64_t left;
time_t last_announced;
time_t first_announced;
uint32_t announces;
uint16_t port;
bool visible;
bool invalid_ip;
user_ptr user;
std::string ip_port;
std::string ip;
} peer;
typedef std::map<std::string, peer> peer_list;
@@ -36,52 +46,52 @@ typedef std::map<std::string, peer> peer_list;
enum freetype { NORMAL, FREE, NEUTRAL };
typedef struct {
torid_t id;
uint32_t completed;
int64_t balance;
freetype free_torrent;
time_t last_flushed;
peer_list seeders;
peer_list leechers;
std::string last_selected_seeder;
std::set<userid_t> tokened_users;
torid_t id;
uint32_t completed;
int64_t balance;
freetype free_torrent;
time_t last_flushed;
peer_list seeders;
peer_list leechers;
std::string last_selected_seeder;
std::set<userid_t> tokened_users;
} torrent;
enum {
DUPE, // 0
TRUMP, // 1
BAD_FILE_NAMES, // 2
BAD_FOLDER_NAMES, // 3
BAD_TAGS, // 4
BAD_FORMAT, // 5
DISCS_MISSING, // 6
DISCOGRAPHY,// 7
EDITED_LOG,// 8
INACCURATE_BITRATE, // 9
LOW_BITRATE, // 10
MUTT_RIP,// 11
BAD_SOURCE,// 12
ENCODE_ERRORS,// 13
BANNED, // 14
TRACKS_MISSING,// 15
TRANSCODE, // 16
CASSETTE, // 17
UNSPLIT_ALBUM, // 18
USER_COMPILATION, // 19
WRONG_FORMAT, // 20
WRONG_MEDIA, // 21
AUDIENCE // 22
DUPE, // 0
TRUMP, // 1
BAD_FILE_NAMES, // 2
BAD_FOLDER_NAMES, // 3
BAD_TAGS, // 4
BAD_FORMAT, // 5
DISCS_MISSING, // 6
DISCOGRAPHY, // 7
EDITED_LOG, // 8
INACCURATE_BITRATE, // 9
LOW_BITRATE, // 10
MUTT_RIP, // 11
BAD_SOURCE, // 12
ENCODE_ERRORS, // 13
BANNED, // 14
TRACKS_MISSING, // 15
TRANSCODE, // 16
CASSETTE, // 17
UNSPLIT_ALBUM, // 18
USER_COMPILATION, // 19
WRONG_FORMAT, // 20
WRONG_MEDIA, // 21
AUDIENCE // 22
};
typedef struct {
int reason;
time_t time;
int reason;
time_t time;
} del_message;
typedef struct {
bool gzip;
bool html;
bool http_close;
bool gzip;
bool html;
bool http_close;
} client_opts_t;
typedef std::unordered_map<std::string, torrent> torrent_list;
@@ -89,19 +99,33 @@ typedef std::unordered_map<std::string, user_ptr> user_list;
typedef std::unordered_map<std::string, std::string> params_type;
struct stats_t {
std::atomic<uint32_t> open_connections;
std::atomic<uint64_t> opened_connections;
std::atomic<uint64_t> connection_rate;
std::atomic<uint32_t> leechers;
std::atomic<uint32_t> seeders;
std::atomic<uint64_t> requests;
std::atomic<uint64_t> request_rate;
std::atomic<uint64_t> announcements;
std::atomic<uint64_t> succ_announcements;
std::atomic<uint64_t> scrapes;
std::atomic<uint64_t> bytes_read;
std::atomic<uint64_t> bytes_written;
time_t start_time;
std::atomic<uint32_t> open_connections;
std::atomic<uint32_t> peak_connections;
std::atomic<uint64_t> opened_connections;
std::atomic<uint64_t> connection_rate;
std::atomic<uint32_t> leechers;
std::atomic<uint32_t> seeders;
std::atomic<uint32_t> user_queue_size;
std::atomic<uint32_t> torrent_queue_size;
std::atomic<uint32_t> peer_queue_size;
std::atomic<uint32_t> snatch_queue_size;
std::atomic<uint32_t> token_queue_size;
std::atomic<uint32_t> max_client_request_len;
std::atomic<uint64_t> requests;
std::atomic<uint64_t> request_rate;
std::atomic<uint64_t> announcements;
std::atomic<uint64_t> succ_announcements;
std::atomic<uint64_t> scrapes;
std::atomic<uint64_t> bytes_read;
std::atomic<uint64_t> bytes_written;
std::atomic<uint64_t> auth_error_secret;
std::atomic<uint64_t> auth_error_report;
std::atomic<uint64_t> auth_error_announce_key;
std::atomic<uint64_t> client_error;
std::atomic<uint64_t> http_error;
time_t start_time;
};
extern struct stats_t stats;
#endif
extern const char *version();
#endif // SRC_OCELOT_H_
+268 -47
View File
@@ -1,56 +1,277 @@
#include <iostream>
#include <map>
// Copyright [2017-2024] Orpheus
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/resource.h>
#include <jemalloc/jemalloc.h>
#include <spdlog/spdlog.h> // debug
#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip> // for std::setfill() and std::setw()
#include <map>
#include <mutex>
#include <thread>
#include "ocelot.h"
#include "misc_functions.h"
#include "jemalloc_parse.h"
#include "report.h"
#include "response.h"
#include "user.h"
std::string report(params_type &params, user_list &users_list, client_opts_t &client_opts) {
std::stringstream output;
std::string action = params["get"];
if (action == "") {
output << "Invalid action\n";
} else if (action == "stats") {
time_t uptime = time(NULL) - stats.start_time;
int up_d = uptime / 86400;
uptime -= up_d * 86400;
int up_h = uptime / 3600;
uptime -= up_h * 3600;
int up_m = uptime / 60;
int up_s = uptime - up_m * 60;
std::string up_ht = up_h <= 9 ? '0' + inttostr(up_h) : inttostr(up_h);
std::string up_mt = up_m <= 9 ? '0' + inttostr(up_m) : inttostr(up_m);
std::string up_st = up_s <= 9 ? '0' + inttostr(up_s) : inttostr(up_s);
int jemalloc_fd;
std::mutex jemalloc_fd_mutex;
output << "Uptime: " << up_d << " days, " << up_ht << ':' << up_mt << ':' << up_st << '\n'
<< stats.opened_connections << " connections opened\n"
<< stats.open_connections << " open connections\n"
<< stats.connection_rate << " connections/s\n"
<< stats.requests << " requests handled\n"
<< stats.request_rate << " requests/s\n"
<< stats.succ_announcements << " successful announcements\n"
<< (stats.announcements - stats.succ_announcements) << " failed announcements\n"
<< stats.scrapes << " scrapes\n"
<< stats.leechers << " leechers tracked\n"
<< stats.seeders << " seeders tracked\n"
<< stats.bytes_read << " bytes read\n"
<< stats.bytes_written << " bytes written\n";
} else if (action == "user") {
std::string key = params["key"];
if (key.empty()) {
output << "Invalid action\n";
} else {
user_list::const_iterator u = users_list.find(key);
if (u != users_list.end()) {
output << u->second->get_leeching() << " leeching" << std::endl
<< u->second->get_seeding() << " seeding" << std::endl;
}
}
} else {
output << "Invalid action\n";
}
output << "success";
return response(output.str(), client_opts);
/* Getting jemalloc stats back to Gazelle is a bit cumbersome
* because all jemalloc can do is write to a file descriptor.
* So we let it write to a file (which is why using a ramdisk
* is important) and then read it back to return as an HTTP
* response.
*/
// callback function for malloc_stats_print()
void jemalloc_stats_export(void *opaque, const char *buf) {
if (jemalloc_fd > 0) {
write(jemalloc_fd, buf, strlen(buf));
}
}
int dump_jemalloc(const char *filename, const char *opts) {
// open the file descriptor
std::lock_guard<std::mutex> guard(jemalloc_fd_mutex);
jemalloc_fd = open(filename, O_CREAT|O_WRONLY, 0600);
if (jemalloc_fd == -1) {
return jemalloc_fd;
}
// dump stats
malloc_stats_print(jemalloc_stats_export, NULL, opts);
// tidy up
int result = close(jemalloc_fd);
jemalloc_fd = 0;
return result;
}
std::string report_jemalloc_plain(const char *opts, const std::string path) {
std::string filename(path + "/jemalloc.json." + std::to_string(pthread_self()));
if (dump_jemalloc(filename.c_str(), opts) != 0) {
// return an empty string if something went bananas
unlink(filename.c_str());
return std::string("");
}
// slurp the contents into a string
std::ifstream input(filename);
std::ostringstream output;
while(input >> output.rdbuf())
;
unlink(filename.c_str());
output << "\n";
std::shared_ptr<spdlog::logger> logger(spdlog::get("logger"));
logger->debug("jemalloc stats written to " + filename + ", size=" + std::to_string(output.str().size()));
return output.str();
}
#define ITEM_BYTE(LABEL, VALUE) "\"" LABEL "\":{\"type\":\"byte\",\"value\":" << VALUE << "}"
#define ITEM_ELAPSED(LABEL, VALUE) "\"" LABEL "\":{\"type\":\"elapsed\",\"value\":" << VALUE << "}"
#define ITEM_NUM(LABEL, VALUE) "\"" LABEL "\":{\"type\":\"number\",\"value\":" << VALUE << "}"
#define ITEM_STR(LABEL, VALUE) "\"" LABEL "\":{\"type\":\"string\",\"value\":\"" VALUE "\"}"
#define ITEM_VERSION(LABEL, MAJ, MIN, BUGFIX) "\"" LABEL "\":{\"type\":\"string\",\"value\":\"" << MAJ << "." << MIN << "." << BUGFIX << "\"}"
std::string report(const uint32_t announce_interval, const uint32_t announce_jitter) {
std::ostringstream output;
output << "{"
<< ITEM_STR("version", OCELOT_VERSION) << ','
<< ITEM_VERSION("jemalloc version", JEMALLOC_VERSION_MAJOR, JEMALLOC_VERSION_MINOR, JEMALLOC_VERSION_BUGFIX) << ','
<< ITEM_NUM("connections opened", stats.opened_connections) << ','
<< ITEM_NUM("open connections", stats.open_connections) << ','
<< ITEM_NUM("peak connections", stats.peak_connections) << ','
<< ITEM_NUM("connections/s", stats.connection_rate) << ','
<< ITEM_NUM("requests handled", stats.requests) << ','
<< ITEM_NUM("requests/s", stats.request_rate) << ','
<< ITEM_NUM("successful announcements", stats.succ_announcements) << ','
<< ITEM_NUM("failed announcements", (stats.announcements - stats.succ_announcements)) << ','
<< ITEM_NUM("scrapes", stats.scrapes) << ','
<< ITEM_NUM("leechers tracked", stats.leechers) << ','
<< ITEM_NUM("seeders tracked", stats.seeders) << ','
<< ITEM_NUM("items in user queue", stats.user_queue_size) << ','
<< ITEM_NUM("items in torrent queue", stats.torrent_queue_size) << ','
<< ITEM_NUM("items in peer queue", stats.peer_queue_size) << ','
<< ITEM_NUM("items in snatch queue", stats.snatch_queue_size) << ','
<< ITEM_NUM("items in token queue", stats.token_queue_size) << ','
<< ITEM_BYTE("max client request length", stats.max_client_request_len) << ','
<< ITEM_BYTE("bytes read", stats.bytes_read) << ','
<< ITEM_BYTE("bytes written", stats.bytes_written) << ','
<< ITEM_NUM("bad tracker secret received", stats.auth_error_secret) << ','
<< ITEM_NUM("bad report secret received", stats.auth_error_report) << ','
<< ITEM_NUM("bad announce key received", stats.auth_error_announce_key) << ','
<< ITEM_NUM("bad client configuration", stats.client_error) << ','
<< ITEM_NUM("bad http request", stats.http_error) << ','
<< ITEM_NUM("announce interval", announce_interval) << ','
<< ITEM_NUM("announce jitter", announce_jitter) << ','
<< ITEM_ELAPSED("uptime", (time(NULL) - stats.start_time))
;
struct rusage r;
if (getrusage(RUSAGE_SELF, &r) == 0) {
output << ','
<< ITEM_ELAPSED("user time", r.ru_utime.tv_sec << '.' << std::setfill('0') << std::setw(6) << r.ru_utime.tv_usec) << ','
<< ITEM_ELAPSED("system time", r.ru_stime.tv_sec << '.' << std::setfill('0') << std::setw(6) << r.ru_stime.tv_usec) << ','
<< ITEM_BYTE("maximum resident set size", r.ru_maxrss * 1024) << ','
<< ITEM_NUM("minor page faults", r.ru_minflt) << ','
<< ITEM_NUM("major page faults", r.ru_majflt) << ','
<< ITEM_NUM("blocks in", r.ru_inblock) << ','
<< ITEM_NUM("blocks out", r.ru_oublock) << ','
<< ITEM_NUM("voluntary context switches", r.ru_nvcsw ) << ','
<< ITEM_NUM("involuntary context switches", r.ru_nivcsw )
;
}
output << "}\n";
return output.str();
}
std::string report_prom_stats(const char *jemalloc) {
std::ostringstream output;
struct ocelot_alloc_info ji;
int result = jemalloc_parse(jemalloc, &ji);
output << "ocelot_uptime " << time(NULL) - stats.start_time << "\n"
"ocelot_version " << OCELOT_VERSION_MAJOR
<< std::setfill('0') << std::setw(3) << OCELOT_VERSION_MINOR
<< std::setfill('0') << std::setw(3) << OCELOT_VERSION_BUGFIX
<< std::setfill('0') << std::setw(3) << OCELOT_VERSION_NREV << "\n"
"jemalloc_version " << JEMALLOC_VERSION_MAJOR
<< std::setfill('0') << std::setw(3) << JEMALLOC_VERSION_MINOR
<< std::setfill('0') << std::setw(3) << JEMALLOC_VERSION_BUGFIX << "\n"
"ocelot_open_connections " << stats.open_connections << "\n"
"#TYPE ocelot_peak_connections counter\n"
"ocelot_peak_connections " << stats.peak_connections << "\n"
"ocelot_connection_rate " << stats.connection_rate << "\n"
"ocelot_requests " << stats.requests << "\n"
"ocelot_request_rate " << stats.request_rate << "\n"
"ocelot_succ_announcements " << stats.succ_announcements << "\n"
"ocelot_total_announcements " << stats.announcements << "\n"
"ocelot_scrapes " << stats.scrapes << "\n"
"ocelot_leechers " << stats.leechers << "\n"
"ocelot_seeders " << stats.seeders << "\n"
"ocelot_user_queue " << stats.user_queue_size << "\n"
"ocelot_torrent_queue " << stats.torrent_queue_size << "\n"
"ocelot_peer_queue " << stats.peer_queue_size << "\n"
"ocelot_snatch_queue " << stats.snatch_queue_size << "\n"
"ocelot_token_queue " << stats.token_queue_size << "\n"
"ocelot_bytes_read " << stats.bytes_read << "\n"
"ocelot_bytes_written " << stats.bytes_written << "\n"
"#TYPE ocelot_max_client_request_len counter\n"
"ocelot_max_client_request_len " << stats.max_client_request_len << "\n"
"#TYPE ocelot_error counter counter\n"
"ocelot_error{kind=\"secret\"} " << stats.auth_error_secret << "\n"
"ocelot_error{kind=\"report\"} " << stats.auth_error_report << "\n"
"ocelot_error{kind=\"announce\"} " << stats.auth_error_announce_key << "\n"
"ocelot_error{kind=\"client\"} " << stats.client_error << "\n"
"ocelot_error{kind=\"http\"} " << stats.http_error << "\n"
"ocelot_error{kind=\"jemalloc_parse\"} " << result << "\n"
"#TYPE jemalloc_arena_total counter\n"
"jemalloc_arena_total " << ji.nr_arena << "\n"
"#TYPE jemalloc_bin_total counter\n"
"jemalloc_bin_total{bin=\"small\"} " << ji.nr_bin_small << "\n"
"jemalloc_bin_total{bin=\"thread_cache\"} " << ji.nr_bin_tc << "\n"
"jemalloc_bin_total{bin=\"large\"} " << ji.nr_bin_large << "\n"
"#TYPE jemalloc_allocated counter\n"
"jemalloc_allocated{bucket=\"small\"} " << ji.small.allocated << "\n"
"jemalloc_allocated{bucket=\"large\"} " << ji.large.allocated << "\n"
"#TYPE jemalloc_nmalloc_total counter\n"
"jemalloc_nmalloc_total{bucket=\"small\"} " << ji.small.nmalloc_total << "\n"
"jemalloc_nmalloc_total{bucket=\"large\"} " << ji.large.nmalloc_total << "\n"
"#TYPE jemalloc_ndalloc_total counter\n"
"jemalloc_ndalloc_total{bucket=\"small\"} " << ji.small.ndalloc_total << "\n"
"jemalloc_ndalloc_total{bucket=\"large\"} " << ji.large.ndalloc_total << "\n"
"#TYPE jemalloc_nrequests_total counter\n"
"jemalloc_nrequests_total{bucket=\"small\"} " << ji.small.nrequests_total << "\n"
"jemalloc_nrequests_total{bucket=\"large\"} " << ji.large.nrequests_total << "\n"
"#TYPE jemalloc_nfill_total counter\n"
"jemalloc_nfill_total{bucket=\"small\"} " << ji.small.nfill_total << "\n"
"jemalloc_nfill_total{bucket=\"large\"} " << ji.large.nfill_total << "\n"
"#TYPE jemalloc_nflush_total counter\n"
"jemalloc_nflush_total{bucket=\"small\"} " << ji.small.nflush_total << "\n"
"jemalloc_nflush_total{bucket=\"large\"} " << ji.large.nflush_total << "\n"
"#TYPE jemalloc_nflush_total gauge\n"
"jemalloc_memory{global=\"allocated\"} " << ji.mem_allocated << "\n"
"jemalloc_memory{global=\"active\"} " << ji.mem_active << "\n"
"jemalloc_memory{global=\"metadata\"} " << ji.mem_metadata << "\n"
"jemalloc_memory{global=\"resident\"} " << ji.mem_resident << "\n"
"jemalloc_memory{global=\"mapped\"} " << ji.mem_mapped << "\n"
"jemalloc_memory{global=\"retained\"} " << ji.mem_retained << "\n"
"#TYPE jemalloc_nflush_rate gauge\n"
"jemalloc_allocated{bucket=\"small\"} " << ji.small.allocated << "\n"
"jemalloc_allocated{bucket=\"large\"} " << ji.large.allocated << "\n"
"#TYPE jemalloc_nflush_rate gauge\n"
"jemalloc_nmalloc_rate{bucket=\"small\"} " << ji.small.nmalloc_rate << "\n"
"jemalloc_nmalloc_rate{bucket=\"large\"} " << ji.large.nmalloc_rate << "\n"
"#TYPE jemalloc_nflush_total gauge\n"
"jemalloc_ndalloc_rate{bucket=\"small\"} " << ji.small.ndalloc_rate << "\n"
"jemalloc_ndalloc_rate{bucket=\"large\"} " << ji.large.ndalloc_rate << "\n"
"#TYPE jemalloc_nflush_rate gauge\n"
"jemalloc_nrequests_rate{bucket=\"small\"} " << ji.small.nrequests_rate << "\n"
"jemalloc_nrequests_rate{bucket=\"large\"} " << ji.large.nrequests_rate << "\n"
"#TYPE jemalloc_nflush_rate gauge\n"
"jemalloc_fill_rate{bucket=\"small\"} " << ji.small.nfill_rate << "\n"
"jemalloc_fill_rate{bucket=\"large\"} " << ji.large.nfill_rate << "\n"
"#TYPE jemalloc_nflush_rate gauge\n"
"jemalloc_nflush_rate{bucket=\"small\"} " << ji.small.nflush_rate << "\n"
"jemalloc_nflush_rate{bucket=\"large\"} " << ji.large.nflush_rate << "\n"
;
struct rusage r;
if (getrusage(RUSAGE_SELF, &r) == 0) {
output << "ocelot_time_user " << r.ru_utime.tv_sec << '.' << std::setfill('0') << std::setw(6) << r.ru_utime.tv_usec << "\n"
"ocelot_time_system " << r.ru_stime.tv_sec << '.' << std::setfill('0') << std::setw(6) << r.ru_stime.tv_usec << "\n"
"ocelot_max_rss " << r.ru_maxrss << "\n"
"ocelot_minor_fault " << r.ru_minflt << "\n"
"ocelot_major_fault " << r.ru_majflt << "\n"
"#TYPE ocelot_block counter\n"
"ocelot_block{op=\"in\"} " << r.ru_inblock << "\n"
"ocelot_block{op=\"out\"} " << r.ru_oublock << "\n"
"ocelot_nvcsw " << r.ru_nvcsw << "\n"
"ocelot_nivcsw " << r.ru_nivcsw << "\n"
;
}
output << '#';
return output.str();
}
std::string report_user(const user_ptr u) {
std::ostringstream output;
output << "{\"id\":" << u->get_id()
<< ",\"leeching\":" << u->get_leeching()
<< ",\"seeding\":" << u->get_seeding()
<< ",\"deleted\":" << u->is_deleted()
<< ",\"protected\":" << u->is_protected()
<< ",\"can_leech\":" << u->can_leech()
<< "}\n";
return output.str();
}
+22 -3
View File
@@ -1,4 +1,23 @@
#include <string>
#include "ocelot.h"
#ifndef SRC_REPORT_H_
#define SRC_REPORT_H_
std::string report(params_type &params, user_list &users_list, client_opts_t &client_opts);
// Copyright [2017-2024] Orpheus
#include <string>
// take a snapshot of the current stats
void copy_stats(const struct stats_t *in, struct stats_t *out);
// status report
std::string report(const uint32_t announce_interval, const uint32_t announce_jitter);
// a snapshot of jemalloc statistics
std::string report_jemalloc_plain(const char *opts, const std::string path);
// a prometheus scrape
std::string report_prom_stats(const char *jemalloc_stats);
// user report
std::string report_user(const user_ptr u);
#endif // SRC_REPORT_H_
+47 -40
View File
@@ -1,51 +1,58 @@
// Copyright [2017-2024] Orpheus
#include <algorithm>
#include <sstream>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include "response.h"
#include "misc_functions.h"
#include "response.h"
const std::string response(const std::string &body, client_opts_t &client_opts) {
std::string out;
bool processed = false;
if (client_opts.html) {
out = "<html><head><meta name=\"robots\" content=\"noindex, nofollow\" /></head><body>" + body + "</body></html>";
processed = true;
}
if (client_opts.gzip) {
std::stringstream ss, zss;
ss << body;
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::gzip_compressor());
in.push(ss);
boost::iostreams::copy(in, zss);
out = zss.str();
processed = true;
}
if (processed) {
return response_head(out.length(), client_opts) + out;
}
return response_head(body.length(), client_opts) + body;
const std::string http_head(size_t content_length, client_opts_t &client_opts) {
const std::string content_type = client_opts.html ? "text/html" : "text/plain";
// rely on preprocessor string concatenation
std::string head = "HTTP/1.1 200 OK\r\nServer: Ocelot " OCELOT_VERSION "\r\n"
"Content-Type: " + content_type + "\r\n"
"Content-Length: " + inttostr(content_length) + "\r\n";
if (client_opts.gzip) {
head += "Content-Encoding: gzip\r\n";
}
if (client_opts.http_close) {
head += "Connection: Close\r\n";
}
return head + "\r\n";
}
const std::string response_head(size_t content_length, client_opts_t &client_opts) {
const std::string content_type = client_opts.html ? "text/html" : "text/plain";
std::string head = "HTTP/1.1 200 OK\r\nServer: Ocelot 1.0";
head += "\r\nContent-Type: " + content_type;
if (client_opts.gzip) {
head += "\r\nContent-Encoding: gzip";
}
if (client_opts.http_close) {
head += "\r\nConnection: Close";
}
head += "\r\nContent-Length: " + inttostr(content_length) + "\r\n\r\n";
return head;
const std::string http_response(const std::string &body, client_opts_t &client_opts) {
std::string out;
bool processed = false;
if (client_opts.html) {
out = "<html><head><meta name=\"robots\" content=\"noindex, nofollow\" /></head><body>" + body + "</body></html>";
processed = true;
}
if (client_opts.gzip) {
std::stringstream ss, zss;
ss << body;
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::gzip_compressor());
in.push(ss);
boost::iostreams::copy(in, zss);
out = zss.str();
processed = true;
}
if (processed) {
return http_head(out.length(), client_opts) + out;
}
return http_head(body.length(), client_opts) + body;
}
const std::string error(const std::string &err, client_opts_t &client_opts) {
return response("d14:failure reason" + inttostr(err.length()) + ':' + err + "12:min intervali5400e8:intervali5400ee", client_opts);
}
const std::string warning(const std::string &msg) {
return "15:warning message" + inttostr(msg.length()) + ':' + msg;
const std::string error(const std::string &message, client_opts_t &client_opts) {
return http_response(
"d14:failure reason" + inttostr(message.length()) + ':' + message
+ "12:min intervali5400e8:intervali5400ee",
client_opts
);
}
+8 -6
View File
@@ -1,11 +1,13 @@
#ifndef RESPONSE_H
#define REPSONSE_H
#ifndef SRC_RESPONSE_H_
#define SRC_RESPONSE_H_
// Copyright [2017-2024] Orpheus
#include <string>
#include "ocelot.h"
const std::string response(const std::string &body, client_opts_t &client_opts);
const std::string response_head(size_t content_length, client_opts_t &client_opts);
const std::string http_response(const std::string &body, client_opts_t &client_opts);
const std::string error(const std::string &err, client_opts_t &client_opts);
const std::string warning(const std::string &msg);
#endif
#endif // SRC_RESPONSE_H_
Loaded 100 of 109 files, more files were not shown because too many files have changed in this diff. Show more