diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 93d64cc3f5e1ab2282abff5e74df5fcfd4f21f2f..65a9707051d771fefdb04feeab32c22a599a70dd 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,14 +22,14 @@ variables:
GIT_SUBMODULE_STRATEGY: recursive
# base image
-image: gekkofs/core:0.8.0
+image: gekkofs/core:0.9.0
################################################################################
## Validating
################################################################################
check format:
stage: lint
- image: gekkofs/linter:0.8.0
+ image: gekkofs/linter:0.9.0
needs: []
script:
- ${SCRIPTS_DIR}/check_format.sh
@@ -43,7 +43,7 @@ check format:
################################################################################
gkfs:
stage: build
- image: gekkofs/deps:0.8.0
+ image: gekkofs/deps:0.9.0
interruptible: true
needs: []
script:
@@ -56,6 +56,7 @@ gkfs:
-DGKFS_BUILD_TESTS:BOOL=ON
-DGKFS_INSTALL_TESTS:BOOL=ON
-DCMAKE_INSTALL_PREFIX=${INSTALL_PATH}
+ -DGKFS_USE_GUIDED_DISTRIBUTION:BOOL=ON
${CI_PROJECT_DIR}
- make -j$(nproc) install
# reduce artifacts size
@@ -68,7 +69,7 @@ gkfs:
gkfwd:
stage: build
- image: gekkofs/deps:0.8.0
+ image: gekkofs/deps:0.9.0
interruptible: true
needs: []
script:
@@ -101,7 +102,7 @@ gkfwd:
## == tests for scripts ====================
scripts:
stage: test
- image: gekkofs/testing:0.8.0
+ image: gekkofs/testing:0.9.0
needs: []
parallel:
matrix:
@@ -119,7 +120,7 @@ scripts:
## == integration tests for gkfs ===========
gkfs:integration:
stage: test
- image: gekkofs/testing:0.8.0
+ image: gekkofs/testing:0.9.0
interruptible: true
needs: ['gkfs']
parallel:
@@ -164,7 +165,7 @@ gkfs:integration:
## == integration tests for gkfwd ==========
gkfwd:integration:
stage: test
- image: gekkofs/testing:0.8.0
+ image: gekkofs/testing:0.9.0
interruptible: true
needs: ['gkfwd']
parallel:
@@ -209,7 +210,7 @@ gkfwd:integration:
## == unit tests for gkfs ==================
gkfs:unit:
stage: test
- image: gekkofs/testing:0.8.0
+ image: gekkofs/testing:0.9.0
needs: ['gkfs']
script:
## run actual tests
@@ -237,7 +238,7 @@ gkfs:unit:
################################################################################
coverage:
stage: report
- image: gekkofs/coverage:0.8.0
+ image: gekkofs/coverage:0.9.0
needs: [ 'gkfs:integration', 'gkfwd:integration', 'gkfs:unit' ]
script:
- cd ${BUILD_PATH}
diff --git a/.gitmodules b/.gitmodules
index bb7c8ebc30f93692607374b41aced403b2eea649..71b5722a3a194ed8a774f66c8de440457ec22641 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -16,3 +16,6 @@
[submodule "tests/scripts/helpers/bats-file"]
path = tests/scripts/helpers/bats-file
url = https://github.com/bats-core/bats-file.git
+[submodule "external/spdlog"]
+ path = external/spdlog
+ url = https://github.com/gabime/spdlog
diff --git a/CMake/gkfs-utils.cmake b/CMake/gkfs-utils.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..52a4c0404f4d653a2af21846904e8eae016f5b7f
--- /dev/null
+++ b/CMake/gkfs-utils.cmake
@@ -0,0 +1,148 @@
+################################################################################
+# Copyright 2018-2021, Barcelona Supercomputing Center (BSC), Spain #
+# Copyright 2015-2021, Johannes Gutenberg Universitaet Mainz, Germany #
+# #
+# This software was partially supported by the #
+# EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). #
+# #
+# This software was partially supported by the #
+# ADA-FS project under the SPPEXA project funded by the DFG. #
+# #
+# This file is part of GekkoFS. #
+# #
+# GekkoFS 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. #
+# #
+# GekkoFS 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 GekkoFS. If not, see . #
+# #
+# SPDX-License-Identifier: GPL-3.0-or-later #
+################################################################################
+
+include(CMakeParseArguments)
+
+#[=======================================================================[.rst:
+
+ get_cmake_variables(OUTPUT_VARIABLE
+ [ REGEX [EXCLUDE] ])
+
+Initialize ``OUTPUT_VARIABLE`` to a list of all currently defined CMake
+variables. The function accepts a ```` to allow filtering
+the results. Furthermore, if the ``EXCLUDE`` flag is used, the function will
+return all variables NOT MATCHING the provided ````.
+#]=======================================================================]
+function(get_cmake_variables OUTPUT_VARIABLE)
+
+ set(OPTIONS EXCLUDE)
+ set(SINGLE_VALUE REGEX)
+ set(MULTI_VALUE) # no multiple value args for now
+
+ cmake_parse_arguments(
+ ARGS "${OPTIONS}" "${SINGLE_VALUE}" "${MULTI_VALUE}" ${ARGN}
+ )
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(WARNING "Unparsed arguments in get_cmake_variables(): "
+ "this often indicates typos!\n"
+ "Unparsed arguments: ${ARGS_UNPARSED_ARGUMENTS}"
+ )
+ endif()
+
+ get_cmake_property(_var_names VARIABLES)
+
+ if(NOT ARGS_REGEX)
+ set(${OUTPUT_VARIABLE}
+ ${_var_names}
+ PARENT_SCOPE
+ )
+ return()
+ endif()
+
+ if(ARGS_EXCLUDE)
+ set(_mode EXCLUDE)
+ else()
+ set(_mode INCLUDE)
+ endif()
+
+ list(FILTER _var_names ${_mode} REGEX ${ARGS_REGEX})
+ set(${OUTPUT_VARIABLE}
+ ${_var_names}
+ PARENT_SCOPE
+ )
+endfunction()
+
+#[=======================================================================[.rst:
+
+ dump_cmake_variables([ REGEX [EXCLUDE] ])
+
+Print all currently defined CMake variables. The function accepts a
+```` to allow filtering the results. Furthermore, if the
+``EXCLUDE`` flag is used, the function will print all variables NOT MATCHING
+the provided ````.
+#]=======================================================================]
+function(dump_cmake_variables)
+
+ set(OPTIONS EXCLUDE)
+ set(SINGLE_VALUE REGEX)
+ set(MULTI_VALUE) # no multiple value args for now
+
+ cmake_parse_arguments(
+ ARGS "${OPTIONS}" "${SINGLE_VALUE}" "${MULTI_VALUE}" ${ARGN}
+ )
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(WARNING "Unparsed arguments in dump_cmake_variables(): "
+ "this often indicates typos!"
+ "Unparsed arguments: ${ARGS_UNPARSED_ARGUMENTS}"
+ )
+ endif()
+
+ if(ARGS_EXCLUDE AND NOT ARGS_REGEX)
+ message(ERROR "EXCLUDE option doesn't make sense without REGEX.")
+ endif()
+
+ get_cmake_variables(_var_names REGEX ${ARGS_REGEX} ${ARGS_EXCLUDE})
+
+ foreach(_var ${_var_names})
+ message(STATUS "${_var}=${${_var}}")
+ endforeach()
+endfunction()
+
+#[=======================================================================[.rst:
+
+ mark_variables_as_advanced(REGEX )
+
+Mark all CMake variables matching ``regular_expression`` as advanced.
+#]=======================================================================]
+function(mark_variables_as_advanced)
+
+ set(OPTIONS) # no options for now
+ set(SINGLE_VALUE REGEX)
+ set(MULTI_VALUE) # no multiple value args for now
+
+ cmake_parse_arguments(
+ ARGS "${OPTIONS}" "${SINGLE_VALUE}" "${MULTI_VALUE}" ${ARGN}
+ )
+
+ if(ARGS_UNPARSED_ARGUMENTS)
+ message(WARNING "Unparsed arguments in mark_variables_as_advanced(): "
+ "this often indicates typos!\n"
+ "Unparsed arguments: ${ARGS_UNPARSED_ARGUMENTS}"
+ )
+ endif()
+
+ get_cmake_property(_var_names VARIABLES)
+
+ list(FILTER _var_names INCLUDE REGEX ${ARGS_REGEX})
+
+ foreach(_var ${_var_names})
+ mark_as_advanced(${_var})
+ endforeach()
+endfunction()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f8f871e9d9856b4f791dcaa6de83a535e027cc3e..45669d7f6fcf08d55b071e49ae114014be0ff765 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,6 +65,11 @@ set(CMAKE_C_FLAGS_MEMCHECK "${WARNINGS_FLAGS} -g -O0 -fsanitize=address -fno-omi
set(CMAKE_C_FLAGS_MAINTAINER "${WARNINGS_FLAGS} -g -O0 -pg -no-pie")
mark_as_advanced(CMAKE_CXX_FLAGS_MAINTAINER)
+# CMake and general includes
+include(CheckCXXSourceCompiles)
+include(CMakeDependentOption)
+include(GNUInstallDirs)
+
# Project version
set(GIT_VERSION_FOUND FALSE)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
@@ -116,10 +121,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 0)
# Rocksdb dependencies
find_package(LZ4 REQUIRED)
-find_package(ZLIB REQUIRED)
-find_package(BZip2 REQUIRED)
-find_package(Snappy REQUIRED)
-find_package(ZStd REQUIRED)
find_package(JeMalloc) # required if rocksdb has been build with jemalloc
find_package(RocksDB REQUIRED)
# margo dependencies
@@ -127,8 +128,6 @@ find_package(Mercury REQUIRED)
find_package(Abt REQUIRED)
find_package(Margo REQUIRED)
find_package(Syscall_intercept REQUIRED)
-
-
find_package(Threads REQUIRED)
# some compilers need extra flags for std::filesystem, such as -lstdc++fs, this
@@ -138,6 +137,9 @@ find_package(Filesystem REQUIRED)
find_package(Date REQUIRED)
+# Import some convenience functions
+include(gkfs-utils)
+
option(CREATE_CHECK_PARENTS "Check parent directory existance before creating child node" ON)
message(STATUS "[gekkofs] Create checks parents: ${CREATE_CHECK_PARENTS}")
@@ -181,9 +183,11 @@ mark_as_advanced(CLIENT_LOG_MESSAGE_SIZE)
option(GKFS_USE_GUIDED_DISTRIBUTION "Use guided data distributor " OFF)
message(STATUS "[gekkofs] Guided data distributor: ${GKFS_USE_GUIDED_DISTRIBUTION}")
-set(GKFS_USE_GUIDED_DISTRIBUTION_PATH "/tmp/guided.txt" CACHE STRING "File Path for guided distributor")
-set_property(CACHE GKFS_USE_GUIDED_DISTRIBUTION_PATH PROPERTY STRINGS)
-message(STATUS "[gekkofs] Guided data distributor input file path: ${GKFS_USE_GUIDED_DISTRIBUTION_PATH}")
+if(GKFS_USE_GUIDED_DISTRIBUTION)
+ set(GKFS_USE_GUIDED_DISTRIBUTION_PATH "/tmp/guided.txt" CACHE STRING "File Path for guided distributor")
+ set_property(CACHE GKFS_USE_GUIDED_DISTRIBUTION_PATH PROPERTY STRINGS)
+ message(STATUS "[gekkofs] Guided data distributor input file path: ${GKFS_USE_GUIDED_DISTRIBUTION_PATH}")
+endif()
configure_file(include/common/cmake_configure.hpp.in include/common/cmake_configure.hpp)
@@ -193,10 +197,6 @@ target_link_libraries(RocksDB
INTERFACE
${ROCKSDB_LIBRARIES}
# rocksdb libs
- ${Snappy_LIBRARIES}
- ${ZLIB_LIBRARIES}
- ${BZIP2_LIBRARIES}
- ${ZStd_LIBRARIES}
${LZ4_LIBRARIES}
)
@@ -212,12 +212,6 @@ set_target_properties(RocksDB
INTERFACE_INCLUDE_DIRECTORIES ${ROCKSDB_INCLUDE_DIRS}
)
-add_library(spdlog INTERFACE)
-# we cannot use target_include_directories with CMake < 3.11
-set_target_properties(spdlog
- PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/external"
- )
add_library(CLI11 INTERFACE)
# we cannot use target_include_directories with CMake < 3.11
set_target_properties(CLI11
@@ -246,8 +240,6 @@ include_directories(
${CMAKE_BINARY_DIR}/include
)
-include(GNUInstallDirs)
-
# Common components
add_subdirectory(src/common)
# Daemon
@@ -255,9 +247,13 @@ add_subdirectory(src/daemon)
# Client library
add_subdirectory(src/client)
+### Mark any CMake variables imported from {fmt} and spdlog as advanced, so
+### that they don't appear in cmake-gui or ccmake. Similarly for FETCHCONTENT
+### variables.
+mark_variables_as_advanced(REGEX "^(FETCHCONTENT|fmt|FMT|spdlog|SPDLOG)_.*$")
+
option(GKFS_BUILD_TESTS "Build GekkoFS self tests" OFF)
-include(CMakeDependentOption)
cmake_dependent_option(GKFS_INSTALL_TESTS "Install GekkoFS self tests" OFF "GKFS_BUILD_TESTS" OFF)
if (GKFS_BUILD_TESTS)
@@ -289,6 +285,13 @@ if (GKFS_BUILD_TESTS)
set(GKFS_TESTS_FORWARDING "OFF" CACHE STRING "Enable I/O forwarding tests (default: OFF)")
endif ()
message(STATUS "[gekkofs] Forwarding tests: ${GKFS_TESTS_FORWARDING}")
+ message(STATUS "[gekkofs] Check for guided distributor tests...")
+ if (GKFS_USE_GUIDED_DISTRIBUTION)
+ set(GKFS_TESTS_GUIDED_DISTRIBUTION "ON" CACHE STRING "Enable guided distributor tests (default: OFF)")
+ else()
+ set(GKFS_TESTS_GUIDED_DISTRIBUTION "OFF" CACHE STRING "Enable guided distributor tests (default: OFF)")
+ endif()
+ message(STATUS "[gekkofs] Guided distributor tests: ${GKFS_TESTS_GUIDED_DISTRIBUTION}")
add_subdirectory(tests)
add_subdirectory(examples/gfind)
diff --git a/README.md b/README.md
index fafb2924e2acf32be9953c9c6a59f6a4c4228aed..89abed982f49e25df23c68add7bc3c8964589d5a 100644
--- a/README.md
+++ b/README.md
@@ -11,136 +11,46 @@ to I/O, which reduces interferences and improves performance.
# Dependencies
-- Upgrade your gcc to version at least 4.8 to get C++11 support
-- CMake >3.6 (>3.11 for GekkoFS testing)
+- \>gcc-8 (including g++) for C++11 support
+- General build tools: Git, Curl, CMake >3.6 (>3.11 for GekkoFS testing), Autoconf, Automake
+- Miscellaneous: Libtool, Libconfig
-## Debian/Ubuntu - Dependencies
+### Debian/Ubuntu
+GekkoFS base dependencies: `apt install git curl cmake autoconf automake libtool libconfig-dev`
-- snappy: `sudo apt-get install libsnappy-dev`
-- zlib: `sudo apt-get install zlib1g-dev`
-- bzip2: `sudo apt-get install libbz2-dev`
-- zstandard: `sudo apt-get install libzstd-dev`
-- lz4: `sudo apt-get install liblz4-dev`
-- uuid: `sudo apt-get install uuid-dev`
-- capstone: `sudo apt-get install libcapstone-dev`
+GekkoFS testing support: `apt install python3-dev python3 python3-venv`
-### CentOS/Red Hat - Dependencies
+With testing
+### CentOS/Red Hat
+GekkoFS base dependencies: `yum install gcc-c++ git curl cmake autoconf automake libtool libconfig`
+GekkoFS testing support: `python38-devel` (**>Python-3.6 required**)
-- snappy: `sudo yum install snappy snappy-devel`
-- zlib: `sudo yum install zlib zlib-devel`
-- bzip2: `sudo yum install bzip2 bzip2-devel`
-- zstandard:
-```bash
- wget https://github.com/facebook/zstd/archive/v1.1.3.tar.gz
- mv v1.1.3.tar.gz zstd-1.1.3.tar.gz
- tar zxvf zstd-1.1.3.tar.gz
- cd zstd-1.1.3
- make && sudo make install
-```
-- lz4: `sudo yum install lz4 lz4-devel`
-- uuid: `sudo yum install libuuid-devel`
-- capstone: `sudo yum install capstone capstone-devel`
-
-
-# Usage
-
-## Clone and compile direct GekkoFS dependencies
-
-- Go to the `scripts` folder and first clone all dependencies projects. You can choose the according network (na) plugin
-(execute the script for help):
-
-```bash
-usage: dl_dep.sh [-h] [-l] [-n ] [-c ] [-d ]
- source_path
-
-
-This script gets all GekkoFS dependency sources (excluding the fs itself)
-
-positional arguments:
- source_path path where the dependency downloads are put
-
-
-optional arguments:
- -h, --help shows this help message and exits
- -l, --list-dependencies
- list dependencies available for download with descriptions
- -n , --na
- network layer that is used for communication. Valid: {bmi,ofi,all}
- defaults to 'ofi'
- -c , --config
- allows additional configurations, e.g., for specific clusters
- supported values: {mogon2, mogon1, ngio, direct, all}
- defaults to 'direct'
- -d , --dependency
- download a specific dependency and ignore --config setting. If unspecified
- all dependencies are built and installed based on set --config setting.
- Multiple dependencies are supported: Pass a space-separated string (e.g., "ofi mercury"
- -v, --verbose Increase download verbosity
-```
-- Now use the install script to compile them and install them to the desired directory. You can choose the according
-(na) network plugin (execute the script for help):
+# Step-by-step installation
-```bash
-usage: compile_dep.sh [-h] [-l] [-n ] [-c ] [-d ] [-j ]
- source_path install_path
-
-
-This script compiles all GekkoFS dependencies (excluding the fs itself)
-
-positional arguments:
- source_path path to the cloned dependencies path from clone_dep.sh
- install_path path to the install path of the compiled dependencies
-
-
-optional arguments:
- -h, --help shows this help message and exits
- -l, --list-dependencies
- list dependencies available for building and installation
- -n , --na
- network layer that is used for communication. Valid: {bmi,ofi,all}
- defaults to 'all'
- -c , --config
- allows additional configurations, e.g., for specific clusters
- supported values: {mogon1, mogon2, ngio, direct, all}
- defaults to 'direct'
- -d , --dependency
- download a specific dependency and ignore --config setting. If unspecified
- all dependencies are built and installed based on set --config setting.
- Multiple dependencies are supported: Pass a space-separated string (e.g., "ofi mercury"
- -j , --compilecores
- number of cores that are used to compile the dependencies
- defaults to number of available cores
- -t, --test Perform libraries tests.
-```
-
-## Compile GekkoFS
+1. Make sure the above listed dependencies are available on your machine
+2. Clone GekkoFS: `git clone --recurse-submodules https://storage.bsc.es/gitlab/hpc/gekkofs.git`
+3. Set up the necessary environment variables where the compiled direct GekkoFS dependencies will be installed at (we assume the path `/home/foo/gekkofs_deps/install` in the following)
+ - `export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/home/foo/gekkofs_deps/install/lib:/home/foo/gekkofs_deps/install/lib64`
+4. Download and compile the direct dependencies, e.g.,
+ - Download example: `gekkofs/scripts/dl_dep.sh /home/foo/gekkofs_deps/git`
+ - Compilation example: `gekkofs/scripts/compile_dep.sh /home/foo/gekkofs_deps/git /home/foo/gekkofs_deps/install`
+ - Consult `-h` for additional arguments for each script
+5. Compile GekkoFS and run optional tests
+ - Create build directory: `mkdir gekkofs/build && cd gekkofs/build`
+ - Configure GekkoFS: `cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=/home/foo/gekkofs_deps/install ..`
+ - add `-DCMAKE_INSTALL_PREFIX=` where the GekkoFS client library and server executable should be available
+ - add `-DGKFS_BUILD_TESTS=ON` if tests should be build
+ - Build and install GekkoFS: `make -j8 install`
+ - Run tests: `make test`
-If above dependencies have been installed outside of the usual system paths, use CMake's `-DCMAKE_PREFIX_PATH` to
-make this path known to CMake.
-
-```bash
-mkdir build && cd build
-cmake -DCMAKE_BUILD_TYPE=Release ..
-make
-```
-
-In order to build self-tests, the *optional* GKFS_BUILD_TESTS CMake option needs
-to be enabled when building. Once that is done, tests can be run by running
-`make test` in the `build` directory:
-
-```bash
-mkdir build && cd build
-cmake -DGKFS_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Release ..
-make
-make test
-make install
-```
+GekkoFS is now available at:
+- GekkoFS daemon (server): `/bin/gkfs_daemon`
+- GekkoFS client interception library: `/lib64/libgkfs_intercept.so`
-**IMPORTANT:** Please note that the testing framework requires Python 3.6 and >CMake 3.11 as
-additional dependencies in order to run.
+# Run GekkoFS
-## Run GekkoFS
+## General
On each node a daemon (`gkfs_daemon` binary) has to be started. Other tools can be used to execute
the binary on many nodes, e.g., `srun`, `mpiexec/mpirun`, `pdsh`, or `pssh`.
@@ -152,51 +62,64 @@ The `-P` argument is used for setting another RPC protocol. See below.
- `ofi+tcp` for using the libfabric plugin with TCP (slower than sockets)
- `ofi+verbs` for using the libfabric plugin with Infiniband verbs (reasonably stable)
- `ofi+psm2` for using the libfabric plugin with Intel Omni-Path (unstable)
- - `bmi+tcp` for using the bmi plugin with TCP (alternative to libfabric)
-### Start and shut down daemon directly
+## The GekkoFS hostsfile
+
+Each GekkoFS daemon needs to register itself in a shared file (*hostsfile*) which needs to be accessible to _all_ GekkoFS clients and daemons.
+Therefore, the hostsfile describes a file system and which node is part of that specific GekkoFS file system instance.
+In a typical cluster environment this hostsfile should be placed within a POSIX-compliant parallel file system, such as GPFS or Lustre.
+
+*Note: NFS is not strongly consistent and cannot be used for the hosts file!*
+
+## GekkoFS daemon start and shut down
+
+tl;dr example: `/bin/gkfs_daemon -r -m -H `
-`./build/src/daemon/gkfs_daemon -r -m `
+Run the GekkoFS daemon on each node specifying its locally used directory where the file system data and metadata is stored (`-r/--rootdir `), e.g., the node-local SSD;
+2. the pseudo mount directory used by clients to access GekkoFS (`-m/--mountdir `); and
+3. the hostsfile path (`-H/--hostsfile `).
+
+Further options are available:
-Further options:
```bash
-Allowed options:
- -h [ --help ] Help message
- -m [ --mountdir ] arg Virtual mounting directory where GekkoFS is
- available.
- -r [ --rootdir ] arg Local data directory where GekkoFS data for this
- daemon is stored.
- -i [ --metadir ] arg Metadata directory where GekkoFS RocksDB data
- directory is located. If not set, rootdir is used.
- -l [ --listen ] arg Address or interface to bind the daemon to.
- Default: local hostname.
- When used with ofi+verbs the FI_VERBS_IFACE
- environment variable is set accordingly which
- associates the verbs device with the network
- interface. In case FI_VERBS_IFACE is already
- defined, the argument is ignored. Default 'ib'.
- -H [ --hosts-file ] arg Shared file used by deamons to register their
- endpoints. (default './gkfs_hosts.txt')
- -P [ --rpc-protocol ] arg Used RPC protocol for inter-node communication.
- Available: {ofi+sockets, ofi+verbs, ofi+psm2} for
- TCP, Infiniband, and Omni-Path, respectively.
- (Default ofi+sockets)
- Libfabric must have enabled support verbs or psm2.
- --auto-sm Enables intra-node communication (IPCs) via the
- `na+sm` (shared memory) protocol, instead of using
- the RPC protocol. (Default off)
- --version Print version and exit.
+Allowed options
+Usage: bin/gkfs_daemon [OPTIONS]
+
+Options:
+ -h,--help Print this help message and exit
+ -m,--mountdir TEXT REQUIRED Virtual mounting directory where GekkoFS is available.
+ -r,--rootdir TEXT REQUIRED Local data directory where GekkoFS data for this daemon is stored.
+ -i,--metadir TEXT Metadata directory where GekkoFS RocksDB data directory is located. If not set, rootdir is used.
+ -l,--listen TEXT Address or interface to bind the daemon to. Default: local hostname.
+ When used with ofi+verbs the FI_VERBS_IFACE environment variable is set accordingly which associates the verbs device with the network interface. In case FI_VERBS_IFACE is already defined, the argument is ignored. Default 'ib'.
+ -H,--hosts-file TEXT Shared file used by deamons to register their endpoints. (default './gkfs_hosts.txt')
+ -P,--rpc-protocol TEXT Used RPC protocol for inter-node communication.
+ Available: {ofi+sockets, ofi+verbs, ofi+psm2} for TCP, Infiniband, and Omni-Path, respectively. (Default ofi+sockets)
+ Libfabric must have enabled support verbs or psm2.
+ --auto-sm Enables intra-node communication (IPCs) via the `na+sm` (shared memory) protocol, instead of using the RPC protocol. (Default off)
+ --clean-rootdir Cleans Rootdir >before< launching the deamon
+ --version Print version and exit.
```
Shut it down by gracefully killing the process (SIGTERM).
-## Miscellaneous
+## Use the GekkoFS client library
+
+tl;dr example:
+```bash
+export LIBGKFS_ HOSTS_FILE=
+LD_PRELOAD=/lib64/libgkfs_intercept.so cp ~/some_input_data /some_input_data
+LD_PRELOAD=/lib64/libgkfs_intercept.so md5sum ~/some_input_data /some_input_data
+```
+
+Clients read the hostsfile to determine which daemons are part of the GekkoFS instance.
+Because the client is an interposition library that is loaded within the context of the application, this information is passed via the environment variable `LIBGKFS_HOSTS_FILE` pointing to the hostsfile path.
+The client library itself is loaded for each application process via the `LD_PRELOAD` environment variable intercepting file system related calls.
+If they are within (or hierarchically under) the GekkoFS mount directory they are processed in the library, otherwise they are passed to the kernel.
-Metadata and actual data will be stored at the ``. The path where the application works on is set with
-``.
+Note, if `LD_PRELOAD` is not pointing to the library and, hence the client is not loaded, the mounting directory appear to be empty.
-Run the application with the preload library: `LD_PRELOAD=/build/lib/libgkfs_intercept.so ./application`. In the case of
-an MPI application use the `{mpirun, mpiexec} -x` argument.
+For MPI application, the `LD_PRELOAD` variable can be passed with the `-x` argument for `mpirun/mpiexec`.
### Logging
The following environment variables can be used to enable logging in the client
@@ -245,50 +168,60 @@ can be provided to set the path to the log file, and the log module can be
selected with the `GKFS_LOG_LEVEL={off,critical,err,warn,info,debug,trace}`
environment variable.
+# Miscellaneous
-### External functions
+## External functions
GekkoFS allows to use external functions on your client code, via LD_PRELOAD.
Source code needs to be compiled with -fPIC. We include a pfind io500 substitution,
`examples/gfind/gfind.cpp` and a non-mpi version `examples/gfind/sfind.cpp`
-### Data distributors
+## Data distributors
The data distribution can be selected at compilation time, we have 2 distributors available:
-## Simple Hash (Default)
+### Simple Hash (Default)
Chunks are distributed randomly to the different GekkoFS servers.
-## Guided Distributor
-Guided distributor distributes chunks using a shared file with the next format:
-` `
+### Guided Distributor
-Moreover if you prepend a path with #, all the data from that path will go to the same place as the metadata.
-Specifically defined paths (without#) will be prioritary.
+To use the Guided Distributor, Boost (specifically the Boost *Interval Container Library* (ICL) must be available).
-i.e.,
-#/mdt-hard 0 0
+#### General
-GekkoFS will store data and metadata to the same server. The server will still be random (0 0 has no meaning, yet).
-
-Chunks not specified, are distributed using the Simple Hash distributor.
+The guided distributor allows defining a specific distribution of data on a per directory or file basis.
+The distribution configurations are defined within a shared file (called `guided_config.txt` henceforth) with the following format:
+` `
-To generate such file we need to follow a first execution, using the trace_reads log option
+To enable the distributor, the following CMake compilation flags are required:
+* `GKFS_USE_GUIDED_DISTRIBUTION` ON
+* `GKFS_USE_GUIDED_DISTRIBUTION_PATH` ``
-This will enable a `TRACE_READS` level log at the clients offering several lines that can be used to generate the input file.
-In this stage, each node should generate a separated file this can be done in SLURM using the next line :
-`srun -N 10 -n 320 --export="ALL" /bin/bash -c "export LIBGKFS_LOG_OUTPUT=${HOME}/test/GLOBAL.txt;LD_PRELOAD=${GKFS_PRLD} "`
+To use a custom distribution, a path needs to have the prefix `#` (e.g., `#/mdt-hard 0 0`), in which all the data of all files in that directory goes to the same place as the metadata.
+Note, that a chunk/host configuration is inherited to all children files automatically even if not using the prefix.
+In this example, `/mdt-hard/file1` is therefore also using the same distribution as the `/mdt-hard` directory.
+If no prefix is used, the Simple Hash distributor is used.
-Then, use the `examples/distributors/guided/generate.py` to create the output file.
-* `python examples/distributors/guided/generate.py ~/test/GLOBAL.txt >> guided.txt`
+#### Guided configuration file
-This should work if the nodes are sorted in alphabetical order, which is the usual scenario. Users should take care of multi-server configurations.
+Creating a guided configuration file is based on an I/O trace file of a previous execution of the application.
+For this the `trace_reads` tracing module is used (see above).
-Finally, enable the distributor using the next compilation flags:
-* `GKFS_USE_GUIDED_DISTRIBUTION` ON
-* `GKFS_USE_GUIDED_DISTRIBUTION_PATH` ``
+The `trace_reads` module enables a `TRACE_READS` level log at the clients writing the I/O information of the client which is used as the input for a script that creates the guided distributor setting.
+Note that capturing the necessary trace records can involve performance degradation.
+To capture the I/O of each client within a SLURM environment, i.e., enabling the `trace_reads` module and print its output to a user-defined path, the following example can be used:
+`srun -N 10 -n 320 --export="ALL" /bin/bash -c "export LIBGKFS_LOG=trace_reads;LIBGKFS_LOG_OUTPUT=${HOME}/test/GLOBAL.txt;LD_PRELOAD=${GKFS_PRLD} "`
+
+Then, the `examples/distributors/guided/generate.py` scrpt is used to create the guided distributor configuration file:
+* `python examples/distributors/guided/generate.py ~/test/GLOBAL.txt >> guided_config.txt`
+
+Finally, modify `guided_config.txt` to your distribution requirements.
### Acknowledgment
-This software was partially supported by the EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).
+This software was partially supported by the EC H2020 funded NEXTGenIO project (Project ID: 671951, www.nextgenio.eu).
+
+This software was partially supported by the ADA-FS project under the SPPEXA project (http://www.sppexa.de/) funded by the DFG.
+
+This software is partially supported by the FIDIUM project funded by the DFG.
-This software was partially supported by the ADA-FS project under the SPPEXA project funded by the DFG.
+This software is partially supported by the ADMIRE project (https://www.admire-eurohpc.eu/) funded by the European Union’s Horizon 2020 JTI-EuroHPC Research and Innovation Programme (Grant 956748).
\ No newline at end of file
diff --git a/docker/0.9.0/core/Dockerfile b/docker/0.9.0/core/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..bf1b2327ef9f7a79973049405c3f8696a0178fa8
--- /dev/null
+++ b/docker/0.9.0/core/Dockerfile
@@ -0,0 +1,39 @@
+FROM debian:bullseye-slim
+
+LABEL Description="Debian-based environment suitable to build GekkoFS and its dependencies"
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ git \
+ curl \
+ ca-certificates \
+ libtool \
+ pkg-config \
+ make \
+ automake \
+ gcc \
+ g++ \
+ procps \
+ # AGIOS dependencies
+ libconfig-dev \
+ # Mercury dependencies
+ libltdl-dev \
+ lbzip2 \
+ # Margo dependencies \
+ libjson-c-dev \
+ # RocksDB dependencies
+ liblz4-dev \
+ # syscall_intercept dependencies
+ libcapstone-dev \
+ # GekkoFS dependencies
+ libboost-program-options-dev \
+ uuid-dev && \
+ # install cmake 3.14 since it's needed for some dependencies
+ curl -OL https://github.com/Kitware/CMake/releases/download/v3.14.5/cmake-3.14.5-Linux-x86_64.sh && \
+ chmod u+x ./cmake-3.14.5-Linux-x86_64.sh && \
+ ./cmake-3.14.5-Linux-x86_64.sh --skip-license --prefix=/usr && \
+ # Clean apt cache to reduce image layer size
+ rm -rf /var/lib/apt/lists/* && \
+ # Clean apt caches of packages
+ apt-get clean && apt-get autoclean && \
+ rm ./cmake-3.14.5-Linux-x86_64.sh
diff --git a/docker/0.9.0/core/Makefile b/docker/0.9.0/core/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..576edb7a8fb1916062ed794f0999878216264017
--- /dev/null
+++ b/docker/0.9.0/core/Makefile
@@ -0,0 +1,10 @@
+.PHONY: all
+
+amd64:
+ docker build --platform amd64 -t gekkofs/core:0.9.0 .
+
+aarch64:
+ docker build --platform aarch64 -t gekkofs/core:0.9.0 .
+
+all:
+ docker build -t gekkofs/core:0.9.0 .
diff --git a/docker/0.9.0/coverage/Dockerfile b/docker/0.9.0/coverage/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..6514807130f821e3dd79dc259a3b5366bb22a4b3
--- /dev/null
+++ b/docker/0.9.0/coverage/Dockerfile
@@ -0,0 +1,20 @@
+FROM debian:bullseye-slim
+
+LABEL Description="Environment to generate coverage reports in GekkoFS"
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ wget \
+ git \
+ cmake \
+ gcc \
+ g++ \
+ lcov \
+ python3 \
+ python3-pip \
+ python3-setuptools && \
+ rm -rf /var/lib/apt/lists/* && \
+ apt-get clean && \
+ apt-get autoclean && \
+ python3 -m pip install --upgrade pip && \
+ pip3 install gcovr
diff --git a/docker/0.9.0/coverage/Makefile b/docker/0.9.0/coverage/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..8c9bf47a5ad8f2ce8f24714bd71e4be1a2d0fac3
--- /dev/null
+++ b/docker/0.9.0/coverage/Makefile
@@ -0,0 +1,10 @@
+.PHONY: all
+
+amd64:
+ docker build --platform amd64 -t gekkofs/coverage:0.9.0 .
+
+aarch64:
+ docker build --platform aarch64 -t gekkofs/coverage:0.9.0 .
+
+all:
+ docker build -t gekkofs/coverage:0.9.0 .
\ No newline at end of file
diff --git a/docker/0.9.0/deps/Dockerfile b/docker/0.9.0/deps/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..d27486c82eb11802ffb1bfd27aa3b3495e4eff4e
--- /dev/null
+++ b/docker/0.9.0/deps/Dockerfile
@@ -0,0 +1,35 @@
+FROM gekkofs/core:0.9.0
+
+LABEL Description="Debian-based environment to build GekkoFS"
+
+ENV GKFS_PATH /opt/gkfs
+ENV GKFS_VERSION 0.9.0
+
+ENV SCRIPTS_PATH ${GKFS_PATH}/scripts
+ENV DEPS_SRC_PATH ${GKFS_PATH}/deps_src
+ENV INSTALL_PATH /usr/local
+
+COPY scripts/dl_dep.sh ${SCRIPTS_PATH}/
+COPY scripts/compile_dep.sh ${SCRIPTS_PATH}/
+COPY scripts/patches ${SCRIPTS_PATH}/patches
+COPY scripts/profiles ${SCRIPTS_PATH}/profiles
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ python3 \
+ python3-pip \
+ python3-dev \
+ python3-venv \
+ python3-setuptools && \
+ python3 -m pip install --upgrade pip && \
+ rm -rf /var/lib/apt/lists/* && \
+ apt-get clean && apt-get autoclean
+
+# Download and build dependencies
+RUN cd ${SCRIPTS_PATH} && \
+ /bin/bash ./dl_dep.sh -p ci:${GKFS_VERSION} ${DEPS_SRC_PATH} && \
+ /bin/bash ./compile_dep.sh -j 8 -p ci:${GKFS_VERSION} ${DEPS_SRC_PATH} ${INSTALL_PATH} && \
+ rm -rf ${DEPS_SRC_PATH} && \
+ rm -rf ${SCRIPTS_PATH} && \
+ rmdir ${GKFS_PATH} && \
+ ldconfig
diff --git a/docker/0.9.0/deps/Makefile b/docker/0.9.0/deps/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b47c6323ddca17c7234fc2d345fce28a1058f3f4
--- /dev/null
+++ b/docker/0.9.0/deps/Makefile
@@ -0,0 +1,23 @@
+CWD:=$(shell pwd)
+GIT_ROOT:=$(shell git rev-parse --show-toplevel)
+
+.PHONY: all build mount-scripts umount-scripts
+
+all: build mount-scripts remove-scripts
+amd64: build-amd64 mount-scripts remove-scripts
+aarch64: build-aarch64 mount-scripts remove-scripts
+
+copy-scripts:
+ cp -R $(GIT_ROOT)/scripts $(CWD)/scripts
+
+build: copy-scripts
+ docker build -t gekkofs/deps:0.9.0 .
+
+build-amd64: copy-scripts
+ docker build --platform amd64 -t gekkofs/deps:0.9.0 .
+
+build-aarch64: copy-scripts
+ docker build --platform aarch64 -t gekkofs/deps:0.9.0 .
+
+remove-scripts:
+ - rm -rf $(CWD)/scripts
diff --git a/docker/0.9.0/linter/Dockerfile b/docker/0.9.0/linter/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..d717b3f0c9ac436e9fd9745a1f8e0bfdbcbbc68d
--- /dev/null
+++ b/docker/0.9.0/linter/Dockerfile
@@ -0,0 +1,19 @@
+FROM gekkofs/core:0.9.0
+
+LABEL Description="Debian-based environment to check the formatting of GekkoFS code"
+
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ # clang 10 deps for clang-format
+ lsb-release \
+ wget \
+ software-properties-common \
+ gnupg2 && \
+ # add clang-10 repos
+ wget https://apt.llvm.org/llvm.sh -P /tmp && chmod +x /tmp/llvm.sh && /tmp/llvm.sh 11 && \
+ # install clang-format
+ apt-get update && apt-get install -y --no-install-recommends clang-format-11 && \
+ # Clean apt cache to reduce image layer size
+ rm -rf /var/lib/apt/lists/* && rm /tmp/llvm.sh && \
+ # Clean apt caches of packages
+ apt-get clean && apt-get autoclean
diff --git a/docker/0.9.0/linter/Makefile b/docker/0.9.0/linter/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c60fffe2b7a38f5866a92c885b8e171df6e00e85
--- /dev/null
+++ b/docker/0.9.0/linter/Makefile
@@ -0,0 +1,10 @@
+.PHONY: all
+
+amd64:
+ docker build --platform amd64 -t gekkofs/linter:0.9.0 .
+
+aarch64:
+ docker build --platform aarch64 -t gekkofs/linter:0.9.0 .
+
+all:
+ docker build -t gekkofs/linter:0.9.0 .
diff --git a/docker/0.9.0/testing/Dockerfile b/docker/0.9.0/testing/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..5d64838fc1354a9138dcae2c7b5d3eb18d8d64d2
--- /dev/null
+++ b/docker/0.9.0/testing/Dockerfile
@@ -0,0 +1,14 @@
+FROM gekkofs/deps:0.9.0
+
+LABEL Description="Debian-based environment to test GekkoFS"
+
+RUN \
+ # install cmake 3.21 since we need to produce JUnit XML files
+ curl -OL https://github.com/Kitware/CMake/releases/download/v3.21.1/cmake-3.21.1-linux-x86_64.sh && \
+ chmod u+x ./cmake-3.21.1-linux-x86_64.sh && \
+ ./cmake-3.21.1-linux-x86_64.sh --skip-license --prefix=/usr && \
+ # install gcovr
+ # (required for partial coverage reports in parallel runs)
+ pip3 install gcovr && \
+ # cleanup
+ rm ./cmake-3.21.1-linux-x86_64.sh
diff --git a/docker/0.9.0/testing/Makefile b/docker/0.9.0/testing/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cff8ea1c187ccb1ce738b1b1cf86ff0e4dca78ee
--- /dev/null
+++ b/docker/0.9.0/testing/Makefile
@@ -0,0 +1,10 @@
+.PHONY: all
+
+amd64:
+ docker build --platform amd64 -t gekkofs/testing:0.9.0 .
+
+aarch64:
+ docker build --platform aarch64 -t gekkofs/testing:0.9.0 .
+
+all:
+ docker build -t gekkofs/testing:0.9.0 .
\ No newline at end of file
diff --git a/docker/latest b/docker/latest
index 8adc70fdd9d6a086cc636d251adf0c7a7bca8319..899f24fc754a14b89617093824d258aaa3aa2943 120000
--- a/docker/latest
+++ b/docker/latest
@@ -1 +1 @@
-0.8.0
\ No newline at end of file
+0.9.0
\ No newline at end of file
diff --git a/examples/gfind/sfind.cpp b/examples/gfind/sfind.cpp
index 52d69c654a2f1bea992307da205120bba4594e18..c7639935567d54279d782ab4ccbcfa318cbf1e00 100644
--- a/examples/gfind/sfind.cpp
+++ b/examples/gfind/sfind.cpp
@@ -113,11 +113,11 @@ static void pfind_print_help(pfind_options_t *res) {
"\tworkdir = \"%s\"\n"
"\t-newer = \"%s\"\n"
"\t-name|-regex = \"%s\"\n"
- "\t-S: num servers = \"%s\"\n"
+ "\t-S: num servers = \"%d\"\n"
"\t-M: mountdir = \"%s\"\n"
"Optional flags\n"
"\t-h: prints the help\n"
- "\t--help: prints the help without initializing MPI\n",res->workdir,
+ "\t--help: prints the help without initializing MPI\n",res->workdir.c_str(),
res->timestamp_file, res->name_pattern, res->num_servers,
res->mountdir );
}
diff --git a/external/hermes b/external/hermes
index 0af45bfa667f7ff9c78167ef94d975bffbd879f0..38d821182ef2b6c6961595bf011ca69bf78bc936 160000
--- a/external/hermes
+++ b/external/hermes
@@ -1 +1 @@
-Subproject commit 0af45bfa667f7ff9c78167ef94d975bffbd879f0
+Subproject commit 38d821182ef2b6c6961595bf011ca69bf78bc936
diff --git a/external/spdlog b/external/spdlog
new file mode 160000
index 0000000000000000000000000000000000000000..eb3220622e73a4889eee355ffa37972b3cac3df5
--- /dev/null
+++ b/external/spdlog
@@ -0,0 +1 @@
+Subproject commit eb3220622e73a4889eee355ffa37972b3cac3df5
diff --git a/external/spdlog/async.h b/external/spdlog/async.h
deleted file mode 100644
index 971becd700023b5abe6db3e74fc8527fa6ef74d6..0000000000000000000000000000000000000000
--- a/external/spdlog/async.h
+++ /dev/null
@@ -1,87 +0,0 @@
-
-//
-// Copyright(c) 2018 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-//
-// Async logging using global thread pool
-// All loggers created here share same global thread pool.
-// Each log message is pushed to a queue along withe a shared pointer to the
-// logger.
-// If a logger deleted while having pending messages in the queue, it's actual
-// destruction will defer
-// until all its messages are processed by the thread pool.
-// This is because each message in the queue holds a shared_ptr to the
-// originating logger.
-
-#include "spdlog/async_logger.h"
-#include "spdlog/details/registry.h"
-#include "spdlog/details/thread_pool.h"
-
-#include
-#include
-
-namespace spdlog {
-
-namespace details {
-static const size_t default_async_q_size = 8192;
-}
-
-// async logger factory - creates async loggers backed with thread pool.
-// if a global thread pool doesn't already exist, create it with default queue
-// size of 8192 items and single thread.
-template
-struct async_factory_impl
-{
- template
- static std::shared_ptr create(std::string logger_name, SinkArgs &&... args)
- {
- auto ®istry_inst = details::registry::instance();
-
- // create global thread pool if not already exists..
- std::lock_guard tp_lock(registry_inst.tp_mutex());
- auto tp = registry_inst.get_tp();
- if (tp == nullptr)
- {
- tp = std::make_shared(details::default_async_q_size, 1);
- registry_inst.set_tp(tp);
- }
-
- auto sink = std::make_shared(std::forward(args)...);
- auto new_logger = std::make_shared(std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);
- registry_inst.initialize_logger(new_logger);
- return new_logger;
- }
-};
-
-using async_factory = async_factory_impl;
-using async_factory_nonblock = async_factory_impl;
-
-template
-inline std::shared_ptr create_async(std::string logger_name, SinkArgs &&... sink_args)
-{
- return async_factory::create(std::move(logger_name), std::forward(sink_args)...);
-}
-
-template
-inline std::shared_ptr create_async_nb(std::string logger_name, SinkArgs &&... sink_args)
-{
- return async_factory_nonblock::create(std::move(logger_name), std::forward(sink_args)...);
-}
-
-// set global thread pool.
-inline void init_thread_pool(size_t q_size, size_t thread_count)
-{
- auto tp = std::make_shared(q_size, thread_count);
- details::registry::instance().set_tp(std::move(tp));
-}
-
-// get the global thread pool.
-inline std::shared_ptr thread_pool()
-{
- return details::registry::instance().get_tp();
-}
-} // namespace spdlog
diff --git a/external/spdlog/async_logger.h b/external/spdlog/async_logger.h
deleted file mode 100644
index a7ecb787377d8de9c431da418aedfea9a10ec10c..0000000000000000000000000000000000000000
--- a/external/spdlog/async_logger.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-// Very fast asynchronous logger (millions of logs per second on an average
-// desktop)
-// Uses pre allocated lockfree queue for maximum throughput even under large
-// number of threads.
-// Creates a single back thread to pop messages from the queue and log them.
-//
-// Upon each log write the logger:
-// 1. Checks if its log level is enough to log the message
-// 2. Push a new copy of the message to a queue (or block the caller until
-// space is available in the queue)
-// 3. will throw spdlog_ex upon log exceptions
-// Upon destruction, logs all remaining messages in the queue before
-// destructing..
-
-#include "spdlog/common.h"
-#include "spdlog/logger.h"
-
-#include
-#include
-#include
-
-namespace spdlog {
-
-// Async overflow policy - block by default.
-enum class async_overflow_policy
-{
- block, // Block until message can be enqueued
- overrun_oldest // Discard oldest message in the queue if full when trying to
- // add new item.
-};
-
-namespace details {
-class thread_pool;
-}
-
-class async_logger final : public std::enable_shared_from_this, public logger
-{
- friend class details::thread_pool;
-
-public:
- template
- async_logger(std::string logger_name, It begin, It end, std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block);
-
- async_logger(std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block);
-
- async_logger(std::string logger_name, sink_ptr single_sink, std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block);
-
- std::shared_ptr clone(std::string new_name) override;
-
-protected:
- void sink_it_(details::log_msg &msg) override;
- void flush_() override;
-
- void backend_log_(const details::log_msg &incoming_log_msg);
- void backend_flush_();
-
-private:
- std::weak_ptr thread_pool_;
- async_overflow_policy overflow_policy_;
-};
-} // namespace spdlog
-
-#include "details/async_logger_impl.h"
diff --git a/external/spdlog/common.h b/external/spdlog/common.h
deleted file mode 100644
index d078a1ab32009f8a17721659a9bb09d287c64008..0000000000000000000000000000000000000000
--- a/external/spdlog/common.h
+++ /dev/null
@@ -1,243 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-#include "spdlog/tweakme.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
-#include
-#include
-#endif
-
-#include "spdlog/details/null_mutex.h"
-
-#include "spdlog/fmt/fmt.h"
-
-// visual studio upto 2013 does not support noexcept nor constexpr
-#if defined(_MSC_VER) && (_MSC_VER < 1900)
-#define SPDLOG_NOEXCEPT throw()
-#define SPDLOG_CONSTEXPR
-#else
-#define SPDLOG_NOEXCEPT noexcept
-#define SPDLOG_CONSTEXPR constexpr
-#endif
-
-#if defined(__GNUC__) || defined(__clang__)
-#define SPDLOG_DEPRECATED __attribute__((deprecated))
-#elif defined(_MSC_VER)
-#define SPDLOG_DEPRECATED __declspec(deprecated)
-#else
-#define SPDLOG_DEPRECATED
-#endif
-
-// disable thread local on msvc 2013
-#ifndef SPDLOG_NO_TLS
-#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt)
-#define SPDLOG_NO_TLS 1
-#endif
-#endif
-
-// Get the basename of __FILE__ (at compile time if possible)
-#if FMT_HAS_FEATURE(__builtin_strrchr)
-#define SPDLOG_STRRCHR(str, sep) __builtin_strrchr(str, sep)
-#else
-#define SPDLOG_STRRCHR(str, sep) strrchr(str, sep)
-#endif //__builtin_strrchr not defined
-
-#ifdef _WIN32
-#define SPDLOG_FILE_BASENAME(file) SPDLOG_STRRCHR("\\" file, '\\') + 1
-#else
-#define SPDLOG_FILE_BASENAME(file) SPDLOG_STRRCHR("/" file, '/') + 1
-#endif
-
-#ifndef SPDLOG_FUNCTION
-#define SPDLOG_FUNCTION __FUNCTION__
-#endif
-
-namespace spdlog {
-
-class formatter;
-
-namespace sinks {
-class sink;
-}
-
-using log_clock = std::chrono::system_clock;
-using sink_ptr = std::shared_ptr;
-using sinks_init_list = std::initializer_list;
-using log_err_handler = std::function;
-
-// string_view type - either std::string_view or fmt::string_view (pre c++17)
-#if defined(FMT_USE_STD_STRING_VIEW)
-using string_view_t = std::string_view;
-#else
-using string_view_t = fmt::string_view;
-#endif
-
-#if defined(SPDLOG_NO_ATOMIC_LEVELS)
-using level_t = details::null_atomic_int;
-#else
-using level_t = std::atomic;
-#endif
-
-#define SPDLOG_LEVEL_TRACE 0
-#define SPDLOG_LEVEL_DEBUG 1
-#define SPDLOG_LEVEL_INFO 2
-#define SPDLOG_LEVEL_WARN 3
-#define SPDLOG_LEVEL_ERROR 4
-#define SPDLOG_LEVEL_CRITICAL 5
-#define SPDLOG_LEVEL_OFF 6
-
-#if !defined(SPDLOG_ACTIVE_LEVEL)
-#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
-#endif
-
-// Log level enum
-namespace level {
-enum level_enum
-{
- trace = SPDLOG_LEVEL_TRACE,
- debug = SPDLOG_LEVEL_DEBUG,
- info = SPDLOG_LEVEL_INFO,
- warn = SPDLOG_LEVEL_WARN,
- err = SPDLOG_LEVEL_ERROR,
- critical = SPDLOG_LEVEL_CRITICAL,
- off = SPDLOG_LEVEL_OFF,
-};
-
-#if !defined(SPDLOG_LEVEL_NAMES)
-#define SPDLOG_LEVEL_NAMES \
- { \
- "trace", "debug", "info", "warning", "error", "critical", "off" \
- }
-#endif
-
-static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
-static const char *short_level_names[]{"T", "D", "I", "W", "E", "C", "O"};
-
-inline string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
-{
- return level_string_views[l];
-}
-
-inline const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT
-{
- return short_level_names[l];
-}
-
-inline spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT
-{
- int level = 0;
- for (const auto &level_str : level_string_views)
- {
- if (level_str == name)
- {
- return static_cast(level);
- }
- level++;
- }
- return level::off;
-}
-
-using level_hasher = std::hash;
-} // namespace level
-
-//
-// Pattern time - specific time getting to use for pattern_formatter.
-// local time by default
-//
-enum class pattern_time_type
-{
- local, // log localtime
- utc // log utc
-};
-
-//
-// Log exception
-//
-class spdlog_ex : public std::exception
-{
-public:
- explicit spdlog_ex(std::string msg)
- : msg_(std::move(msg))
- {
- }
-
- spdlog_ex(const std::string &msg, int last_errno)
- {
- fmt::memory_buffer outbuf;
- fmt::format_system_error(outbuf, last_errno, msg);
- msg_ = fmt::to_string(outbuf);
- }
-
- const char *what() const SPDLOG_NOEXCEPT override
- {
- return msg_.c_str();
- }
-
-private:
- std::string msg_;
-};
-
-//
-// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
-//
-#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
-using filename_t = std::wstring;
-#else
-using filename_t = std::string;
-#endif
-
-struct source_loc
-{
- SPDLOG_CONSTEXPR source_loc()
- : filename{""}
- , line{0}
- , funcname{""}
- {
- }
- SPDLOG_CONSTEXPR source_loc(const char *filename, int line, const char *funcname)
- : filename{filename}
- , line{static_cast(line)}
- , funcname{funcname}
- {
- }
-
- SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT
- {
- return line == 0;
- }
- const char *filename;
- uint32_t line;
- const char *funcname;
-};
-
-namespace details {
-// make_unique support for pre c++14
-
-#if __cplusplus >= 201402L // C++14 and beyond
-using std::make_unique;
-#else
-template
-std::unique_ptr make_unique(Args &&... args)
-{
- static_assert(!std::is_array::value, "arrays not supported");
- return std::unique_ptr(new T(std::forward(args)...));
-}
-#endif
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/async_logger_impl.h b/external/spdlog/details/async_logger_impl.h
deleted file mode 100644
index aafcae6568cd0468dff3d1dc39e9dd1d88738b1e..0000000000000000000000000000000000000000
--- a/external/spdlog/details/async_logger_impl.h
+++ /dev/null
@@ -1,110 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-// async logger implementation
-// uses a thread pool to perform the actual logging
-
-#include "spdlog/details/thread_pool.h"
-
-#include
-#include
-#include
-
-template
-inline spdlog::async_logger::async_logger(
- std::string logger_name, It begin, It end, std::weak_ptr tp, async_overflow_policy overflow_policy)
- : logger(std::move(logger_name), begin, end)
- , thread_pool_(std::move(tp))
- , overflow_policy_(overflow_policy)
-{
-}
-
-inline spdlog::async_logger::async_logger(
- std::string logger_name, sinks_init_list sinks_list, std::weak_ptr tp, async_overflow_policy overflow_policy)
- : async_logger(std::move(logger_name), sinks_list.begin(), sinks_list.end(), std::move(tp), overflow_policy)
-{
-}
-
-inline spdlog::async_logger::async_logger(
- std::string logger_name, sink_ptr single_sink, std::weak_ptr tp, async_overflow_policy overflow_policy)
- : async_logger(std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy)
-{
-}
-
-// send the log message to the thread pool
-inline void spdlog::async_logger::sink_it_(details::log_msg &msg)
-{
-#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
- incr_msg_counter_(msg);
-#endif
- if (auto pool_ptr = thread_pool_.lock())
- {
- pool_ptr->post_log(shared_from_this(), msg, overflow_policy_);
- }
- else
- {
- throw spdlog_ex("async log: thread pool doesn't exist anymore");
- }
-}
-
-// send flush request to the thread pool
-inline void spdlog::async_logger::flush_()
-{
- if (auto pool_ptr = thread_pool_.lock())
- {
- pool_ptr->post_flush(shared_from_this(), overflow_policy_);
- }
- else
- {
- throw spdlog_ex("async flush: thread pool doesn't exist anymore");
- }
-}
-
-//
-// backend functions - called from the thread pool to do the actual job
-//
-inline void spdlog::async_logger::backend_log_(const details::log_msg &incoming_log_msg)
-{
- try
- {
- for (auto &s : sinks_)
- {
- if (s->should_log(incoming_log_msg.level))
- {
- s->log(incoming_log_msg);
- }
- }
- }
- SPDLOG_CATCH_AND_HANDLE
-
- if (should_flush_(incoming_log_msg))
- {
- backend_flush_();
- }
-}
-
-inline void spdlog::async_logger::backend_flush_()
-{
- try
- {
- for (auto &sink : sinks_)
- {
- sink->flush();
- }
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-inline std::shared_ptr spdlog::async_logger::clone(std::string new_name)
-{
- auto cloned = std::make_shared(std::move(new_name), sinks_.begin(), sinks_.end(), thread_pool_, overflow_policy_);
-
- cloned->set_level(this->level());
- cloned->flush_on(this->flush_level());
- cloned->set_error_handler(this->error_handler());
- return std::move(cloned);
-}
diff --git a/external/spdlog/details/circular_q.h b/external/spdlog/details/circular_q.h
deleted file mode 100644
index b01325bb751604819dab686bcc2a19ad746668bc..0000000000000000000000000000000000000000
--- a/external/spdlog/details/circular_q.h
+++ /dev/null
@@ -1,72 +0,0 @@
-//
-// Copyright(c) 2018 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-// cirucal q view of std::vector.
-#pragma once
-
-#include
-
-namespace spdlog {
-namespace details {
-template
-class circular_q
-{
-public:
- using item_type = T;
-
- explicit circular_q(size_t max_items)
- : max_items_(max_items + 1) // one item is reserved as marker for full q
- , v_(max_items_)
- {
- }
-
- // push back, overrun (oldest) item if no room left
- void push_back(T &&item)
- {
- v_[tail_] = std::move(item);
- tail_ = (tail_ + 1) % max_items_;
-
- if (tail_ == head_) // overrun last item if full
- {
- head_ = (head_ + 1) % max_items_;
- ++overrun_counter_;
- }
- }
-
- // Pop item from front.
- // If there are no elements in the container, the behavior is undefined.
- void pop_front(T &popped_item)
- {
- popped_item = std::move(v_[head_]);
- head_ = (head_ + 1) % max_items_;
- }
-
- bool empty()
- {
- return tail_ == head_;
- }
-
- bool full()
- {
- // head is ahead of the tail by 1
- return ((tail_ + 1) % max_items_) == head_;
- }
-
- size_t overrun_counter() const
- {
- return overrun_counter_;
- }
-
-private:
- size_t max_items_;
- typename std::vector::size_type head_ = 0;
- typename std::vector::size_type tail_ = 0;
-
- std::vector v_;
-
- size_t overrun_counter_ = 0;
-};
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/console_globals.h b/external/spdlog/details/console_globals.h
deleted file mode 100644
index e2afb6bf0107e7dea4956f20ac811017d70396c3..0000000000000000000000000000000000000000
--- a/external/spdlog/details/console_globals.h
+++ /dev/null
@@ -1,74 +0,0 @@
-#pragma once
-//
-// Copyright(c) 2018 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#include "spdlog/details/null_mutex.h"
-#include
-#include
-
-#ifdef _WIN32
-
-#ifndef NOMINMAX
-#define NOMINMAX // prevent windows redefining min/max
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include
-#endif
-
-namespace spdlog {
-namespace details {
-struct console_stdout
-{
- static std::FILE *stream()
- {
- return stdout;
- }
-#ifdef _WIN32
- static HANDLE handle()
- {
- return ::GetStdHandle(STD_OUTPUT_HANDLE);
- }
-#endif
-};
-
-struct console_stderr
-{
- static std::FILE *stream()
- {
- return stderr;
- }
-#ifdef _WIN32
- static HANDLE handle()
- {
- return ::GetStdHandle(STD_ERROR_HANDLE);
- }
-#endif
-};
-
-struct console_mutex
-{
- using mutex_t = std::mutex;
- static mutex_t &mutex()
- {
- static mutex_t s_mutex;
- return s_mutex;
- }
-};
-
-struct console_nullmutex
-{
- using mutex_t = null_mutex;
- static mutex_t &mutex()
- {
- static mutex_t s_mutex;
- return s_mutex;
- }
-};
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/file_helper.h b/external/spdlog/details/file_helper.h
deleted file mode 100644
index 8c1132d9c5e9ff02fa27b43ceeb2cc9a887f4141..0000000000000000000000000000000000000000
--- a/external/spdlog/details/file_helper.h
+++ /dev/null
@@ -1,152 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-// Helper class for file sinks.
-// When failing to open a file, retry several times(5) with a delay interval(10 ms).
-// Throw spdlog_ex exception on errors.
-
-#include "spdlog/details/log_msg.h"
-#include "spdlog/details/os.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace spdlog {
-namespace details {
-
-class file_helper
-{
-
-public:
- const int open_tries = 5;
- const int open_interval = 10;
-
- explicit file_helper() = default;
-
- file_helper(const file_helper &) = delete;
- file_helper &operator=(const file_helper &) = delete;
-
- ~file_helper()
- {
- close();
- }
-
- void open(const filename_t &fname, bool truncate = false)
- {
- close();
- auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
- _filename = fname;
- for (int tries = 0; tries < open_tries; ++tries)
- {
- if (!os::fopen_s(&fd_, fname, mode))
- {
- return;
- }
-
- details::os::sleep_for_millis(open_interval);
- }
-
- throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
- }
-
- void reopen(bool truncate)
- {
- if (_filename.empty())
- {
- throw spdlog_ex("Failed re opening file - was not opened before");
- }
- open(_filename, truncate);
- }
-
- void flush()
- {
- std::fflush(fd_);
- }
-
- void close()
- {
- if (fd_ != nullptr)
- {
- std::fclose(fd_);
- fd_ = nullptr;
- }
- }
-
- void write(const fmt::memory_buffer &buf)
- {
- size_t msg_size = buf.size();
- auto data = buf.data();
- if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
- {
- throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
- }
- }
-
- size_t size() const
- {
- if (fd_ == nullptr)
- {
- throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
- }
- return os::filesize(fd_);
- }
-
- const filename_t &filename() const
- {
- return _filename;
- }
-
- static bool file_exists(const filename_t &fname)
- {
- return os::file_exists(fname);
- }
-
- //
- // return file path and its extension:
- //
- // "mylog.txt" => ("mylog", ".txt")
- // "mylog" => ("mylog", "")
- // "mylog." => ("mylog.", "")
- // "/dir1/dir2/mylog.txt" => ("/dir1/dir2/mylog", ".txt")
- //
- // the starting dot in filenames is ignored (hidden files):
- //
- // ".mylog" => (".mylog". "")
- // "my_folder/.mylog" => ("my_folder/.mylog", "")
- // "my_folder/.mylog.txt" => ("my_folder/.mylog", ".txt")
- static std::tuple split_by_extension(const spdlog::filename_t &fname)
- {
- auto ext_index = fname.rfind('.');
-
- // no valid extension found - return whole path and empty string as
- // extension
- if (ext_index == filename_t::npos || ext_index == 0 || ext_index == fname.size() - 1)
- {
- return std::make_tuple(fname, spdlog::filename_t());
- }
-
- // treat casese like "/etc/rc.d/somelogfile or "/abc/.hiddenfile"
- auto folder_index = fname.rfind(details::os::folder_sep);
- if (folder_index != filename_t::npos && folder_index >= ext_index - 1)
- {
- return std::make_tuple(fname, spdlog::filename_t());
- }
-
- // finally - return a valid base and extension tuple
- return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
- }
-
-private:
- std::FILE *fd_{nullptr};
- filename_t _filename;
-};
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/fmt_helper.h b/external/spdlog/details/fmt_helper.h
deleted file mode 100644
index d76aac452c2f6f88195df83594aef949c3e96ecf..0000000000000000000000000000000000000000
--- a/external/spdlog/details/fmt_helper.h
+++ /dev/null
@@ -1,122 +0,0 @@
-//
-// Created by gabi on 6/15/18.
-//
-
-#pragma once
-
-#include
-#include
-#include "spdlog/fmt/fmt.h"
-
-// Some fmt helpers to efficiently format and pad ints and strings
-namespace spdlog {
-namespace details {
-namespace fmt_helper {
-
-template
-inline spdlog::string_view_t to_string_view(const fmt::basic_memory_buffer &buf) SPDLOG_NOEXCEPT
-{
- return spdlog::string_view_t(buf.data(), buf.size());
-}
-
-template
-inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest)
-{
- auto *buf_ptr = buf.data();
- dest.append(buf_ptr, buf_ptr + buf.size());
-}
-
-template
-inline void append_string_view(spdlog::string_view_t view, fmt::basic_memory_buffer &dest)
-{
- auto *buf_ptr = view.data();
- if (buf_ptr != nullptr)
- {
- dest.append(buf_ptr, buf_ptr + view.size());
- }
-}
-
-template
-inline void append_int(T n, fmt::basic_memory_buffer &dest)
-{
- fmt::format_int i(n);
- dest.append(i.data(), i.data() + i.size());
-}
-
-template
-inline unsigned count_digits(T n)
-{
- using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
- return static_cast(fmt::internal::count_digits(static_cast(n)));
-}
-
-template
-inline void pad2(int n, fmt::basic_memory_buffer &dest)
-{
- if (n > 99)
- {
- append_int(n, dest);
- }
- else if (n > 9) // 10-99
- {
- dest.push_back(static_cast('0' + n / 10));
- dest.push_back(static_cast('0' + n % 10));
- }
- else if (n >= 0) // 0-9
- {
- dest.push_back('0');
- dest.push_back(static_cast('0' + n));
- }
- else // negatives (unlikely, but just in case, let fmt deal with it)
- {
- fmt::format_to(dest, "{:02}", n);
- }
-}
-
-template
-inline void pad_uint(T n, unsigned int width, fmt::basic_memory_buffer &dest)
-{
- static_assert(std::is_unsigned::value, "pad_uint must get unsigned T");
- auto digits = count_digits(n);
- if (width > digits)
- {
- const char *zeroes = "0000000000000000000";
- dest.append(zeroes, zeroes + width - digits);
- }
- append_int(n, dest);
-}
-
-template
-inline void pad3(T n, fmt::basic_memory_buffer &dest)
-{
- pad_uint(n, 3, dest);
-}
-
-template
-inline void pad6(T n, fmt::basic_memory_buffer &dest)
-{
- pad_uint(n, 6, dest);
-}
-
-template
-inline void pad9(T n, fmt::basic_memory_buffer &dest)
-{
- pad_uint(n, 9, dest);
-}
-
-// return fraction of a second of the given time_point.
-// e.g.
-// fraction(tp) -> will return the millis part of the second
-template
-inline ToDuration time_fraction(const log_clock::time_point &tp)
-{
- using std::chrono::duration_cast;
- using std::chrono::seconds;
- auto duration = tp.time_since_epoch();
- auto secs = duration_cast(duration);
- return duration_cast(duration) - duration_cast(secs);
-}
-
-} // namespace fmt_helper
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/log_msg.h b/external/spdlog/details/log_msg.h
deleted file mode 100644
index 69422ba378a410386904012121a5f4b5cb9bfbe2..0000000000000000000000000000000000000000
--- a/external/spdlog/details/log_msg.h
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-#include "spdlog/common.h"
-#include "spdlog/details/os.h"
-
-#include
-#include
-
-namespace spdlog {
-namespace details {
-struct log_msg
-{
-
- log_msg(source_loc loc, const std::string *loggers_name, level::level_enum lvl, string_view_t view)
- : logger_name(loggers_name)
- , level(lvl)
-#ifndef SPDLOG_NO_DATETIME
- , time(os::now())
-#endif
-
-#ifndef SPDLOG_NO_THREAD_ID
- , thread_id(os::thread_id())
-#endif
- , source(loc)
- , payload(view)
- {
- }
-
- log_msg(const std::string *loggers_name, level::level_enum lvl, string_view_t view)
- : log_msg(source_loc{}, loggers_name, lvl, view)
- {
- }
-
- log_msg(const log_msg &other) = default;
-
- const std::string *logger_name{nullptr};
- level::level_enum level{level::off};
- log_clock::time_point time;
- size_t thread_id{0};
- size_t msg_id{0};
-
- // wrapping the formatted text with color (updated by pattern_formatter).
- mutable size_t color_range_start{0};
- mutable size_t color_range_end{0};
-
- source_loc source;
- const string_view_t payload;
-};
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/logger_impl.h b/external/spdlog/details/logger_impl.h
deleted file mode 100644
index 0212ede5364de9149abf2bb3b2b5a5656e100873..0000000000000000000000000000000000000000
--- a/external/spdlog/details/logger_impl.h
+++ /dev/null
@@ -1,441 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-#include "spdlog/details/fmt_helper.h"
-
-#include
-#include
-
-#define SPDLOG_CATCH_AND_HANDLE \
- catch (const std::exception &ex) \
- { \
- err_handler_(ex.what()); \
- } \
- catch (...) \
- { \
- err_handler_("Unknown exception in logger"); \
- }
-
-// create logger with given name, sinks and the default pattern formatter
-// all other ctors will call this one
-template
-inline spdlog::logger::logger(std::string logger_name, It begin, It end)
- : name_(std::move(logger_name))
- , sinks_(begin, end)
-{
-}
-
-// ctor with sinks as init list
-inline spdlog::logger::logger(std::string logger_name, sinks_init_list sinks_list)
- : logger(std::move(logger_name), sinks_list.begin(), sinks_list.end())
-{
-}
-
-// ctor with single sink
-inline spdlog::logger::logger(std::string logger_name, spdlog::sink_ptr single_sink)
- : logger(std::move(logger_name), {std::move(single_sink)})
-{
-}
-
-inline spdlog::logger::~logger() = default;
-
-inline void spdlog::logger::set_formatter(std::unique_ptr f)
-{
- for (auto &sink : sinks_)
- {
- sink->set_formatter(f->clone());
- }
-}
-
-inline void spdlog::logger::set_pattern(std::string pattern, pattern_time_type time_type)
-{
- auto new_formatter = details::make_unique(std::move(pattern), time_type);
- set_formatter(std::move(new_formatter));
-}
-
-template
-inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *fmt, const Args &... args)
-{
- if (!should_log(lvl))
- {
- return;
- }
-
- try
- {
- using details::fmt_helper::to_string_view;
- fmt::memory_buffer buf;
- fmt::format_to(buf, fmt, args...);
- details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
- sink_it_(log_msg);
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-template
-inline void spdlog::logger::log(level::level_enum lvl, const char *fmt, const Args &... args)
-{
- log(source_loc{}, lvl, fmt, args...);
-}
-
-inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const char *msg)
-{
- if (!should_log(lvl))
- {
- return;
- }
-
- try
- {
- details::log_msg log_msg(source, &name_, lvl, spdlog::string_view_t(msg));
- sink_it_(log_msg);
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-inline void spdlog::logger::log(level::level_enum lvl, const char *msg)
-{
- log(source_loc{}, lvl, msg);
-}
-
-template::value, T>::type *>
-inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
-{
- if (!should_log(lvl))
- {
- return;
- }
- try
- {
- details::log_msg log_msg(source, &name_, lvl, msg);
- sink_it_(log_msg);
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-template::value, T>::type *>
-inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
-{
- log(source_loc{}, lvl, msg);
-}
-
-template::value, T>::type *>
-inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const T &msg)
-{
- if (!should_log(lvl))
- {
- return;
- }
- try
- {
- using details::fmt_helper::to_string_view;
- fmt::memory_buffer buf;
- fmt::format_to(buf, "{}", msg);
- details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
- sink_it_(log_msg);
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-template::value, T>::type *>
-inline void spdlog::logger::log(level::level_enum lvl, const T &msg)
-{
- log(source_loc{}, lvl, msg);
-}
-
-template
-inline void spdlog::logger::trace(const char *fmt, const Args &... args)
-{
- log(level::trace, fmt, args...);
-}
-
-template
-inline void spdlog::logger::debug(const char *fmt, const Args &... args)
-{
- log(level::debug, fmt, args...);
-}
-
-template
-inline void spdlog::logger::info(const char *fmt, const Args &... args)
-{
- log(level::info, fmt, args...);
-}
-
-template
-inline void spdlog::logger::warn(const char *fmt, const Args &... args)
-{
- log(level::warn, fmt, args...);
-}
-
-template
-inline void spdlog::logger::error(const char *fmt, const Args &... args)
-{
- log(level::err, fmt, args...);
-}
-
-template
-inline void spdlog::logger::critical(const char *fmt, const Args &... args)
-{
- log(level::critical, fmt, args...);
-}
-
-template
-inline void spdlog::logger::trace(const T &msg)
-{
- log(level::trace, msg);
-}
-
-template
-inline void spdlog::logger::debug(const T &msg)
-{
- log(level::debug, msg);
-}
-
-template
-inline void spdlog::logger::info(const T &msg)
-{
- log(level::info, msg);
-}
-
-template
-inline void spdlog::logger::warn(const T &msg)
-{
- log(level::warn, msg);
-}
-
-template
-inline void spdlog::logger::error(const T &msg)
-{
- log(level::err, msg);
-}
-
-template
-inline void spdlog::logger::critical(const T &msg)
-{
- log(level::critical, msg);
-}
-
-#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
-
-inline void wbuf_to_utf8buf(const fmt::wmemory_buffer &wbuf, fmt::memory_buffer &target)
-{
- int wbuf_size = static_cast(wbuf.size());
- if (wbuf_size == 0)
- {
- return;
- }
-
- auto result_size = ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, NULL, 0, NULL, NULL);
-
- if (result_size > 0)
- {
- target.resize(result_size);
- ::WideCharToMultiByte(CP_UTF8, 0, wbuf.data(), wbuf_size, &target.data()[0], result_size, NULL, NULL);
- }
- else
- {
- throw spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
- }
-}
-
-template
-inline void spdlog::logger::log(source_loc source, level::level_enum lvl, const wchar_t *fmt, const Args &... args)
-{
- if (!should_log(lvl))
- {
- return;
- }
-
- try
- {
- // format to wmemory_buffer and convert to utf8
- using details::fmt_helper::to_string_view;
- fmt::wmemory_buffer wbuf;
- fmt::format_to(wbuf, fmt, args...);
- fmt::memory_buffer buf;
- wbuf_to_utf8buf(wbuf, buf);
- details::log_msg log_msg(source, &name_, lvl, to_string_view(buf));
- sink_it_(log_msg);
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-template
-inline void spdlog::logger::log(level::level_enum lvl, const wchar_t *fmt, const Args &... args)
-{
- log(source_loc{}, lvl, fmt, args...);
-}
-
-template
-inline void spdlog::logger::trace(const wchar_t *fmt, const Args &... args)
-{
- log(level::trace, fmt, args...);
-}
-
-template
-inline void spdlog::logger::debug(const wchar_t *fmt, const Args &... args)
-{
- log(level::debug, fmt, args...);
-}
-
-template
-inline void spdlog::logger::info(const wchar_t *fmt, const Args &... args)
-{
- log(level::info, fmt, args...);
-}
-
-template
-inline void spdlog::logger::warn(const wchar_t *fmt, const Args &... args)
-{
- log(level::warn, fmt, args...);
-}
-
-template
-inline void spdlog::logger::error(const wchar_t *fmt, const Args &... args)
-{
- log(level::err, fmt, args...);
-}
-
-template
-inline void spdlog::logger::critical(const wchar_t *fmt, const Args &... args)
-{
- log(level::critical, fmt, args...);
-}
-
-#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
-
-//
-// name and level
-//
-inline const std::string &spdlog::logger::name() const
-{
- return name_;
-}
-
-inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
-{
- level_.store(log_level);
-}
-
-inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
-{
- err_handler_ = std::move(err_handler);
-}
-
-inline spdlog::log_err_handler spdlog::logger::error_handler() const
-{
- return err_handler_;
-}
-
-inline void spdlog::logger::flush()
-{
- try
- {
- flush_();
- }
- SPDLOG_CATCH_AND_HANDLE
-}
-
-inline void spdlog::logger::flush_on(level::level_enum log_level)
-{
- flush_level_.store(log_level);
-}
-
-inline spdlog::level::level_enum spdlog::logger::flush_level() const
-{
- return static_cast(flush_level_.load(std::memory_order_relaxed));
-}
-
-inline bool spdlog::logger::should_flush_(const details::log_msg &msg)
-{
- auto flush_level = flush_level_.load(std::memory_order_relaxed);
- return (msg.level >= flush_level) && (msg.level != level::off);
-}
-
-inline spdlog::level::level_enum spdlog::logger::default_level()
-{
- return static_cast(SPDLOG_ACTIVE_LEVEL);
-}
-
-inline spdlog::level::level_enum spdlog::logger::level() const
-{
- return static_cast(level_.load(std::memory_order_relaxed));
-}
-
-inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
-{
- return msg_level >= level_.load(std::memory_order_relaxed);
-}
-
-//
-// protected virtual called at end of each user log call (if enabled) by the
-// line_logger
-//
-inline void spdlog::logger::sink_it_(details::log_msg &msg)
-{
-#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
- incr_msg_counter_(msg);
-#endif
- for (auto &sink : sinks_)
- {
- if (sink->should_log(msg.level))
- {
- sink->log(msg);
- }
- }
-
- if (should_flush_(msg))
- {
- flush_();
- }
-}
-
-inline void spdlog::logger::flush_()
-{
- for (auto &sink : sinks_)
- {
- sink->flush();
- }
-}
-
-inline void spdlog::logger::default_err_handler_(const std::string &msg)
-{
- auto now = time(nullptr);
- if (now - last_err_time_ < 60)
- {
- return;
- }
- last_err_time_ = now;
- auto tm_time = details::os::localtime(now);
- char date_buf[100];
- std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
- fmt::print(stderr, "[*** LOG ERROR ***] [{}] [{}] {}\n", date_buf, name(), msg);
-}
-
-inline void spdlog::logger::incr_msg_counter_(details::log_msg &msg)
-{
- msg.msg_id = msg_counter_.fetch_add(1, std::memory_order_relaxed);
-}
-
-inline const std::vector &spdlog::logger::sinks() const
-{
- return sinks_;
-}
-
-inline std::vector &spdlog::logger::sinks()
-{
- return sinks_;
-}
-
-inline std::shared_ptr spdlog::logger::clone(std::string logger_name)
-{
- auto cloned = std::make_shared(std::move(logger_name), sinks_.begin(), sinks_.end());
- cloned->set_level(this->level());
- cloned->flush_on(this->flush_level());
- cloned->set_error_handler(this->error_handler());
- return cloned;
-}
diff --git a/external/spdlog/details/mpmc_blocking_q.h b/external/spdlog/details/mpmc_blocking_q.h
deleted file mode 100644
index ca789fc660e11554410f81e422c519760234e7b2..0000000000000000000000000000000000000000
--- a/external/spdlog/details/mpmc_blocking_q.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#pragma once
-
-//
-// Copyright(c) 2018 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-// multi producer-multi consumer blocking queue.
-// enqueue(..) - will block until room found to put the new message.
-// enqueue_nowait(..) - will return immediately with false if no room left in
-// the queue.
-// dequeue_for(..) - will block until the queue is not empty or timeout have
-// passed.
-
-#include "spdlog/details/circular_q.h"
-
-#include
-#include
-
-namespace spdlog {
-namespace details {
-
-template
-class mpmc_blocking_queue
-{
-public:
- using item_type = T;
- explicit mpmc_blocking_queue(size_t max_items)
- : q_(max_items)
- {
- }
-
-#ifndef __MINGW32__
- // try to enqueue and block if no room left
- void enqueue(T &&item)
- {
- {
- std::unique_lock lock(queue_mutex_);
- pop_cv_.wait(lock, [this] { return !this->q_.full(); });
- q_.push_back(std::move(item));
- }
- push_cv_.notify_one();
- }
-
- // enqueue immediately. overrun oldest message in the queue if no room left.
- void enqueue_nowait(T &&item)
- {
- {
- std::unique_lock lock(queue_mutex_);
- q_.push_back(std::move(item));
- }
- push_cv_.notify_one();
- }
-
- // try to dequeue item. if no item found. wait upto timeout and try again
- // Return true, if succeeded dequeue item, false otherwise
- bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)
- {
- {
- std::unique_lock lock(queue_mutex_);
- if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))
- {
- return false;
- }
- q_.pop_front(popped_item);
- }
- pop_cv_.notify_one();
- return true;
- }
-
-#else
- // apparently mingw deadlocks if the mutex is released before cv.notify_one(),
- // so release the mutex at the very end each function.
-
- // try to enqueue and block if no room left
- void enqueue(T &&item)
- {
- std::unique_lock lock(queue_mutex_);
- pop_cv_.wait(lock, [this] { return !this->q_.full(); });
- q_.push_back(std::move(item));
- push_cv_.notify_one();
- }
-
- // enqueue immediately. overrun oldest message in the queue if no room left.
- void enqueue_nowait(T &&item)
- {
- std::unique_lock lock(queue_mutex_);
- q_.push_back(std::move(item));
- push_cv_.notify_one();
- }
-
- // try to dequeue item. if no item found. wait upto timeout and try again
- // Return true, if succeeded dequeue item, false otherwise
- bool dequeue_for(T &popped_item, std::chrono::milliseconds wait_duration)
- {
- std::unique_lock lock(queue_mutex_);
- if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); }))
- {
- return false;
- }
- q_.pop_front(popped_item);
- pop_cv_.notify_one();
- return true;
- }
-
-#endif
-
- size_t overrun_counter()
- {
- std::unique_lock lock(queue_mutex_);
- return q_.overrun_counter();
- }
-
-private:
- std::mutex queue_mutex_;
- std::condition_variable push_cv_;
- std::condition_variable pop_cv_;
- spdlog::details::circular_q q_;
-};
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/null_mutex.h b/external/spdlog/details/null_mutex.h
deleted file mode 100644
index 3f495bd98a36ad48174a0e0e51acf73f670d9952..0000000000000000000000000000000000000000
--- a/external/spdlog/details/null_mutex.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-
-#pragma once
-
-#include
-// null, no cost dummy "mutex" and dummy "atomic" int
-
-namespace spdlog {
-namespace details {
-struct null_mutex
-{
- void lock() {}
- void unlock() {}
- bool try_lock()
- {
- return true;
- }
-};
-
-struct null_atomic_int
-{
- int value;
- null_atomic_int() = default;
-
- explicit null_atomic_int(int val)
- : value(val)
- {
- }
-
- int load(std::memory_order) const
- {
- return value;
- }
-
- void store(int val)
- {
- value = val;
- }
-};
-
-} // namespace details
-} // namespace spdlog
diff --git a/external/spdlog/details/os.h b/external/spdlog/details/os.h
deleted file mode 100644
index 646805e608c4563ed2cc73d10c9b3b24d7c71bc7..0000000000000000000000000000000000000000
--- a/external/spdlog/details/os.h
+++ /dev/null
@@ -1,421 +0,0 @@
-//
-// Copyright(c) 2015 Gabi Melman.
-// Distributed under the MIT License (http://opensource.org/licenses/MIT)
-//
-#pragma once
-
-#include "../common.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#ifdef _WIN32
-
-#ifndef NOMINMAX
-#define NOMINMAX // prevent windows redefining min/max
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include // _get_osfhandle and _isatty support
-#include // _get_pid support
-#include
-
-#ifdef __MINGW32__
-#include
-#endif
-
-#else // unix
-
-#include
-#include
-
-#ifdef __linux__
-#include //Use gettid() syscall under linux to get thread id
-
-#elif __FreeBSD__
-#include //Use thr_self() syscall under FreeBSD to get thread id
-#endif
-
-#endif // unix
-
-#ifndef __has_feature // Clang - feature checking macros.
-#define __has_feature(x) 0 // Compatibility with non-clang compilers.
-#endif
-
-namespace spdlog {
-namespace details {
-namespace os {
-
-inline spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT
-{
-
-#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
- timespec ts;
- ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
- return std::chrono::time_point(
- std::chrono::duration_cast(std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
-
-#else
- return log_clock::now();
-#endif
-}
-inline std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT
-{
-
-#ifdef _WIN32
- std::tm tm;
- localtime_s(&tm, &time_tt);
-#else
- std::tm tm;
- localtime_r(&time_tt, &tm);
-#endif
- return tm;
-}
-
-inline std::tm localtime() SPDLOG_NOEXCEPT
-{
- std::time_t now_t = time(nullptr);
- return localtime(now_t);
-}
-
-inline std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT
-{
-
-#ifdef _WIN32
- std::tm tm;
- gmtime_s(&tm, &time_tt);
-#else
- std::tm tm;
- gmtime_r(&time_tt, &tm);
-#endif
- return tm;
-}
-
-inline std::tm gmtime() SPDLOG_NOEXCEPT
-{
- std::time_t now_t = time(nullptr);
- return gmtime(now_t);
-}
-
-// eol definition
-#if !defined(SPDLOG_EOL)
-#ifdef _WIN32
-#define SPDLOG_EOL "\r\n"
-#else
-#define SPDLOG_EOL "\n"
-#endif
-#endif
-
-SPDLOG_CONSTEXPR static const char *default_eol = SPDLOG_EOL;
-
-// folder separator
-#ifdef _WIN32
-SPDLOG_CONSTEXPR static const char folder_sep = '\\';
-#else
-SPDLOG_CONSTEXPR static const char folder_sep = '/';
-#endif
-
-inline void prevent_child_fd(FILE *f)
-{
-
-#ifdef _WIN32
-#if !defined(__cplusplus_winrt)
- auto file_handle = (HANDLE)_get_osfhandle(_fileno(f));
- if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
- throw spdlog_ex("SetHandleInformation failed", errno);
-#endif
-#else
- auto fd = fileno(f);
- if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
- {
- throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno);
- }
-#endif
-}
-
-// fopen_s on non windows for writing
-inline bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode)
-{
-#ifdef _WIN32
-#ifdef SPDLOG_WCHAR_FILENAMES
- *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
-#else
- *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
-#endif
-#else // unix
- *fp = fopen((filename.c_str()), mode.c_str());
-#endif
-
-#ifdef SPDLOG_PREVENT_CHILD_FD
- if (*fp != nullptr)
- {
- prevent_child_fd(*fp);
- }
-#endif
- return *fp == nullptr;
-}
-
-inline int remove(const filename_t &filename) SPDLOG_NOEXCEPT
-{
-#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
- return _wremove(filename.c_str());
-#else
- return std::remove(filename.c_str());
-#endif
-}
-
-inline int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT
-{
-#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
- return _wrename(filename1.c_str(), filename2.c_str());
-#else
- return std::rename(filename1.c_str(), filename2.c_str());
-#endif
-}
-
-// Return if file exists
-inline bool file_exists(const filename_t &filename) SPDLOG_NOEXCEPT
-{
-#ifdef _WIN32
-#ifdef SPDLOG_WCHAR_FILENAMES
- auto attribs = GetFileAttributesW(filename.c_str());
-#else
- auto attribs = GetFileAttributesA(filename.c_str());
-#endif
- return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
-#else // common linux/unix all have the stat system call
- struct stat buffer;
- return (stat(filename.c_str(), &buffer) == 0);
-#endif
-}
-
-// Return file size according to open FILE* object
-inline size_t filesize(FILE *f)
-{
- if (f == nullptr)
- {
- throw spdlog_ex("Failed getting file size. fd is null");
- }
-#if defined(_WIN32) && !defined(__CYGWIN__)
- int fd = _fileno(f);
-#if _WIN64 // 64 bits
- __int64 ret = _filelengthi64(fd);
- if (ret >= 0)
- {
- return static_cast(ret);
- }
-
-#else // windows 32 bits
- long ret = _filelength(fd);
- if (ret >= 0)
- {
- return static_cast(ret);
- }
-#endif
-
-#else // unix
- int fd = fileno(f);
-// 64 bits(but not in osx or cygwin, where fstat64 is deprecated)
-#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__)
- struct stat64 st;
- if (fstat64(fd, &st) == 0)
- {
- return static_cast(st.st_size);
- }
-#else // unix 32 bits or cygwin
- struct stat st;
-
- if (fstat(fd, &st) == 0)
- {
- return static_cast(st.st_size);
- }
-#endif
-#endif
- throw spdlog_ex("Failed getting file size from fd", errno);
-}
-
-// Return utc offset in minutes or throw spdlog_ex on failure
-inline int utc_minutes_offset(const std::tm &tm = details::os::localtime())
-{
-
-#ifdef _WIN32
-#if _WIN32_WINNT < _WIN32_WINNT_WS08
- TIME_ZONE_INFORMATION tzinfo;
- auto rv = GetTimeZoneInformation(&tzinfo);
-#else
- DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
- auto rv = GetDynamicTimeZoneInformation(&tzinfo);
-#endif
- if (rv == TIME_ZONE_ID_INVALID)
- throw spdlog::spdlog_ex("Failed getting timezone info. ", errno);
-
- int offset = -tzinfo.Bias;
- if (tm.tm_isdst)
- {
- offset -= tzinfo.DaylightBias;
- }
- else
- {
- offset -= tzinfo.StandardBias;
- }
- return offset;
-#else
-
-#if defined(sun) || defined(__sun) || defined(_AIX)
- // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
- struct helper
- {
- static long int calculate_gmt_offset(const std::tm &localtm = details::os::localtime(), const std::tm &gmtm = details::os::gmtime())
- {
- int local_year = localtm.tm_year + (1900 - 1);
- int gmt_year = gmtm.tm_year + (1900 - 1);
-
- long int days = (
- // difference in day of year
- localtm.tm_yday -
- gmtm.tm_yday
-
- // + intervening leap days
- + ((local_year >> 2) - (gmt_year >> 2)) - (local_year / 100 - gmt_year / 100) +
- ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
-
- // + difference in years * 365 */
- + (long int)(local_year - gmt_year) * 365);
-
- long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);
- long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);
- long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec);
-
- return secs;
- }
- };
-
- auto offset_seconds = helper::calculate_gmt_offset(tm);
-#else
- auto offset_seconds = tm.tm_gmtoff;
-#endif
-
- return static_cast(offset_seconds / 60);
-#endif
-}
-
-// Return current thread id as size_t
-// It exists because the std::this_thread::get_id() is much slower(especially
-// under VS 2013)
-inline size_t _thread_id() SPDLOG_NOEXCEPT
-{
-#ifdef _WIN32
- return static_cast(::GetCurrentThreadId());
-#elif __linux__
-#if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
-#define SYS_gettid __NR_gettid
-#endif
- return static_cast(syscall(SYS_gettid));
-#elif __FreeBSD__
- long tid;
- thr_self(&tid);
- return static_cast(tid);
-#elif __APPLE__
- uint64_t tid;
- pthread_threadid_np(nullptr, &tid);
- return static_cast(tid);
-#else // Default to standard C++11 (other Unix)
- return static_cast