Merge 10.0-serg -> 10.0

This commit is contained in:
Sergey Petrunya 2013-08-07 17:21:37 +04:00
commit a3d79f2e58
1488 changed files with 126487 additions and 46392 deletions

View File

@ -165,8 +165,7 @@ valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max"
valgrind_configs="--with-valgrind"
#
# Used in -debug builds
debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG"
debug_cflags="$debug_cflags -DSAFE_MUTEX -DSAFEMALLOC"
debug_cflags="-DEXTRA_DEBUG -DSAFE_MUTEX -DSAFEMALLOC"
error_inject="--with-error-inject "
#
# Base C++ flags for all builds

View File

@ -139,7 +139,9 @@ INCLUDE(cpack_rpm)
# Add macros
INCLUDE(character_sets)
INCLUDE(cpu_info)
INCLUDE(zlib)
INCLUDE(libevent)
INCLUDE(ssl)
INCLUDE(readline)
INCLUDE(libutils)
@ -204,7 +206,7 @@ ENDFOREACH()
# Add safemutex for debug configurations, except on Windows
# (safemutex has never worked on Windows)
IF(NOT WIN32)
IF(NOT WIN32 AND NOT WITH_INNODB_MEMCACHED)
FOREACH(LANG C CXX)
SET(CMAKE_${LANG}_FLAGS_DEBUG "${CMAKE_${LANG}_FLAGS_DEBUG} -DSAFE_MUTEX")
ENDFOREACH()
@ -256,10 +258,12 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
# Add bundled or system zlib.
MYSQL_CHECK_ZLIB_WITH_COMPRESS()
# Optionally add bundled yassl/taocrypt or system openssl.
# Add bundled yassl/taocrypt or system openssl.
MYSQL_CHECK_SSL()
# Add readline or libedit.
MYSQL_CHECK_READLINE()
# Add libevent
MYSQL_CHECK_LIBEVENT()
#
# Setup maintainer mode options. Platform checks are
@ -297,6 +301,7 @@ ADD_SUBDIRECTORY(strings)
ADD_SUBDIRECTORY(vio)
ADD_SUBDIRECTORY(regex)
ADD_SUBDIRECTORY(mysys)
ADD_SUBDIRECTORY(mysys_ssl)
ADD_SUBDIRECTORY(libmysql)
ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(extra)

7
TODO
View File

@ -32,12 +32,10 @@ Short time TODO:
- add support for host_error()
- Enable performance_schema.host_cache in scripts/mysql_system_tables.sql
- Add full support for automatic timestamp.
(remove timestamp handling from ha_write())
- Timour is working on this
- Add Sys_my_bind_addr(); Needed for perfschema
- Add support for format_section_buff in unireg.cc and table.cc
- mysql_socket_shutdown() was removed from vio/viosocket.cc.
It was replaced with inline function in include/mysql/psi/mysql_socket.h
but this doesn't call DisconnectEx(). We should check if we need to
@ -60,4 +58,3 @@ Sergei's notes:
rpl_slave.cc
XXX in mysql_client_test
net_serv.cc

View File

@ -15,6 +15,7 @@
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/mysys_ssl
${ZLIB_INCLUDE_DIR}
${SSL_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/libmysql
@ -25,6 +26,9 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_BINARY_DIR}
)
## We will need libeay32.dll and ssleay32.dll when running client executables.
COPY_OPENSSL_DLLS(copy_openssl_client)
ADD_DEFINITIONS(${SSL_DEFINES})
MYSQL_ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc
${CMAKE_SOURCE_DIR}/sql/sql_string.cc)
@ -78,7 +82,7 @@ ENDIF(WIN32)
ADD_EXECUTABLE(async_example async_example.c)
TARGET_LINK_LIBRARIES(async_example mysqlclient)
SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin
SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap mysql_plugin async_example
PROPERTIES HAS_CXX TRUE)
ADD_DEFINITIONS(-DHAVE_DLOPEN)

View File

@ -3504,9 +3504,9 @@ print_table_data(MYSQL_RES *result)
{
uint length= column_names ? field->name_length : 0;
if (quick)
length=max(length,field->length);
length= MY_MAX(length,field->length);
else
length=max(length,field->max_length);
length= MY_MAX(length,field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length=4; // Room for "NULL"
field->max_length=length;
@ -3526,8 +3526,8 @@ print_table_data(MYSQL_RES *result)
field->name,
field->name + name_length);
uint display_length= field->max_length + name_length - numcells;
tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
MAX_COLUMN_LENGTH),
tee_fprintf(PAGER, " %-*s |",(int) MY_MIN(display_length,
MAX_COLUMN_LENGTH),
field->name);
num_flag[off]= IS_NUM(field->type);
}
@ -3616,9 +3616,9 @@ static int get_field_disp_length(MYSQL_FIELD *field)
uint length= column_names ? field->name_length : 0;
if (quick)
length= max(length, field->length);
length= MY_MAX(length, field->length);
else
length= max(length, field->max_length);
length= MY_MAX(length, field->max_length);
if (length < 4 && !IS_NOT_NULL(field->flags))
length= 4; /* Room for "NULL" */
@ -3634,6 +3634,7 @@ static int get_field_disp_length(MYSQL_FIELD *field)
@returns The max number of characters in any row of this result
*/
static int get_result_width(MYSQL_RES *result)
{
unsigned int len= 0;

View File

@ -585,7 +585,7 @@ static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value)
if ((value_end= strchr(value_start, '\n')) == NULL)
return 1; /* Unexpected result */
len= (size_t) min(FN_REFLEN, value_end-value_start);
len= (size_t) MY_MIN(FN_REFLEN, value_end-value_start);
strncpy(value, value_start, len);
value[len]= '\0';
return 0;

View File

@ -23,7 +23,8 @@
#include <sys/stat.h>
#include <mysql.h>
#include <sql_common.h>
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
#include <welcome_copyright_notice.h>
#include <my_rnd.h>
#define ADMIN_VERSION "9.1"
#define MAX_MYSQL_VAR 512

View File

@ -2345,7 +2345,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
my_off_t length,tmp;
for (length= start_position_mot ; length > 0 ; length-=tmp)
{
tmp=min(length,sizeof(buff));
tmp= MY_MIN(length,sizeof(buff));
if (my_b_read(file, buff, (uint) tmp))
{
error("Failed reading from file.");

View File

@ -784,8 +784,8 @@ static int handle_request_for_tables(char *tables, uint length)
org= ptr= strmov(strmov(query, op), " TABLE ");
ptr= fix_table_name(ptr, tables);
strmake(table_name_buff, org, min((int) sizeof(table_name_buff)-1,
(int) (ptr - org)));
strmake(table_name_buff, org, MY_MIN((int) sizeof(table_name_buff)-1,
(int) (ptr - org)));
table_name= table_name_buff;
ptr= strxmov(ptr, " ", options, NullS);
query_length= (uint) (ptr - query);

View File

@ -6485,9 +6485,9 @@ int read_line(char *buf, int size)
}
else if ((c == '{' &&
(!my_strnncoll_simple(charset_info, (const uchar*) "while", 5,
(uchar*) buf, min(5, p - buf), 0) ||
(uchar*) buf, MY_MIN(5, p - buf), 0) ||
!my_strnncoll_simple(charset_info, (const uchar*) "if", 2,
(uchar*) buf, min(2, p - buf), 0))))
(uchar*) buf, MY_MIN(2, p - buf), 0))))
{
/* Only if and while commands can be terminated by { */
*p++= c;

View File

@ -150,6 +150,16 @@ foreach my $option (@ARGV)
$cmakeargs = $cmakeargs." -DWITH_ZLIB=system";
next;
}
if($option =~ /with-libevent=/)
{
$cmakeargs = $cmakeargs." -DWITH_LIBEVENT=system";
next;
}
if($option =~ /with-libevent/)
{
$cmakeargs = $cmakeargs." -DWITH_LIBEVENT=bundled";
next;
}
if($option =~ /with-ssl=/)
{
$cmakeargs = $cmakeargs." -DWITH_SSL=yes";
@ -237,6 +247,16 @@ foreach my $option (@ARGV)
print("configure.pl : ignoring $option\n");
next;
}
if ($option =~ /with-client-ldflags/)
{
print("configure.pl : ignoring $option\n");
next;
}
if ($option =~ /with-mysqld-ldflags=/)
{
print("configure.pl : ignoring $option\n");
next;
}
$option = uc($option);
$option =~ s/-/_/g;

30
cmake/cpu_info.cmake Normal file
View File

@ -0,0 +1,30 @@
# Copyright (c) 2009, 2011, 2012 Oracle and/or its affiliates. All rights reserved.
#
# 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; version 2 of the License.
#
# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
# Symbols with information about the CPU.
FIND_PROGRAM(GETCONF getconf)
MARK_AS_ADVANCED(GETCONF)
IF(GETCONF)
EXECUTE_PROCESS(
COMMAND ${GETCONF} LEVEL1_DCACHE_LINESIZE
OUTPUT_VARIABLE CPU_LEVEL1_DCACHE_LINESIZE
)
ENDIF()
IF(CPU_LEVEL1_DCACHE_LINESIZE AND CPU_LEVEL1_DCACHE_LINESIZE GREATER 0)
ELSE()
SET(CPU_LEVEL1_DCACHE_LINESIZE 64)
ENDIF()

89
cmake/libevent.cmake Normal file
View File

@ -0,0 +1,89 @@
# Copyright (C) 2011 Oracle and/or its affiliates. All Rights Reserved.
#
# 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; version 2 of the License.
#
# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
MACRO (MYSQL_USE_BUNDLED_LIBEVENT)
SET(LIBEVENT_LIBRARY event)
SET(LIBEVENT_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/libevent)
SET(LIBEVENT_FOUND TRUE)
SET(WITH_LIBEVENT "bundled" CACHE STRING "Use bundled libevent")
ADD_SUBDIRECTORY(libevent)
GET_TARGET_PROPERTY(src libevent SOURCES)
FOREACH(file ${src})
SET(LIBEVENT_SOURCES ${LIBEVENT_SOURCES} ${CMAKE_SOURCE_DIR}/libevent/${file})
ENDFOREACH()
ENDMACRO()
# MYSQL_CHECK_LIBEVENT
#
# Provides the following configure options:
# WITH_LIBEVENT_BUNDLED
# If this is set,we use bindled libevent
# If this is not set,search for system libevent.
# if system libevent is not found, use bundled copy
# LIBEVENT_LIBRARIES, LIBEVENT_INCLUDE_DIR and LIBEVENT_SOURCES
# are set after this macro has run
MACRO (MYSQL_CHECK_LIBEVENT)
IF (NOT WITH_LIBEVENT)
SET(WITH_LIBEVENT "bundled" CACHE STRING "By default use bundled libevent on this platform")
ENDIF()
IF(WITH_LIBEVENT STREQUAL "bundled")
MYSQL_USE_BUNDLED_LIBEVENT()
ELSEIF(WITH_LIBEVENT STREQUAL "system" OR WITH_LIBEVENT STREQUAL "yes")
SET(LIBEVENT_FIND_QUIETLY TRUE)
IF (NOT LIBEVENT_INCLUDE_PATH)
set(LIBEVENT_INCLUDE_PATH /usr/local/include /opt/local/include)
ENDIF()
find_path(LIBEVENT_INCLUDE_DIR event.h PATHS ${LIBEVENT_INCLUDE_PATH})
if (NOT LIBEVENT_INCLUDE_DIR)
MESSAGE(SEND_ERROR "Cannot find appropriate event.h in /usr/local/include or /opt/local/include. Use bundled libevent")
endif()
IF (NOT LIBEVENT_LIB_PATHS)
set(LIBEVENT_LIB_PATHS /usr/local/lib /opt/local/lib)
ENDIF()
find_library(LIBEVENT_LIB event PATHS ${LIBEVENT_LIB_PATHS})
if (NOT LIBEVENT_LIB)
MESSAGE(SEND_ERROR "Cannot find appropriate event lib in /usr/local/lib or /opt/local/lib. Use bundled libevent")
endif()
IF (LIBEVENT_LIB AND LIBEVENT_INCLUDE_DIR)
set(LIBEVENT_FOUND TRUE)
set(LIBEVENT_LIBS ${LIBEVENT_LIB})
ELSE()
set(LIBEVENT_FOUND FALSE)
ENDIF()
IF(LIBEVENT_FOUND)
SET(LIBEVENT_SOURCES "")
SET(LIBEVENT_LIBRARIES ${LIBEVENT_LIBS})
SET(LIBEVENT_INCLUDE_DIRS ${LIBEVENT_INCLUDE_DIR})
SET(LIBEVENT_DEFINES "-DHAVE_LIBEVENT")
ELSE()
IF(WITH_LIBEVENT STREQUAL "system")
MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for libevent. Use bundled libevent")
ENDIF()
MYSQL_USE_BUNDLED_LIBEVENT()
ENDIF()
ENDIF()
ENDMACRO()

View File

@ -304,20 +304,22 @@ FUNCTION(GET_DEPENDEND_OS_LIBS target result)
SET(${result} ${ret} PARENT_SCOPE)
ENDFUNCTION()
MACRO(RESTRICT_SYMBOL_EXPORTS target)
SET(VISIBILITY_HIDDEN_FLAG)
SET(VISIBILITY_HIDDEN_FLAG)
IF(CMAKE_COMPILER_IS_GNUCXX AND UNIX)
CHECK_C_COMPILER_FLAG("-fvisibility=hidden" HAVE_VISIBILITY_HIDDEN)
IF(HAVE_VISIBILITY_HIDDEN)
SET(VISIBILITY_HIDDEN_FLAG "-fvisibility=hidden")
ENDIF()
IF(CMAKE_COMPILER_IS_GNUCXX AND UNIX)
CHECK_C_COMPILER_FLAG("-fvisibility=hidden" HAVE_VISIBILITY_HIDDEN)
IF(HAVE_VISIBILITY_HIDDEN)
SET(VISIBILITY_HIDDEN_FLAG "-fvisibility=hidden")
ENDIF()
ENDIF()
IF(CMAKE_C_COMPILER_ID MATCHES "SunPro")
SET(VISIBILITY_HIDDEN_FLAG "-xldscope=hidden")
ENDIF()
IF(CMAKE_C_COMPILER_ID MATCHES "SunPro")
SET(VISIBILITY_HIDDEN_FLAG "-xldscope=hidden")
ENDIF()
# We try to hide the symbols in yassl/zlib to avoid name clashes with
# other libraries like openssl.
FUNCTION(RESTRICT_SYMBOL_EXPORTS target)
IF(VISIBILITY_HIDDEN_FLAG)
GET_TARGET_PROPERTY(COMPILE_FLAGS ${target} COMPILE_FLAGS)
IF(NOT COMPILE_FLAGS)
@ -327,5 +329,4 @@ MACRO(RESTRICT_SYMBOL_EXPORTS target)
SET_TARGET_PROPERTIES(${target} PROPERTIES
COMPILE_FLAGS "${COMPILE_FLAGS} ${VISIBILITY_HIDDEN_FLAG}")
ENDIF()
ENDMACRO()
ENDFUNCTION()

View File

@ -80,10 +80,6 @@ IF(MSVC)
STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}")
ENDFOREACH()
# Remove support for exceptions
FOREACH(flag CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_INIT)
STRING(REPLACE "/EHsc" "" "${flag}" "${${flag}}")
ENDFOREACH()
# Fix CMake's predefined huge stack size
FOREACH(type EXE SHARED MODULE)

View File

@ -13,80 +13,228 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# We support different versions of SSL:
# - "bundled" uses source code in <source dir>/extra/yassl
# - "system" (typically) uses headers/libraries in /usr/lib and /usr/lib64
# - a custom installation of openssl can be used like this
# - cmake -DCMAKE_PREFIX_PATH=</path/to/custom/openssl> -DWITH_SSL="system"
# or
# - cmake -DWITH_SSL=</path/to/custom/openssl>
#
# The default value for WITH_SSL is "bundled"
# set in cmake/build_configurations/feature_set.cmake
#
# For custom build/install of openssl, see the accompanying README and
# INSTALL* files. When building with gcc, you must build the shared libraries
# (in addition to the static ones):
# ./config --prefix=</path/to/custom/openssl> --shared; make; make install
# On some platforms (mac) you need to choose 32/64 bit architecture.
# Build/Install of openssl on windows is slightly different: you need to run
# perl and nmake. You might also need to
# 'set path=</path/to/custom/openssl>\bin;%PATH%
# in order to find the .dll files at runtime.
SET(WITH_SSL_DOC "bundled (use yassl)")
SET(WITH_SSL_DOC
"${WITH_SSL_DOC}, yes (prefer os library if present, otherwise use bundled)")
SET(WITH_SSL_DOC
"${WITH_SSL_DOC}, system (use os library)")
SET(WITH_SSL_DOC
"${WITH_SSL_DOC}, </path/to/custom/installation>")
MACRO (CHANGE_SSL_SETTINGS string)
SET(WITH_SSL ${string} CACHE STRING "Options are: no bundled yes(prefer os library if present otherwise use bundled) system(use os library)" FORCE)
SET(WITH_SSL ${string} CACHE STRING ${WITH_SSL_DOC} FORCE)
ENDMACRO()
MACRO (MYSQL_USE_BUNDLED_SSL)
SET(INC_DIRS
${CMAKE_SOURCE_DIR}/extra/yassl/include
${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/include
${CMAKE_SOURCE_DIR}/extra/yassl/include
${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/include
)
SET(SSL_LIBRARIES yassl taocrypt)
SET(SSL_INCLUDE_DIRS ${INC_DIRS})
SET(SSL_INTERNAL_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL)
SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PURE_C -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED")
SET(SSL_DEFINES "-DHAVE_YASSL -DYASSL_PREFIX -DHAVE_OPENSSL -DMULTI_THREADED")
CHANGE_SSL_SETTINGS("bundled")
#Remove -fno-implicit-templates
#(yassl sources cannot be compiled with it)
SET(SAVE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
IF(CMAKE_CXX_FLAGS)
STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS
${CMAKE_CXX_FLAGS})
ENDIF()
ADD_SUBDIRECTORY(extra/yassl)
ADD_SUBDIRECTORY(extra/yassl/taocrypt)
SET(CMAKE_CXX_FLAGS ${SAVE_CXX_FLAGS})
GET_TARGET_PROPERTY(src yassl SOURCES)
FOREACH(file ${src})
SET(SSL_SOURCES ${SSL_SOURCES} ${CMAKE_SOURCE_DIR}/extra/yassl/${file})
ENDFOREACH()
GET_TARGET_PROPERTY(src taocrypt SOURCES)
FOREACH(file ${src})
SET(SSL_SOURCES ${SSL_SOURCES} ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/${file})
SET(SSL_SOURCES ${SSL_SOURCES}
${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/${file})
ENDFOREACH()
ENDMACRO()
# MYSQL_CHECK_SSL
#
# Provides the following configure options:
# WITH_SSL=[yes|no|bundled]
# WITH_SSL=[yes|bundled|system|<path/to/custom/installation>]
MACRO (MYSQL_CHECK_SSL)
IF(NOT WITH_SSL)
IF(WIN32)
CHANGE_SSL_SETTINGS("bundled")
ELSE()
CHANGE_SSL_SETTINGS("no")
SET(WITH_SSL "yes")
ENDIF()
ENDIF()
# See if WITH_SSL is of the form </path/to/custom/installation>
FILE(GLOB WITH_SSL_HEADER ${WITH_SSL}/include/openssl/ssl.h)
IF (WITH_SSL_HEADER)
SET(WITH_SSL_PATH ${WITH_SSL} CACHE PATH "path to custom SSL installation")
ENDIF()
IF(WITH_SSL STREQUAL "bundled")
MYSQL_USE_BUNDLED_SSL()
ELSEIF(WITH_SSL STREQUAL "system" OR WITH_SSL STREQUAL "yes")
# Check for system library
SET(OPENSSL_FIND_QUIETLY TRUE)
INCLUDE(FindOpenSSL)
FIND_LIBRARY(CRYPTO_LIBRARY crypto)
MARK_AS_ADVANCED(CRYPTO_LIBRARY)
# Reset some variables, in case we switch from /path/to/ssl to "bundled".
IF (WITH_SSL_PATH)
UNSET(WITH_SSL_PATH)
UNSET(WITH_SSL_PATH CACHE)
ENDIF()
IF (OPENSSL_ROOT_DIR)
UNSET(OPENSSL_ROOT_DIR)
UNSET(OPENSSL_ROOT_DIR CACHE)
ENDIF()
IF (OPENSSL_INCLUDE_DIR)
UNSET(OPENSSL_INCLUDE_DIR)
UNSET(OPENSSL_INCLUDE_DIR CACHE)
ENDIF()
IF (WIN32 AND OPENSSL_APPLINK_C)
UNSET(OPENSSL_APPLINK_C)
UNSET(OPENSSL_APPLINK_C CACHE)
ENDIF()
IF (OPENSSL_LIBRARIES)
UNSET(OPENSSL_LIBRARIES)
UNSET(OPENSSL_LIBRARIES CACHE)
ENDIF()
ELSEIF(WITH_SSL STREQUAL "system" OR
WITH_SSL STREQUAL "yes" OR
WITH_SSL_PATH
)
# First search in WITH_SSL_PATH.
FIND_PATH(OPENSSL_ROOT_DIR
NAMES include/openssl/ssl.h
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
HINTS ${WITH_SSL_PATH}
)
# Then search in standard places (if not found above).
FIND_PATH(OPENSSL_ROOT_DIR
NAMES include/openssl/ssl.h
)
FIND_PATH(OPENSSL_INCLUDE_DIR
NAMES openssl/ssl.h
HINTS ${OPENSSL_ROOT_DIR}/include
)
IF (WIN32)
FIND_FILE(OPENSSL_APPLINK_C
NAMES openssl/applink.c
HINTS ${OPENSSL_ROOT_DIR}/include
)
MESSAGE(STATUS "OPENSSL_APPLINK_C ${OPENSSL_APPLINK_C}")
ENDIF()
# On mac this list is <.dylib;.so;.a>
# We prefer static libraries, so we revert it here.
IF (WITH_SSL_PATH)
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
ENDIF()
MESSAGE(STATUS "suffixes <${CMAKE_FIND_LIBRARY_SUFFIXES}>")
FIND_LIBRARY(OPENSSL_LIBRARIES
NAMES ssl ssleay32 ssleay32MD
HINTS ${OPENSSL_ROOT_DIR}/lib)
FIND_LIBRARY(CRYPTO_LIBRARY
NAMES crypto libeay32
HINTS ${OPENSSL_ROOT_DIR}/lib)
IF (WITH_SSL_PATH)
LIST(REVERSE CMAKE_FIND_LIBRARY_SUFFIXES)
ENDIF()
# Verify version number. Version information looks like:
# #define OPENSSL_VERSION_NUMBER 0x1000103fL
# Encoded as MNNFFPPS: major minor fix patch status
FILE(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h"
OPENSSL_VERSION_NUMBER
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x[0-9].*"
)
STRING(REGEX REPLACE
"^.*OPENSSL_VERSION_NUMBER[\t ]+0x([0-9]).*$" "\\1"
OPENSSL_MAJOR_VERSION "${OPENSSL_VERSION_NUMBER}"
)
IF(OPENSSL_INCLUDE_DIR AND
OPENSSL_LIBRARIES AND
CRYPTO_LIBRARY AND
OPENSSL_MAJOR_VERSION STREQUAL "1"
)
SET(OPENSSL_FOUND TRUE)
ELSE()
SET(OPENSSL_FOUND FALSE)
ENDIF()
MESSAGE(STATUS "OPENSSL_INCLUDE_DIR = ${OPENSSL_INCLUDE_DIR}")
MESSAGE(STATUS "OPENSSL_LIBRARIES = ${OPENSSL_LIBRARIES}")
MESSAGE(STATUS "CRYPTO_LIBRARY = ${CRYPTO_LIBRARY}")
MESSAGE(STATUS "OPENSSL_MAJOR_VERSION = ${OPENSSL_MAJOR_VERSION}")
INCLUDE(CheckSymbolExists)
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h"
HAVE_SHA512_DIGEST_LENGTH)
SET(CMAKE_REQUIRED_INCLUDES)
IF(OPENSSL_FOUND AND CRYPTO_LIBRARY AND HAVE_SHA512_DIGEST_LENGTH)
IF(OPENSSL_FOUND AND HAVE_SHA512_DIGEST_LENGTH)
SET(SSL_SOURCES "")
SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARY})
IF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBSOCKET})
ENDIF()
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${LIBDL})
ENDIF()
MESSAGE(STATUS "SSL_LIBRARIES = ${SSL_LIBRARIES}")
SET(SSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
SET(SSL_INTERNAL_INCLUDE_DIRS "")
SET(SSL_DEFINES "-DHAVE_OPENSSL")
CHANGE_SSL_SETTINGS("system")
ELSE()
IF(WITH_SSL STREQUAL "system")
MESSAGE(SEND_ERROR "Cannot find appropriate system libraries for SSL. Use WITH_SSL=bundled to enable SSL support")
ENDIF()
MYSQL_USE_BUNDLED_SSL()
ENDIF()
ELSEIF(NOT WITH_SSL STREQUAL "no")
MESSAGE(SEND_ERROR "Wrong option for WITH_SSL. Valid values are : yes, no, bundled")
ELSE()
MESSAGE(SEND_ERROR
"Wrong option for WITH_SSL. Valid values are : "${WITH_SSL_DOC})
ENDIF()
ENDMACRO()
# Many executables will depend on libeay32.dll and ssleay32.dll at runtime.
# In order to ensure we find the right version(s), we copy them into
# the same directory as the executables.
# NOTE: Using dlls will likely crash in malloc/free,
# see INSTALL.W32 which comes with the openssl sources.
# So we should be linking static versions of the libraries.
MACRO (COPY_OPENSSL_DLLS target_name)
IF (WIN32 AND WITH_SSL_PATH)
GET_FILENAME_COMPONENT(CRYPTO_NAME "${CRYPTO_LIBRARY}" NAME_WE)
GET_FILENAME_COMPONENT(OPENSSL_NAME "${OPENSSL_LIBRARIES}" NAME_WE)
FILE(GLOB HAVE_CRYPTO_DLL "${WITH_SSL_PATH}/bin/${CRYPTO_NAME}.dll")
FILE(GLOB HAVE_OPENSSL_DLL "${WITH_SSL_PATH}/bin/${OPENSSL_NAME}.dll")
IF (HAVE_CRYPTO_DLL AND HAVE_OPENSSL_DLL)
ADD_CUSTOM_COMMAND(OUTPUT ${target_name}
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${WITH_SSL_PATH}/bin/${CRYPTO_NAME}.dll"
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CRYPTO_NAME}.dll"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${WITH_SSL_PATH}/bin/${OPENSSL_NAME}.dll"
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${OPENSSL_NAME}.dll"
)
ADD_CUSTOM_TARGET(${target_name} ALL)
ENDIF()
ENDIF()
ENDMACRO()

View File

@ -1332,7 +1332,7 @@ void _db_dump_(uint _line_, const char *keyword,
if (TRACING)
{
Indent(cs, cs->level + 1);
pos= min(max(cs->level-cs->stack->sub_level,0)*INDENT,80);
pos= MY_MIN(MY_MAX(cs->level-cs->stack->sub_level,0)*INDENT,80);
}
else
{
@ -1737,7 +1737,7 @@ static void Indent(CODE_STATE *cs, int indent)
{
int count;
indent= max(indent-1-cs->stack->sub_level,0)*INDENT;
indent= MY_MAX(indent-1-cs->stack->sub_level,0)*INDENT;
for (count= 0; count < indent ; count++)
{
if ((count % INDENT) == 0)

View File

@ -20,9 +20,9 @@
DROP TABLE tmp_db;
@@ -40,8 +38,6 @@
REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','');
REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','');
-INSERT INTO tmp_user (host,user) VALUES ('localhost','');
-INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;

View File

@ -33,8 +33,9 @@
#include <assert.h>
#include <my_dir.h>
#define MAX_ROWS 1000
#define MAX_ROWS 2000
#define HEADER_LENGTH 32 /* Length of header in errmsg.sys */
#define ERRMSG_VERSION 3 /* Version number of errmsg.sys */
#define DEFAULT_CHARSET_DIR "../sql/share/charsets"
#define ER_PREFIX "ER_"
#define ER_PREFIX2 "MARIA_ER_"
@ -50,9 +51,9 @@ static char *default_dbug_option= (char*) "d:t:O,/tmp/comp_err.trace";
#endif
/* Header for errmsg.sys files */
uchar file_head[]= { 254, 254, 2, 2 };
uchar file_head[]= { 254, 254, 2, ERRMSG_VERSION };
/* Store positions to each error message row to store in errmsg.sys header */
uint file_pos[MAX_ROWS];
uint file_pos[MAX_ROWS+1];
const char *empty_string= ""; /* For empty states */
/*
@ -379,9 +380,11 @@ static int create_sys_files(struct languages *lang_head,
if (my_fwrite(to, (uchar*) head, HEADER_LENGTH, MYF(MY_WME | MY_FNABP)))
goto err;
file_pos[row_count]= (ftell(to) - start_pos);
for (i= 0; i < row_count; i++)
{
int2store(head, file_pos[i]);
/* Store length of each string */
int2store(head, file_pos[i+1] - file_pos[i]);
if (my_fwrite(to, (uchar*) head, 2, MYF(MY_WME | MY_FNABP)))
goto err;
}

View File

@ -26,6 +26,7 @@
#include <my_sys.h>
#include <m_string.h>
#include <my_getopt.h>
#include <my_default.h>
#include <mysql_version.h>
#define load_default_groups mysqld_groups
@ -33,6 +34,7 @@
#undef load_default_groups
my_bool opt_mysqld;
const char *config_file="my"; /* Default config file */
uint verbose= 0, opt_defaults_file_used= 0;
const char *default_dbug_option="d:t:o,/tmp/my_print_defaults.trace";

82
include/big_endian.h Normal file
View File

@ -0,0 +1,82 @@
/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
Data in big-endian format.
*/
#define float4store(T,A) do { *(T)= ((uchar *) &A)[3];\
*((T)+1)=(char) ((uchar *) &A)[2];\
*((T)+2)=(char) ((uchar *) &A)[1];\
*((T)+3)=(char) ((uchar *) &A)[0]; } while(0)
#define float4get(V,M) do { float def_temp;\
((uchar*) &def_temp)[0]=(M)[3];\
((uchar*) &def_temp)[1]=(M)[2];\
((uchar*) &def_temp)[2]=(M)[1];\
((uchar*) &def_temp)[3]=(M)[0];\
(V)=def_temp; } while(0)
#define float8store(T,V) do { *(T)= ((uchar *) &V)[7];\
*((T)+1)=(char) ((uchar *) &V)[6];\
*((T)+2)=(char) ((uchar *) &V)[5];\
*((T)+3)=(char) ((uchar *) &V)[4];\
*((T)+4)=(char) ((uchar *) &V)[3];\
*((T)+5)=(char) ((uchar *) &V)[2];\
*((T)+6)=(char) ((uchar *) &V)[1];\
*((T)+7)=(char) ((uchar *) &V)[0]; } while(0)
#define float8get(V,M) do { double def_temp;\
((uchar*) &def_temp)[0]=(M)[7];\
((uchar*) &def_temp)[1]=(M)[6];\
((uchar*) &def_temp)[2]=(M)[5];\
((uchar*) &def_temp)[3]=(M)[4];\
((uchar*) &def_temp)[4]=(M)[3];\
((uchar*) &def_temp)[5]=(M)[2];\
((uchar*) &def_temp)[6]=(M)[1];\
((uchar*) &def_temp)[7]=(M)[0];\
(V) = def_temp; } while(0)
#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
((uint16) ((uint16) (M)[0]) << 8)); } while(0)
#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\
((short) ((short) (M)[0]) << 8)); } while(0)
#define longget(V,M) do { int32 def_temp;\
((uchar*) &def_temp)[0]=(M)[0];\
((uchar*) &def_temp)[1]=(M)[1];\
((uchar*) &def_temp)[2]=(M)[2];\
((uchar*) &def_temp)[3]=(M)[3];\
(V)=def_temp; } while(0)
#define ulongget(V,M) do { uint32 def_temp;\
((uchar*) &def_temp)[0]=(M)[0];\
((uchar*) &def_temp)[1]=(M)[1];\
((uchar*) &def_temp)[2]=(M)[2];\
((uchar*) &def_temp)[3]=(M)[3];\
(V)=def_temp; } while(0)
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
*(((char*)T)+1)=(char)(def_temp); \
*(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
#define longstore(T,A) do { *(((char*)T)+3)=((A));\
*(((char*)T)+2)=(((A) >> 8));\
*(((char*)T)+1)=(((A) >> 16));\
*(((char*)T)+0)=(((A) >> 24)); } while(0)
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
/* Cast away type qualifiers (necessary as macro takes argument by value). */
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
/* Cast away type qualifiers (necessary as macro takes argument by value). */
#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double))
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))

View File

@ -0,0 +1,95 @@
/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
Endianness-independent definitions for architectures other
than the x86 architecture.
*/
#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\
((int16) ((int16) (A)[1]) << 8))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])) : \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (int32) (((int32) ((uchar) (A)[0])) +\
(((int32) ((uchar) (A)[1]) << 8)) +\
(((int32) ((uchar) (A)[2]) << 16)) +\
(((int32) ((int16) (A)[3]) << 24)))
#define sint8korr(A) (longlong) uint8korr(A)
#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) +\
((uint16) ((uchar) (A)[1]) << 8))
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) ((uchar) (A)[4])) << 32))
#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
(((uint32) ((uchar) (A)[1])) << 8) + \
(((uint32) ((uchar) (A)[2])) << 16) + \
(((uint32) ((uchar) (A)[3])) << 24)) + \
(((ulonglong) ((uchar) (A)[4])) << 32) + \
(((ulonglong) ((uchar) (A)[5])) << 40))
#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) (((uint32) ((uchar) (A)[4])) +\
(((uint32) ((uchar) (A)[5])) << 8) +\
(((uint32) ((uchar) (A)[6])) << 16) +\
(((uint32) ((uchar) (A)[7])) << 24))) <<\
32))
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
*((uchar*) (T))= (uchar)(def_temp); \
*((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \
} while(0)
#define int3store(T,A) do { /*lint -save -e734 */\
*((uchar*)(T))=(uchar) ((A));\
*((uchar*) (T)+1)=(uchar) (((A) >> 8));\
*((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
/*lint -restore */} while(0)
#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
*(((char *)(T))+1)=(char) (((A) >> 8));\
*(((char *)(T))+2)=(char) (((A) >> 16));\
*(((char *)(T))+3)=(char) (((A) >> 24));\
} while(0)
#define int5store(T,A) do { *((char *)(T))= (char)((A)); \
*(((char *)(T))+1)= (char)(((A) >> 8)); \
*(((char *)(T))+2)= (char)(((A) >> 16)); \
*(((char *)(T))+3)= (char)(((A) >> 24)); \
*(((char *)(T))+4)= (char)(((A) >> 32)); \
} while(0)
#define int6store(T,A) do { *((char *)(T))= (char)((A)); \
*(((char *)(T))+1)= (char)(((A) >> 8)); \
*(((char *)(T))+2)= (char)(((A) >> 16)); \
*(((char *)(T))+3)= (char)(((A) >> 24)); \
*(((char *)(T))+4)= (char)(((A) >> 32)); \
*(((char *)(T))+5)= (char)(((A) >> 40)); \
} while(0)
#define int8store(T,A) do { uint def_temp= (uint) (A), \
def_temp2= (uint) ((A) >> 32); \
int4store((T),def_temp); \
int4store((T+4),def_temp2);\
} while(0)

View File

@ -0,0 +1,97 @@
/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
Optimized function-like macros for the x86 architecture (_WIN32 included).
*/
#define sint2korr(A) (*((const int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])) : \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (*((const long *) (A)))
#define uint2korr(A) (*((const uint16 *) (A)))
/*
Attention: Please, note, uint3korr reads 4 bytes (not 3)!
It means, that you have to provide enough allocated space.
*/
#if defined(HAVE_valgrind) && !defined(_WIN32)
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#else
#define uint3korr(A) (long) (*((const unsigned int *) (A)) & 0xFFFFFF)
#endif
#define uint4korr(A) (*((const uint32 *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) ((uchar) (A)[4])) << 32))
#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
(((uint32) ((uchar) (A)[1])) << 8) + \
(((uint32) ((uchar) (A)[2])) << 16) + \
(((uint32) ((uchar) (A)[3])) << 24)) + \
(((ulonglong) ((uchar) (A)[4])) << 32) + \
(((ulonglong) ((uchar) (A)[5])) << 40))
#define uint8korr(A) (*((const ulonglong *) (A)))
#define sint8korr(A) (*((const longlong *) (A)))
#define int2store(T,A) *((uint16*) (T))= (uint16) (A)
#define int3store(T,A) do { *(T)= (uchar) ((A));\
*(T+1)=(uchar) (((uint) (A) >> 8));\
*(T+2)=(uchar) (((A) >> 16));\
} while (0)
#define int4store(T,A) *((long *) (T))= (long) (A)
#define int5store(T,A) do { *(T)= (uchar)((A));\
*((T)+1)=(uchar) (((A) >> 8));\
*((T)+2)=(uchar) (((A) >> 16));\
*((T)+3)=(uchar) (((A) >> 24));\
*((T)+4)=(uchar) (((A) >> 32));\
} while(0)
#define int6store(T,A) do { *(T)= (uchar)((A)); \
*((T)+1)=(uchar) (((A) >> 8)); \
*((T)+2)=(uchar) (((A) >> 16)); \
*((T)+3)=(uchar) (((A) >> 24)); \
*((T)+4)=(uchar) (((A) >> 32)); \
*((T)+5)=(uchar) (((A) >> 40)); \
} while(0)
#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A)
typedef union {
double v;
long m[2];
} doubleget_union;
#define doubleget(V,M) \
do { doubleget_union _tmp; \
_tmp.m[0] = *((const long*)(M)); \
_tmp.m[1] = *(((const long*) (M))+1); \
(V) = _tmp.v; } while(0)
#define doublestore(T,V) \
do { *((long *) T) = ((const doubleget_union *)&V)->m[0]; \
*(((long *) T)+1) = ((const doubleget_union *)&V)->m[1]; \
} while (0)
#define float4get(V,M) \
do { *((float *) &(V)) = *((const float*) (M)); } while(0)
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((uchar*)(V), (uchar*)(&M), sizeof(float))
#define floatstore(T,V) memcpy((uchar*)(T), (uchar*)(&V), sizeof(float))
#define floatget(V,M) memcpy((uchar*)(&V),(uchar*) (M), sizeof(float))
#define float8store(V,M) doublestore((V),(M))

View File

@ -0,0 +1,83 @@
/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
Optimized function-like macros for the x86 architecture (_WIN32 included).
*/
#define sint2korr(A) (int16) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])) : \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (int32) (*((int32 *) (A)))
#define uint2korr(A) (uint16) (*((uint16 *) (A)))
/*
Attention: Please, note, uint3korr reads 4 bytes (not 3)!
It means, that you have to provide enough allocated space.
*/
#if defined(HAVE_purify) && !defined(_WIN32)
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#else
#define uint3korr(A) (uint32) (*((unsigned int *) (A)) & 0xFFFFFF)
#endif
#define uint4korr(A) (uint32) (*((uint32 *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) ((uchar) (A)[4])) << 32))
#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
(((uint32) ((uchar) (A)[1])) << 8) + \
(((uint32) ((uchar) (A)[2])) << 16) + \
(((uint32) ((uchar) (A)[3])) << 24)) + \
(((ulonglong) ((uchar) (A)[4])) << 32) + \
(((ulonglong) ((uchar) (A)[5])) << 40))
#define uint8korr(A) (ulonglong) (*((ulonglong *) (A)))
#define sint8korr(A) (longlong) (*((longlong *) (A)))
#define int2store(T,A) do { uchar *pT= (uchar*)(T);\
*((uint16*)(pT))= (uint16) (A);\
} while (0)
#define int3store(T,A) do { *(T)= (uchar) ((A));\
*(T+1)=(uchar) (((uint) (A) >> 8));\
*(T+2)=(uchar) (((A) >> 16));\
} while (0)
#define int4store(T,A) do { uchar *pT= (uchar*)(T);\
*((uint32 *) (pT))= (uint32) (A); \
} while (0)
#define int5store(T,A) do { *(T)= (uchar)((A));\
*((T)+1)=(uchar) (((A) >> 8));\
*((T)+2)=(uchar) (((A) >> 16));\
*((T)+3)=(uchar) (((A) >> 24));\
*((T)+4)=(uchar) (((A) >> 32));\
} while(0)
#define int6store(T,A) do { *(T)= (uchar)((A)); \
*((T)+1)=(uchar) (((A) >> 8)); \
*((T)+2)=(uchar) (((A) >> 16)); \
*((T)+3)=(uchar) (((A) >> 24)); \
*((T)+4)=(uchar) (((A) >> 32)); \
*((T)+5)=(uchar) (((A) >> 40)); \
} while(0)
#define int8store(T,A) do { uchar *pT= (uchar*)(T);\
*((ulonglong *) (pT))= (ulonglong) (A);\
} while(0)

View File

@ -0,0 +1,32 @@
/* defines and prototypes for using crypt_genhash_impl.cc */
#ifndef CRYPT_HASHGEN_IMPL_H
#define CRYPT_HASHGEN_IMPL_H
#define ROUNDS_DEFAULT 5000
#define ROUNDS_MIN 1000
#define ROUNDS_MAX 999999999
#define MIXCHARS 32
#define CRYPT_SALT_LENGTH 20
#define CRYPT_MAGIC_LENGTH 3
#define CRYPT_PARAM_LENGTH 13
#define SHA256_HASH_LENGTH 43
#define CRYPT_MAX_PASSWORD_SIZE (CRYPT_SALT_LENGTH + \
SHA256_HASH_LENGTH + \
CRYPT_MAGIC_LENGTH + \
CRYPT_PARAM_LENGTH)
int extract_user_salt(char **salt_begin,
char **salt_end);
C_MODE_START
char *
my_crypt_genhash(char *ctbuffer,
size_t ctbufflen,
const char *plaintext,
int plaintext_len,
const char *switchsalt,
const char **params);
void generate_user_salt(char *buffer, int buffer_len);
void xor_string(char *to, int to_len, char *pattern, int pattern_len);
C_MODE_END
#endif

View File

@ -16,8 +16,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* Error messages for MySQL clients */
/* (Error messages for the daemon are in sql/share/errmsg.txt) */
/*
Error messages numbers for MySQL clients.
The error messages itself are in libmysql/errmsg.c
Error messages for the mysqld daemon are in sql/share/errmsg.txt
*/
#ifdef __cplusplus
extern "C" {
@ -102,7 +106,9 @@ extern const char *client_errors[]; /* Error messages */
#define CR_NEW_STMT_METADATA 2057
#define CR_ALREADY_CONNECTED 2058
#define CR_AUTH_PLUGIN_CANNOT_LOAD 2059
#define CR_ERROR_LAST /*Copy last error nr:*/ 2059
#define CR_DUPLICATE_CONNECTION_ATTR 2060
#define CR_AUTH_PLUGIN_ERR 2061
#define CR_ERROR_LAST /*Copy last error nr:*/ 2061
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
#endif /* ERRMSG_INCLUDED */

View File

@ -43,11 +43,32 @@ struct _ft_vft
void (*reinit_search)(FT_INFO *);
};
typedef struct st_ft_info_ext FT_INFO_EXT;
struct _ft_vft_ext
{
uint (*get_version)(); // Extended API version
ulonglong (*get_flags)();
ulonglong (*get_docid)(FT_INFO_EXT *);
ulonglong (*count_matches)(FT_INFO_EXT *);
};
/* Flags for extended FT API */
#define FTS_ORDERED_RESULT (1LL << 1)
#define FTS_DOCID_IN_RESULT (1LL << 2)
#define FTS_DOC_ID_COL_NAME "FTS_DOC_ID"
#ifndef FT_CORE
struct st_ft_info
{
struct _ft_vft *please; /* INTERCAL style :-) */
};
struct st_ft_info_ext
{
struct _ft_vft *please; /* INTERCAL style :-) */
struct _ft_vft_ext *could_you;
};
#endif
extern const char *ft_stopword_file;

75
include/little_endian.h Normal file
View File

@ -0,0 +1,75 @@
/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02111-1307 USA */
/*
Data in little-endian format.
*/
#ifndef MY_BYTE_ORDER_ARCH_OPTIMIZED
#define float4get(V,M) memcpy(&V, (M), sizeof(float))
#define float4store(V,M) memcpy(V, (&M), sizeof(float))
#define float8get(V,M) doubleget((V),(M))
#define float8store(V,M) doublestore((V),(M))
/* Bi-endian hardware.... */
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\
*(((char*)T)+1)=(char) ((uchar *) &V)[5];\
*(((char*)T)+2)=(char) ((uchar *) &V)[6];\
*(((char*)T)+3)=(char) ((uchar *) &V)[7];\
*(((char*)T)+4)=(char) ((uchar *) &V)[0];\
*(((char*)T)+5)=(char) ((uchar *) &V)[1];\
*(((char*)T)+6)=(char) ((uchar *) &V)[2];\
*(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\
while(0)
#define doubleget(V,M) do { double def_temp;\
((uchar*) &def_temp)[0]=(M)[4];\
((uchar*) &def_temp)[1]=(M)[5];\
((uchar*) &def_temp)[2]=(M)[6];\
((uchar*) &def_temp)[3]=(M)[7];\
((uchar*) &def_temp)[4]=(M)[0];\
((uchar*) &def_temp)[5]=(M)[1];\
((uchar*) &def_temp)[6]=(M)[2];\
((uchar*) &def_temp)[7]=(M)[3];\
(V) = def_temp; } while(0)
#else /* Bi-endian hardware.... */
/* Cast away type qualifiers (necessary as macro takes argument by value). */
#define doublestore(T,V) memcpy((T), (void*) &V, sizeof(double))
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
#endif /* Bi-endian hardware.... */
#endif /* !MY_BYTE_ORDER_ARCH_OPTIMIZED */
#define ushortget(V,M) do { uchar *pM= (uchar*)(M);V = uint2korr(pM);} while(0)
#define shortget(V,M) do { uchar *pM= (uchar*)(M);V = sint2korr(pM);} while(0)
#define longget(V,M) do { uchar *pM= (uchar*)(M);V = sint4korr(pM);} while(0)
#define ulongget(V,M) do { uchar *pM= (uchar*)(M);V = uint4korr(pM);} while(0)
#define shortstore(T,V) int2store(T,V)
#define longstore(T,V) int4store(T,V)
#ifndef floatstore
/* Cast away type qualifiers (necessary as macro takes argument by value). */
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
#endif
#ifndef doubleget
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
#endif /* doubleget */
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))

View File

@ -137,6 +137,38 @@ extern MY_UNI_CTYPE my_uni_ctype[256];
#define MY_REPERTOIRE_EXTENDED 2 /* Extended characters: U+0080..U+FFFF */
#define MY_REPERTOIRE_UNICODE30 3 /* ASCII | EXTENDED: U+0000..U+FFFF */
/* Flags for strxfrm */
#define MY_STRXFRM_LEVEL1 0x00000001 /* for primary weights */
#define MY_STRXFRM_LEVEL2 0x00000002 /* for secondary weights */
#define MY_STRXFRM_LEVEL3 0x00000004 /* for tertiary weights */
#define MY_STRXFRM_LEVEL4 0x00000008 /* fourth level weights */
#define MY_STRXFRM_LEVEL5 0x00000010 /* fifth level weights */
#define MY_STRXFRM_LEVEL6 0x00000020 /* sixth level weights */
#define MY_STRXFRM_LEVEL_ALL 0x0000003F /* Bit OR for the above six */
#define MY_STRXFRM_NLEVELS 6 /* Number of possible levels*/
#define MY_STRXFRM_PAD_WITH_SPACE 0x00000040 /* if pad result with spaces */
#define MY_STRXFRM_PAD_TO_MAXLEN 0x00000080 /* if pad tail(for filesort) */
#define MY_STRXFRM_DESC_LEVEL1 0x00000100 /* if desc order for level1 */
#define MY_STRXFRM_DESC_LEVEL2 0x00000200 /* if desc order for level2 */
#define MY_STRXFRM_DESC_LEVEL3 0x00000300 /* if desc order for level3 */
#define MY_STRXFRM_DESC_LEVEL4 0x00000800 /* if desc order for level4 */
#define MY_STRXFRM_DESC_LEVEL5 0x00001000 /* if desc order for level5 */
#define MY_STRXFRM_DESC_LEVEL6 0x00002000 /* if desc order for level6 */
#define MY_STRXFRM_DESC_SHIFT 8
#define MY_STRXFRM_UNUSED_00004000 0x00004000 /* for future extensions */
#define MY_STRXFRM_UNUSED_00008000 0x00008000 /* for future extensions */
#define MY_STRXFRM_REVERSE_LEVEL1 0x00010000 /* if reverse order for level1 */
#define MY_STRXFRM_REVERSE_LEVEL2 0x00020000 /* if reverse order for level2 */
#define MY_STRXFRM_REVERSE_LEVEL3 0x00040000 /* if reverse order for level3 */
#define MY_STRXFRM_REVERSE_LEVEL4 0x00080000 /* if reverse order for level4 */
#define MY_STRXFRM_REVERSE_LEVEL5 0x00100000 /* if reverse order for level5 */
#define MY_STRXFRM_REVERSE_LEVEL6 0x00200000 /* if reverse order for level6 */
#define MY_STRXFRM_REVERSE_SHIFT 16
struct my_uni_idx_st
{
uint16 from;

View File

@ -168,7 +168,7 @@ size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to,
(DBL_DIG + 2) significant digits + sign + "." + ("e-NNN" or
MAX_DECPT_FOR_F_FORMAT zeros for cases when |x|<1 and the 'f' format is used).
*/
#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + max(5, MAX_DECPT_FOR_F_FORMAT)) \
#define MY_GCVT_MAX_FIELD_WIDTH (DBL_DIG + 4 + MY_MAX(5, MAX_DECPT_FOR_F_FORMAT)) \
extern char *llstr(longlong value,char *buff);
extern char *ullstr(longlong value,char *buff);

View File

@ -46,7 +46,8 @@
#define HA_OPEN_COPY 256 /* Open copy (for repair) */
/* Internal temp table, used for temporary results */
#define HA_OPEN_INTERNAL_TABLE 512
#define HA_OPEN_MERGE_TABLE 1024
#define HA_OPEN_NO_PSI_CALL 1024 /* Don't call/connect PSI */
#define HA_OPEN_MERGE_TABLE 2048
/* The following is parameter to ha_rkey() how to use key */
@ -194,6 +195,11 @@ enum ha_extra_function {
HA_EXTRA_ATTACH_CHILDREN,
HA_EXTRA_IS_ATTACHED_CHILDREN,
HA_EXTRA_DETACH_CHILDREN,
/*
Prepare table for export
(e.g. quiesce the table and write table metadata).
*/
HA_EXTRA_EXPORT,
HA_EXTRA_DETACH_CHILD,
/* Inform handler we will force a close as part of flush */
HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
@ -317,6 +323,23 @@ enum ha_base_keytype {
#define HA_OPTION_RELIES_ON_SQL_LAYER 512
#define HA_OPTION_NULL_FIELDS 1024
#define HA_OPTION_PAGE_CHECKSUM 2048
/*
STATS_PERSISTENT=1 has been specified in the SQL command (either CREATE
or ALTER TABLE). Table and index statistics that are collected by the
storage engine and used by the optimizer for query optimization will be
stored on disk and will not change after a server restart.
*/
#define HA_OPTION_STATS_PERSISTENT 4096
/*
STATS_PERSISTENT=0 has been specified in CREATE/ALTER TABLE. Statistics
for the table will be wiped away on server shutdown and new ones recalculated
after the server is started again. If none of HA_OPTION_STATS_PERSISTENT or
HA_OPTION_NO_STATS_PERSISTENT is set, this means that the setting is not
explicitly set at table level and the corresponding table will use whatever
is the global server default.
*/
#define HA_OPTION_NO_STATS_PERSISTENT 8192
/* .frm has extra create options in linked-list format */
#define HA_OPTION_TEXT_CREATE_OPTIONS_legacy (1L << 14) /* 5.2 to 5.5, unused since 10.0 */
#define HA_OPTION_TEMP_COMPRESS_RECORD (1L << 15) /* set by isamchk */
@ -334,7 +357,7 @@ enum ha_base_keytype {
#define HA_CREATE_PAGE_CHECKSUM 32
#define HA_CREATE_DELAY_KEY_WRITE 64
#define HA_CREATE_RELIES_ON_SQL_LAYER 128
#define HA_CREATE_INTERNAL_TABLE 256
/* Flags used by start_bulk_insert */
@ -458,7 +481,8 @@ enum ha_base_keytype {
/* It is not possible to log this statement */
#define HA_ERR_LOGGING_IMPOSSIBLE 170
/* The event was corrupt, leading to illegal data being read */
#define HA_ERR_CORRUPT_EVENT 171
#define HA_ERR_CORRUPT_EVENT 171 /* The event was corrupt, leading to
illegal data being read */
#define HA_ERR_NEW_FILE 172 /* New file format */
/* The event could not be processed no other handler error happened */
#define HA_ERR_ROWS_EVENT_APPLY 173
@ -466,16 +490,19 @@ enum ha_base_keytype {
#define HA_ERR_FILE_TOO_SHORT 175 /* File too short */
#define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */
#define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */
/* There's no explicitly listed partition in table for the given value */
#define HA_ERR_NOT_IN_LOCK_PARTITIONS 178
#define HA_ERR_INDEX_COL_TOO_LONG 179 /* Index column length exceeds limit */
#define HA_ERR_INDEX_CORRUPT 180 /* Index corrupted */
#define HA_ERR_UNDO_REC_TOO_BIG 181 /* Undo log record too big */
#define HA_ERR_TABLE_IN_FK_CHECK 182 /* Table being used in foreign key check */
#define HA_FTS_INVALID_DOCID 183 /* Invalid InnoDB Doc ID */
#define HA_ERR_ROW_NOT_VISIBLE 184
#define HA_ERR_ABORTED_BY_USER 185
#define HA_ERR_DISK_FULL 186
#define HA_ERR_LAST 186 /* Copy of last error nr */
#define HA_FTS_INVALID_DOCID 182 /* Invalid InnoDB Doc ID */
#define HA_ERR_TABLE_IN_FK_CHECK 183 /* Table being used in foreign key check */
#define HA_ERR_TABLESPACE_EXISTS 184 /* The tablespace existed in storage engine */
#define HA_ERR_TOO_MANY_FIELDS 185 /* Table has too many columns */
#define HA_ERR_ROW_NOT_VISIBLE 186
#define HA_ERR_ABORTED_BY_USER 187
#define HA_ERR_DISK_FULL 188
#define HA_ERR_LAST 188 /* Copy of last error nr */
/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
@ -608,4 +635,17 @@ C_MODE_START
typedef void (* invalidator_by_filename)(const char * filename);
C_MODE_END
enum durability_properties
{
/*
Preserves the durability properties defined by the engine */
HA_REGULAR_DURABILITY= 0,
/*
Ignore the durability properties defined by the engine and
write only in-memory entries.
*/
HA_IGNORE_DURABILITY= 1
};
#endif /* _my_base_h */

View File

@ -63,6 +63,7 @@ extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first(const MY_BITMAP *map);
extern uint bitmap_get_first_set(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
extern void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);

54
include/my_byteorder.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef MY_BYTEORDER_INCLUDED
#define MY_BYTEORDER_INCLUDED
/* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
Macro for reading 32-bit integer from network byte order (big-endian)
from an unaligned memory location.
*/
#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) | \
(((uint32) ((uchar) (A)[2])) << 8) | \
(((uint32) ((uchar) (A)[1])) << 16) | \
(((uint32) ((uchar) (A)[0])) << 24))
/*
Function-like macros for reading and storing in machine independent
format (low byte first). There are 'korr' (assume 'corrector') variants
for integer types, but 'get' (assume 'getter') for floating point types.
*/
#if defined(__i386__) || defined(_WIN32)
#define MY_BYTE_ORDER_ARCH_OPTIMIZED
#include "byte_order_generic_x86.h"
#elif defined(__x86_64__)
#include "byte_order_generic_x86_64.h"
#else
#include "byte_order_generic.h"
#endif
/*
Function-like macros for reading and storing in machine format from/to
short/long to/from some place in memory V should be a variable (not on
a register) and M a pointer to byte.
*/
#ifdef WORDS_BIGENDIAN
#include "big_endian.h"
#else
#include "little_endian.h"
#endif
#endif /* MY_BYTEORDER_INCLUDED */

50
include/my_default.h Normal file
View File

@ -0,0 +1,50 @@
/* Copyright (C) 2013 Monty Program Ab
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; version 2 of the License.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Definitions for mysys/my_default.c */
#ifndef MY_DEFAULT_INCLUDED
#define MY_DEFAULT_INCLUDED
C_MODE_START
extern const char *my_defaults_extra_file;
extern const char *my_defaults_group_suffix;
extern const char *my_defaults_file;
extern my_bool my_getopt_use_args_separator;
extern my_bool my_getopt_is_args_separator(const char* arg);
/* Define the type of function to be passed to process_default_option_files */
typedef int (*Process_option_func)(void *ctx, const char *group_name,
const char *option);
extern int get_defaults_options(int argc, char **argv,
char **defaults, char **extra_defaults,
char **group_suffix);
extern int my_load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv, const char ***);
extern int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
extern int my_search_option_files(const char *conf_file, int *argc,
char ***argv, uint *args_used,
Process_option_func func, void *func_ctx,
const char **default_directories);
extern void free_defaults(char **argv);
extern void my_print_default_files(const char *conf_file);
extern void print_defaults(const char *conf_file, const char **groups);
C_MODE_END
#endif /* MY_DEFAULT_INCLUDED */

View File

@ -17,7 +17,9 @@
#ifndef _my_getopt_h
#define _my_getopt_h
#include "my_sys.h" /* loglevel */
#include "my_sys.h" /* loglevel */
/* my_getopt and my_default are almost always used together */
#include <my_default.h>
C_MODE_START
@ -85,7 +87,6 @@ struct my_option
void *app_type; /**< To be used by an application */
};
typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *);
/**

View File

@ -50,11 +50,6 @@
#define _POSIX_THREAD_CPUTIME
#endif /* __CYGWIN__ */
/* to make command line shorter we'll define USE_PRAGMA_INTERFACE here */
#ifdef USE_PRAGMA_IMPLEMENTATION
#define USE_PRAGMA_INTERFACE
#endif
#if defined(__OpenBSD__) && (OpenBSD >= 200411)
#define HAVE_ERRNO_AS_DEFINE
#endif
@ -130,6 +125,7 @@
/* Define missing access() modes. */
#define F_OK 0
#define W_OK 2
#define R_OK 4 /* Test for read permission. */
/* Define missing file locking constants. */
#define F_RDLCK 1
@ -348,6 +344,9 @@ C_MODE_END
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_TIMEB_H
#include <sys/timeb.h> /* Avoid warnings on SCO */
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
@ -1046,296 +1045,7 @@ typedef ulong myf; /* Type of MyFlags in my_funcs */
#define MY_HOW_OFTEN_TO_ALARM 2 /* How often we want info on screen */
#define MY_HOW_OFTEN_TO_WRITE 10000 /* How often we want info on screen */
/*
Define-funktions for reading and storing in machine independent format
(low byte first)
*/
/* Optimized store functions for Intel x86 */
#if defined(__i386__) || defined(_WIN32)
#define sint2korr(A) (*((const int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])) : \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (*((const long *) (A)))
#define uint2korr(A) (*((const uint16 *) (A)))
#if defined(HAVE_valgrind) && !defined(_WIN32)
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#else
/*
ATTENTION !
Please, note, uint3korr reads 4 bytes (not 3) !
It means, that you have to provide enough allocated space !
*/
#define uint3korr(A) (long) (*((const unsigned int *) (A)) & 0xFFFFFF)
#endif /* HAVE_valgrind && !_WIN32 */
#define uint4korr(A) (*((const uint32 *) (A)))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) ((uchar) (A)[4])) << 32))
#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
(((uint32) ((uchar) (A)[1])) << 8) + \
(((uint32) ((uchar) (A)[2])) << 16) + \
(((uint32) ((uchar) (A)[3])) << 24)) + \
(((ulonglong) ((uchar) (A)[4])) << 32) + \
(((ulonglong) ((uchar) (A)[5])) << 40))
#define uint8korr(A) (*((const ulonglong *) (A)))
#define sint8korr(A) (*((const longlong *) (A)))
#define int2store(T,A) *((uint16*) (T))= (uint16) (A)
#define int3store(T,A) do { *(T)= (uchar) ((A));\
*(T+1)=(uchar) (((uint) (A) >> 8));\
*(T+2)=(uchar) (((A) >> 16)); } while (0)
#define int4store(T,A) *((long *) (T))= (long) (A)
#define int5store(T,A) do { *(T)= (uchar)((A));\
*((T)+1)=(uchar) (((A) >> 8));\
*((T)+2)=(uchar) (((A) >> 16));\
*((T)+3)=(uchar) (((A) >> 24)); \
*((T)+4)=(uchar) (((A) >> 32)); } while(0)
#define int6store(T,A) do { *(T)= (uchar)((A)); \
*((T)+1)=(uchar) (((A) >> 8)); \
*((T)+2)=(uchar) (((A) >> 16)); \
*((T)+3)=(uchar) (((A) >> 24)); \
*((T)+4)=(uchar) (((A) >> 32)); \
*((T)+5)=(uchar) (((A) >> 40)); } while(0)
#define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A)
typedef union {
double v;
long m[2];
} doubleget_union;
#define doubleget(V,M) \
do { doubleget_union _tmp; \
_tmp.m[0] = *((const long*)(M)); \
_tmp.m[1] = *(((const long*) (M))+1); \
(V) = _tmp.v; } while(0)
#define doublestore(T,V) do { *((long *) T) = ((const doubleget_union *)&V)->m[0]; \
*(((long *) T)+1) = ((const doubleget_union *)&V)->m[1]; \
} while (0)
#define float4get(V,M) do { *((float *) &(V)) = *((const float*) (M)); } while(0)
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((uchar*) V,(uchar*) (&M),sizeof(float))
#define floatstore(T,V) memcpy((uchar*)(T), (uchar*)(&V),sizeof(float))
#define floatget(V,M) memcpy((uchar*) &V,(uchar*) (M),sizeof(float))
#define float8store(V,M) doublestore((V),(M))
#else
/*
We're here if it's not a IA-32 architecture (Win32 and UNIX IA-32 defines
were done before)
*/
#define sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) +\
((int16) ((int16) (A)[1]) << 8))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])) : \
(((uint32) (uchar) (A)[2]) << 16) |\
(((uint32) (uchar) (A)[1]) << 8) | \
((uint32) (uchar) (A)[0])))
#define sint4korr(A) (int32) (((int32) ((uchar) (A)[0])) +\
(((int32) ((uchar) (A)[1]) << 8)) +\
(((int32) ((uchar) (A)[2]) << 16)) +\
(((int32) ((int16) (A)[3]) << 24)))
#define sint8korr(A) (longlong) uint8korr(A)
#define uint2korr(A) (uint16) (((uint16) ((uchar) (A)[0])) +\
((uint16) ((uchar) (A)[1]) << 8))
#define uint3korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16))
#define uint4korr(A) (uint32) (((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24))
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) ((uchar) (A)[4])) << 32))
#define uint6korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) + \
(((uint32) ((uchar) (A)[1])) << 8) + \
(((uint32) ((uchar) (A)[2])) << 16) + \
(((uint32) ((uchar) (A)[3])) << 24)) + \
(((ulonglong) ((uchar) (A)[4])) << 32) + \
(((ulonglong) ((uchar) (A)[5])) << 40))
#define uint8korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
(((uint32) ((uchar) (A)[1])) << 8) +\
(((uint32) ((uchar) (A)[2])) << 16) +\
(((uint32) ((uchar) (A)[3])) << 24)) +\
(((ulonglong) (((uint32) ((uchar) (A)[4])) +\
(((uint32) ((uchar) (A)[5])) << 8) +\
(((uint32) ((uchar) (A)[6])) << 16) +\
(((uint32) ((uchar) (A)[7])) << 24))) <<\
32))
#define int2store(T,A) do { uint def_temp= (uint) (A) ;\
*((uchar*) (T))= (uchar)(def_temp); \
*((uchar*) (T)+1)=(uchar)((def_temp >> 8)); \
} while(0)
#define int3store(T,A) do { /*lint -save -e734 */\
*((uchar*)(T))=(uchar) ((A));\
*((uchar*) (T)+1)=(uchar) (((A) >> 8));\
*((uchar*)(T)+2)=(uchar) (((A) >> 16)); \
/*lint -restore */} while(0)
#define int4store(T,A) do { *((char *)(T))=(char) ((A));\
*(((char *)(T))+1)=(char) (((A) >> 8));\
*(((char *)(T))+2)=(char) (((A) >> 16));\
*(((char *)(T))+3)=(char) (((A) >> 24)); } while(0)
#define int5store(T,A) do { *((char *)(T))= (char)((A)); \
*(((char *)(T))+1)= (char)(((A) >> 8)); \
*(((char *)(T))+2)= (char)(((A) >> 16)); \
*(((char *)(T))+3)= (char)(((A) >> 24)); \
*(((char *)(T))+4)= (char)(((A) >> 32)); \
} while(0)
#define int6store(T,A) do { *((char *)(T))= (char)((A)); \
*(((char *)(T))+1)= (char)(((A) >> 8)); \
*(((char *)(T))+2)= (char)(((A) >> 16)); \
*(((char *)(T))+3)= (char)(((A) >> 24)); \
*(((char *)(T))+4)= (char)(((A) >> 32)); \
*(((char *)(T))+5)= (char)(((A) >> 40)); \
} while(0)
#define int8store(T,A) do { uint def_temp= (uint) (A), def_temp2= (uint) ((A) >> 32); \
int4store((T),def_temp); \
int4store((T+4),def_temp2); } while(0)
#ifdef WORDS_BIGENDIAN
#define float4store(T,A) do { *(T)= ((uchar *) &A)[3];\
*((T)+1)=(char) ((uchar *) &A)[2];\
*((T)+2)=(char) ((uchar *) &A)[1];\
*((T)+3)=(char) ((uchar *) &A)[0]; } while(0)
#define float4get(V,M) do { float def_temp;\
((uchar*) &def_temp)[0]=(M)[3];\
((uchar*) &def_temp)[1]=(M)[2];\
((uchar*) &def_temp)[2]=(M)[1];\
((uchar*) &def_temp)[3]=(M)[0];\
(V)=def_temp; } while(0)
#define float8store(T,V) do { *(T)= ((uchar *) &V)[7];\
*((T)+1)=(char) ((uchar *) &V)[6];\
*((T)+2)=(char) ((uchar *) &V)[5];\
*((T)+3)=(char) ((uchar *) &V)[4];\
*((T)+4)=(char) ((uchar *) &V)[3];\
*((T)+5)=(char) ((uchar *) &V)[2];\
*((T)+6)=(char) ((uchar *) &V)[1];\
*((T)+7)=(char) ((uchar *) &V)[0]; } while(0)
#define float8get(V,M) do { double def_temp;\
((uchar*) &def_temp)[0]=(M)[7];\
((uchar*) &def_temp)[1]=(M)[6];\
((uchar*) &def_temp)[2]=(M)[5];\
((uchar*) &def_temp)[3]=(M)[4];\
((uchar*) &def_temp)[4]=(M)[3];\
((uchar*) &def_temp)[5]=(M)[2];\
((uchar*) &def_temp)[6]=(M)[1];\
((uchar*) &def_temp)[7]=(M)[0];\
(V) = def_temp; } while(0)
#else
#define float4get(V,M) memcpy(&V, (M), sizeof(float))
#define float4store(V,M) memcpy(V, (&M), sizeof(float))
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
#define doublestore(T,V) do { *(((char*)T)+0)=(char) ((uchar *) &V)[4];\
*(((char*)T)+1)=(char) ((uchar *) &V)[5];\
*(((char*)T)+2)=(char) ((uchar *) &V)[6];\
*(((char*)T)+3)=(char) ((uchar *) &V)[7];\
*(((char*)T)+4)=(char) ((uchar *) &V)[0];\
*(((char*)T)+5)=(char) ((uchar *) &V)[1];\
*(((char*)T)+6)=(char) ((uchar *) &V)[2];\
*(((char*)T)+7)=(char) ((uchar *) &V)[3]; }\
while(0)
#define doubleget(V,M) do { double def_temp;\
((uchar*) &def_temp)[0]=(M)[4];\
((uchar*) &def_temp)[1]=(M)[5];\
((uchar*) &def_temp)[2]=(M)[6];\
((uchar*) &def_temp)[3]=(M)[7];\
((uchar*) &def_temp)[4]=(M)[0];\
((uchar*) &def_temp)[5]=(M)[1];\
((uchar*) &def_temp)[6]=(M)[2];\
((uchar*) &def_temp)[7]=(M)[3];\
(V) = def_temp; } while(0)
#endif /* __FLOAT_WORD_ORDER */
#define float8get(V,M) doubleget((V),(M))
#define float8store(V,M) doublestore((V),(M))
#endif /* WORDS_BIGENDIAN */
#endif /* __i386__ OR _WIN32 */
/*
Macro for reading 32-bit integer from network byte order (big-endian)
from unaligned memory location.
*/
#define int4net(A) (int32) (((uint32) ((uchar) (A)[3])) |\
(((uint32) ((uchar) (A)[2])) << 8) |\
(((uint32) ((uchar) (A)[1])) << 16) |\
(((uint32) ((uchar) (A)[0])) << 24))
/*
Define-funktions for reading and storing in machine format from/to
short/long to/from some place in memory V should be a (not
register) variable, M is a pointer to byte
*/
#ifdef WORDS_BIGENDIAN
#define ushortget(V,M) do { V = (uint16) (((uint16) ((uchar) (M)[1]))+\
((uint16) ((uint16) (M)[0]) << 8)); } while(0)
#define shortget(V,M) do { V = (short) (((short) ((uchar) (M)[1]))+\
((short) ((short) (M)[0]) << 8)); } while(0)
#define longget(V,M) do { int32 def_temp;\
((uchar*) &def_temp)[0]=(M)[0];\
((uchar*) &def_temp)[1]=(M)[1];\
((uchar*) &def_temp)[2]=(M)[2];\
((uchar*) &def_temp)[3]=(M)[3];\
(V)=def_temp; } while(0)
#define ulongget(V,M) do { uint32 def_temp;\
((uchar*) &def_temp)[0]=(M)[0];\
((uchar*) &def_temp)[1]=(M)[1];\
((uchar*) &def_temp)[2]=(M)[2];\
((uchar*) &def_temp)[3]=(M)[3];\
(V)=def_temp; } while(0)
#define shortstore(T,A) do { uint def_temp=(uint) (A) ;\
*(((char*)T)+1)=(char)(def_temp); \
*(((char*)T)+0)=(char)(def_temp >> 8); } while(0)
#define longstore(T,A) do { *(((char*)T)+3)=((A));\
*(((char*)T)+2)=(((A) >> 8));\
*(((char*)T)+1)=(((A) >> 16));\
*(((char*)T)+0)=(((A) >> 24)); } while(0)
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
#define floatstore(T,V) memcpy((T), (void*) (&V), sizeof(float))
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
#else
#define ushortget(V,M) do { V = uint2korr(M); } while(0)
#define shortget(V,M) do { V = sint2korr(M); } while(0)
#define longget(V,M) do { V = sint4korr(M); } while(0)
#define ulongget(V,M) do { V = uint4korr(M); } while(0)
#define shortstore(T,V) int2store(T,V)
#define longstore(T,V) int4store(T,V)
#ifndef floatstore
#define floatstore(T,V) memcpy((T), (void *) (&V), sizeof(float))
#define floatget(V,M) memcpy(&V, (M), sizeof(float))
#endif
#ifndef doubleget
#define doubleget(V,M) memcpy(&V, (M), sizeof(double))
#define doublestore(T,V) memcpy((T), (void *) &V, sizeof(double))
#endif /* doubleget */
#define longlongget(V,M) memcpy(&V, (M), sizeof(ulonglong))
#define longlongstore(T,V) memcpy((T), &V, sizeof(ulonglong))
#endif /* WORDS_BIGENDIAN */
#include <my_byteorder.h>
#ifdef HAVE_CHARSET_utf8
#define MYSQL_UNIVERSAL_CLIENT_CHARSET "utf8"
@ -1396,10 +1106,6 @@ static inline char *dlerror(void)
#endif
/* Define some useful general macros (should be done after all headers). */
#if !defined(max)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
#define MY_MAX(a, b) ((a) > (b) ? (a) : (b))
#define MY_MIN(a, b) ((a) < (b) ? (a) : (b))

View File

@ -84,8 +84,10 @@ static const char *handler_error_messages[]=
"Index column length exceeds limit",
"Index corrupted",
"Undo record too big",
"Table is being used in foreign key check",
"Invalid InnoDB FTS Doc ID",
"Table is being used in foreign key check",
"Tablespace already exists",
"Too many columns",
"Row is not visible by the current transaction",
"Operation was interrupted by end user (probably kill command?)",
"Disk full"

View File

@ -1,8 +1,8 @@
#ifndef MY_MD5_INCLUDED
#define MY_MD5_INCLUDED
/* Copyright (c) 2000, 2001, 2007 MySQL AB, 2009 Sun Microsystems, Inc.
Use is subject to license terms
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
Copyright (c) 2013 Monty Program Ab
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
@ -17,79 +17,36 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
/* See md5.c for explanation and copyright information. */
#include "m_string.h"
#define MD5_HASH_SIZE 16 /* Hash size in bytes */
/*
* $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $
*/
#if defined(HAVE_YASSL) || defined(HAVE_OPENSSL)
/*
Use MD5 implementation provided by the SSL libraries.
Wrapper function for MD5 implementation.
*/
#if defined(HAVE_YASSL)
C_MODE_START
void my_md5_hash(char *digest, const char *buf, int len);
C_MODE_END
#else /* HAVE_YASSL */
#include <openssl/md5.h>
#define MY_MD5_HASH(digest, buf, len) \
do { \
MD5_CTX ctx; \
MD5_Init (&ctx); \
MD5_Update (&ctx, buf, len); \
MD5_Final (digest, &ctx); \
} while (0)
#endif /* HAVE_YASSL */
#else /* HAVE_YASSL || HAVE_OPENSSL */
/* Fallback to the MySQL's implementation. */
/* Unlike previous versions of this code, uint32 need not be exactly
32 bits, merely 32 bits or more. Choosing a data type which is 32
bits instead of 64 is not important; speed is considerably more
important. ANSI guarantees that "unsigned long" will be big enough,
and always using it seems to have few disadvantages. */
typedef uint32 cvs_uint32;
typedef struct {
cvs_uint32 buf[4];
cvs_uint32 bits[2];
unsigned char in[64];
} my_MD5Context;
C_MODE_START
void my_MD5Init (my_MD5Context *context);
void my_MD5Update (my_MD5Context *context,
unsigned char const *buf, unsigned len);
void my_MD5Final (unsigned char digest[16],
my_MD5Context *context);
C_MODE_END
#define MY_MD5_HASH(digest,buf,len) \
do { \
my_MD5Context ctx; \
my_MD5Init (&ctx); \
my_MD5Update (&ctx, buf, len); \
my_MD5Final (digest, &ctx); \
} while (0)
#endif /* defined(HAVE_YASSL) || defined(HAVE_OPENSSL) */
C_MODE_START
#ifdef __cplusplus
extern "C" {
#endif
void compute_md5_hash(char *digest, const char *buf, int len);
C_MODE_END
/*
Convert an array of bytes to a hexadecimal representation.
Used to generate a hexadecimal representation of a message digest.
*/
static inline void array_to_hex(char *to, const unsigned char *str, uint len)
{
const unsigned char *str_end= str + len;
for (; str != str_end; ++str)
{
*to++= _dig_vec_lower[((uchar) *str) >> 4];
*to++= _dig_vec_lower[((uchar) *str) & 0x0F];
}
}
#ifdef __cplusplus
}
#endif
#endif /* MY_MD5_INCLUDED */

32
include/my_rnd.h Normal file
View File

@ -0,0 +1,32 @@
/* Copyright (C) 2013 Monty Program Ab
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; version 2 or later of the License.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifndef _my_rnd_h
#define _my_rnd_h
C_MODE_START
struct my_rnd_struct {
unsigned long seed1,seed2,max_value;
double max_value_dbl;
};
void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2);
double my_rnd(struct my_rnd_struct *rand_st);
double my_rnd_ssl(struct my_rnd_struct *rand_st);
C_MODE_END
#endif /* _my_rnd_h */

View File

@ -174,8 +174,6 @@ extern void *my_memdup(const void *from,size_t length,myf MyFlags);
extern char *my_strdup(const char *from,myf MyFlags);
extern char *my_strndup(const char *from, size_t length, myf MyFlags);
extern int sf_leaking_memory; /* set to 1 to disable memleak detection */
#ifdef HAVE_LARGE_PAGES
extern uint my_get_large_page_size(void);
extern uchar * my_large_malloc(size_t size, myf my_flags);
@ -199,14 +197,18 @@ extern void my_large_free(uchar *ptr);
#endif /* GNUC */
#define my_alloca(SZ) alloca((size_t) (SZ))
#define my_afree(PTR) ((void)0)
#define my_safe_alloca(size, max_alloca_sz) ((size <= max_alloca_sz) ? \
my_alloca(size) : \
my_malloc(size, MYF(0)))
#define my_safe_afree(ptr, size, max_alloca_sz) if (size > max_alloca_sz) \
my_free(ptr)
#else
#define my_alloca(SZ) my_malloc(SZ,MYF(MY_FAE))
#define my_afree(PTR) my_free(PTR)
#define my_safe_alloca(size, max_alloca_sz) my_alloca(size)
#define my_safe_afree(ptr, size, max_alloca_sz) my_afree(ptr)
#endif /* HAVE_ALLOCA */
#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : my_malloc(size,MYF(MY_FAE)))
#define my_safe_afree(ptr, size, min_length) ((size <= min_length) ? my_afree(ptr) : my_free(ptr))
#ifndef errno /* did we already get it? */
#ifdef HAVE_ERRNO_AS_DEFINE
#include <errno.h> /* errno is a define */
@ -223,6 +225,7 @@ extern void (*fatal_error_handler_hook)(uint my_err, const char *str,
myf MyFlags);
extern uint my_file_limit;
extern ulonglong my_thread_stack_size;
extern int sf_leaking_memory; /* set to 1 to disable memleak detection */
extern void (*proc_info_hook)(void *, const PSI_stage_info *, PSI_stage_info *,
const char *, const char *, const unsigned int);
@ -265,11 +268,6 @@ extern my_bool my_disable_locking, my_disable_async_io,
extern my_bool my_disable_sync;
extern char wild_many,wild_one,wild_prefix;
extern const char *charsets_dir;
/* from default.c */
extern const char *my_defaults_extra_file;
extern const char *my_defaults_group_suffix;
extern const char *my_defaults_file;
extern my_bool timed_mutexes;
enum loglevel {
@ -566,13 +564,8 @@ my_off_t my_b_safe_tell(IO_CACHE* info); /* picks the correct tell() */
typedef uint32 ha_checksum;
extern ulong my_crc_dbug_check;
/* Define the type of function to be passed to process_default_option_files */
typedef int (*Process_option_func)(void *ctx, const char *group_name,
const char *option);
#include <my_alloc.h>
/* Prototypes for mysys and my_func functions */
extern int my_copy(const char *from,const char *to,myf MyFlags);
@ -631,6 +624,13 @@ extern int my_access(const char *path, int amode);
extern int check_if_legal_filename(const char *path);
extern int check_if_legal_tablename(const char *path);
#ifdef __WIN__
extern my_bool is_filename_allowed(const char *name, size_t length,
my_bool allow_current_dir);
#else /* __WIN__ */
# define is_filename_allowed(name, length, allow_cwd) (TRUE)
#endif /* __WIN__ */
#ifdef _WIN32
/* Windows-only functions (CRT equivalents)*/
extern HANDLE my_get_osfhandle(File fd);
@ -656,15 +656,16 @@ extern void thr_set_sync_wait_callback(void (*before_sync)(void),
extern int my_sync(File fd, myf my_flags);
extern int my_sync_dir(const char *dir_name, myf my_flags);
extern int my_sync_dir_by_file(const char *file_name, myf my_flags);
extern void my_error(int nr,myf MyFlags, ...);
extern const char *my_get_err_msg(uint nr);
extern void my_error(uint nr,myf MyFlags, ...);
extern void my_printf_error(uint my_err, const char *format,
myf MyFlags, ...)
ATTRIBUTE_FORMAT(printf, 2, 4);
extern void my_printv_error(uint error, const char *format, myf MyFlags,
va_list ap);
extern int my_error_register(const char** (*get_errmsgs) (),
int first, int last);
extern const char **my_error_unregister(int first, int last);
uint first, uint last);
extern const char **my_error_unregister(uint first, uint last);
extern void my_message(uint my_err, const char *str,myf MyFlags);
extern void my_message_stderr(uint my_err, const char *str, myf MyFlags);
extern my_bool my_init(void);
@ -853,22 +854,6 @@ static inline char *safe_strdup_root(MEM_ROOT *root, const char *str)
}
extern char *strmake_root(MEM_ROOT *root,const char *str,size_t len);
extern void *memdup_root(MEM_ROOT *root,const void *str, size_t len);
extern int get_defaults_options(int argc, char **argv,
char **defaults, char **extra_defaults,
char **group_suffix);
extern my_bool my_getopt_use_args_separator;
extern my_bool my_getopt_is_args_separator(const char* arg);
extern int my_load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv, const char ***);
extern int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
extern int my_search_option_files(const char *conf_file, int *argc,
char ***argv, uint *args_used,
Process_option_func func, void *func_ctx,
const char **default_directories);
extern void free_defaults(char **argv);
extern void my_print_default_files(const char *conf_file);
extern void print_defaults(const char *conf_file, const char **groups);
extern my_bool my_compress(uchar *, size_t *, size_t *);
extern my_bool my_uncompress(uchar *, size_t , size_t *);
extern uchar *my_compress_alloc(const uchar *packet, size_t *len,
@ -960,14 +945,6 @@ void my_uuid(uchar *guid);
void my_uuid2str(const uchar *guid, char *s);
void my_uuid_end();
struct my_rnd_struct {
unsigned long seed1,seed2,max_value;
double max_value_dbl;
};
void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2);
double my_rnd(struct my_rnd_struct *rand_st);
/* character sets */
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
@ -1030,6 +1007,5 @@ void my_init_mysys_psi_keys(void);
struct st_mysql_file;
extern struct st_mysql_file *mysql_stdin;
C_MODE_END
#endif /* _my_sys_h */

View File

@ -146,8 +146,8 @@ void my_init_time(void);
estimate.
RETURN VALUES
FALSE The value seems sane
TRUE The MYSQL_TIME value is definitely out of range
TRUE The value seems sane
FALSE The MYSQL_TIME value is definitely out of range
*/
static inline my_bool validate_timestamp_range(const MYSQL_TIME *t)

View File

@ -31,7 +31,8 @@ extern "C" {
#include <queues.h>
#define MYRG_NAME_EXT ".MRG"
#define MYRG_NAME_EXT ".MRG"
#define MYRG_NAME_TMPEXT ".MRG_TMP"
/* In which table to INSERT rows */
#define MERGE_INSERT_DISABLED 0

View File

@ -0,0 +1,13 @@
#ifndef CLIENT_AUTHENTICATION_H
#define CLIENT_AUTHENTICATION_H
#include "mysql.h"
#include "mysql/client_plugin.h"
C_MODE_START
int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
int sha256_password_init(char *, size_t, int, va_list);
int sha256_password_deinit(void);
C_MODE_END
#endif

View File

@ -46,6 +46,7 @@ class Item;
#endif
typedef char my_bool;
typedef void * MYSQL_PLUGIN;
#include <mysql/services.h>
@ -71,10 +72,10 @@ typedef struct st_mysql_xid MYSQL_XID;
*/
/* MySQL plugin interface version */
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0103
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0104
/* MariaDB plugin interface version */
#define MARIA_PLUGIN_INTERFACE_VERSION 0x0105
#define MARIA_PLUGIN_INTERFACE_VERSION 0x0107
/*
The allowable types of plugins
@ -87,7 +88,8 @@ typedef struct st_mysql_xid MYSQL_XID;
#define MYSQL_AUDIT_PLUGIN 5 /* The Audit plugin type */
#define MYSQL_REPLICATION_PLUGIN 6 /* The replication plugin type */
#define MYSQL_AUTHENTICATION_PLUGIN 7 /* The authentication plugin type */
#define MYSQL_MAX_PLUGIN_TYPE_NUM 8 /* The number of plugin types */
#define MYSQL_VALIDATE_PASSWORD_PLUGIN 8 /* validate password plugin type */
#define MYSQL_MAX_PLUGIN_TYPE_NUM 9 /* The number of plugin types */
/* We use the following strings to define licenses for plugins */
#define PLUGIN_LICENSE_PROPRIETARY 0
@ -560,7 +562,7 @@ struct handlerton;
/*
API for Replication plugin. (MYSQL_REPLICATION_PLUGIN)
*/
#define MYSQL_REPLICATION_INTERFACE_VERSION 0x0100
#define MYSQL_REPLICATION_INTERFACE_VERSION 0x0200
/**
Replication plugin descriptor
@ -608,6 +610,7 @@ int thd_sql_command(const MYSQL_THD thd);
void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton);
void thd_storage_lock_wait(MYSQL_THD thd, long long value);
int thd_tx_isolation(const MYSQL_THD thd);
int thd_tx_is_read_only(const MYSQL_THD thd);
char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length,
unsigned int max_query_len);
/* Increments the row counter, see THD::row_count */

View File

@ -1,5 +1,6 @@
#include "plugin.h"
typedef char my_bool;
typedef void * MYSQL_PLUGIN;
#include <mysql/services.h>
#include <mysql/service_my_snprintf.h>
extern struct my_snprintf_service_st {
@ -107,6 +108,13 @@ extern struct thd_timezone_service_st {
} *thd_timezone_service;
my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
#include <mysql/service_sha1.h>
extern struct my_sha1_service_st {
void (*my_sha1_type)(unsigned char*, const char*, size_t);
void (*my_sha1_multi_type)(unsigned char*, ...);
} *my_sha1_service;
void my_sha1(unsigned char*, const char*, size_t);
void my_sha1_multi(unsigned char*, ...);
struct st_mysql_xid {
long formatID;
long gtrid_length;
@ -247,6 +255,7 @@ int thd_sql_command(const void* thd);
void **thd_ha_data(const void* thd, const struct handlerton *hton);
void thd_storage_lock_wait(void* thd, long long value);
int thd_tx_isolation(const void* thd);
int thd_tx_is_read_only(const void* thd);
char *thd_security_context(void* thd, char *buffer, unsigned int length,
unsigned int max_query_len);
void thd_inc_row_count(void* thd);

View File

@ -1,5 +1,6 @@
#include <mysql/plugin.h>
typedef char my_bool;
typedef void * MYSQL_PLUGIN;
#include <mysql/services.h>
#include <mysql/service_my_snprintf.h>
extern struct my_snprintf_service_st {
@ -107,6 +108,13 @@ extern struct thd_timezone_service_st {
} *thd_timezone_service;
my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
#include <mysql/service_sha1.h>
extern struct my_sha1_service_st {
void (*my_sha1_type)(unsigned char*, const char*, size_t);
void (*my_sha1_multi_type)(unsigned char*, ...);
} *my_sha1_service;
void my_sha1(unsigned char*, const char*, size_t);
void my_sha1_multi(unsigned char*, ...);
struct st_mysql_xid {
long formatID;
long gtrid_length;
@ -247,6 +255,7 @@ int thd_sql_command(const void* thd);
void **thd_ha_data(const void* thd, const struct handlerton *hton);
void thd_storage_lock_wait(void* thd, long long value);
int thd_tx_isolation(const void* thd);
int thd_tx_is_read_only(const void* thd);
char *thd_security_context(void* thd, char *buffer, unsigned int length,
unsigned int max_query_len);
void thd_inc_row_count(void* thd);

View File

@ -34,6 +34,27 @@
return values of the plugin authenticate_user() method.
*/
/**
Authentication failed, plugin internal error.
An error occurred in the authentication plugin itself.
These errors are reported in table performance_schema.host_cache,
column COUNT_AUTH_PLUGIN_ERRORS.
*/
#define CR_AUTH_PLUGIN_ERROR 3
/**
Authentication failed, client server handshake.
An error occurred during the client server handshake.
These errors are reported in table performance_schema.host_cache,
column COUNT_HANDSHAKE_ERRORS.
*/
#define CR_AUTH_HANDSHAKE 2
/**
Authentication failed, user credentials.
For example, wrong passwords.
These errors are reported in table performance_schema.host_cache,
column COUNT_AUTHENTICATION_ERRORS.
*/
#define CR_AUTH_USER_CREDENTIALS 1
/**
Authentication failed. Additionally, all other CR_xxx values
(libmysql error code) can be used too.

View File

@ -1,5 +1,6 @@
#include "plugin.h"
typedef char my_bool;
typedef void * MYSQL_PLUGIN;
#include <mysql/services.h>
#include <mysql/service_my_snprintf.h>
extern struct my_snprintf_service_st {
@ -107,6 +108,13 @@ extern struct thd_timezone_service_st {
} *thd_timezone_service;
my_time_t thd_TIME_to_gmt_sec(void* thd, const MYSQL_TIME *ltime, unsigned int *errcode);
void thd_gmt_sec_to_TIME(void* thd, MYSQL_TIME *ltime, my_time_t t);
#include <mysql/service_sha1.h>
extern struct my_sha1_service_st {
void (*my_sha1_type)(unsigned char*, const char*, size_t);
void (*my_sha1_multi_type)(unsigned char*, ...);
} *my_sha1_service;
void my_sha1(unsigned char*, const char*, size_t);
void my_sha1_multi(unsigned char*, ...);
struct st_mysql_xid {
long formatID;
long gtrid_length;
@ -200,6 +208,7 @@ int thd_sql_command(const void* thd);
void **thd_ha_data(const void* thd, const struct handlerton *hton);
void thd_storage_lock_wait(void* thd, long long value);
int thd_tx_isolation(const void* thd);
int thd_tx_is_read_only(const void* thd);
char *thd_security_context(void* thd, char *buffer, unsigned int length,
unsigned int max_query_len);
void thd_inc_row_count(void* thd);

View File

@ -518,7 +518,7 @@ static inline void inline_mysql_file_register(
)
{
#ifdef HAVE_PSI_FILE_INTERFACE
PSI_CALL(register_file)(category, info, count);
PSI_FILE_CALL(register_file)(category, info, count);
#endif
}
@ -533,13 +533,13 @@ inline_mysql_file_fgets(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_READ);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_READ);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) size, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) size, src_file, src_line);
result= fgets(str, size, file->m_file);
PSI_CALL(end_file_wait)(locker, result ? strlen(result) : 0);
PSI_FILE_CALL(end_file_wait)(locker, result ? strlen(result) : 0);
return result;
}
#endif
@ -559,13 +559,13 @@ inline_mysql_file_fgetc(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_READ);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_READ);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line);
result= fgetc(file->m_file);
PSI_CALL(end_file_wait)(locker, (size_t) 1);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1);
return result;
}
#endif
@ -586,14 +586,14 @@ inline_mysql_file_fputs(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
bytes= str ? strlen(str) : 0;
PSI_CALL(start_file_wait)(locker, bytes, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, bytes, src_file, src_line);
result= fputs(str, file->m_file);
PSI_CALL(end_file_wait)(locker, bytes);
PSI_FILE_CALL(end_file_wait)(locker, bytes);
return result;
}
#endif
@ -613,13 +613,13 @@ inline_mysql_file_fputc(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 1, src_file, src_line);
result= fputc(c, file->m_file);
PSI_CALL(end_file_wait)(locker, (size_t) 1);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 1);
return result;
}
#endif
@ -639,15 +639,15 @@ inline_mysql_file_fprintf(MYSQL_FILE *file, const char *format, ...)
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, __FILE__, __LINE__);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, __FILE__, __LINE__);
va_start(args, format);
result= vfprintf(file->m_file, format, args);
va_end(args);
PSI_CALL(end_file_wait)(locker, (size_t) result);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) result);
return result;
}
#endif
@ -669,13 +669,13 @@ inline_mysql_file_vfprintf(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= vfprintf(file->m_file, format, args);
PSI_CALL(end_file_wait)(locker, (size_t) result);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) result);
return result;
}
#endif
@ -695,13 +695,13 @@ inline_mysql_file_fflush(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_FLUSH);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_FLUSH);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= fflush(file->m_file);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -727,13 +727,13 @@ inline_mysql_file_fstat(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, filenr,
PSI_FILE_FSTAT);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, filenr, PSI_FILE_FSTAT);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_fstat(filenr, stat_area, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -753,14 +753,13 @@ inline_mysql_file_stat(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state,
key, PSI_FILE_STAT,
path, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_STAT, path, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_open_wait)(locker, src_file, src_line);
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
result= my_stat(path, stat_area, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_open_wait)(locker, result);
return result;
}
#endif
@ -780,14 +779,14 @@ inline_mysql_file_chsize(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file,
PSI_FILE_CHSIZE);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_CHSIZE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) newlength, src_file,
PSI_FILE_CALL(start_file_wait)(locker, (size_t) newlength, src_file,
src_line);
result= my_chsize(file, newlength, filler, flags);
PSI_CALL(end_file_wait)(locker, (size_t) newlength);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) newlength);
return result;
}
#endif
@ -810,14 +809,14 @@ inline_mysql_file_fopen(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_STREAM_OPEN, filename, that);
if (likely(locker != NULL))
{
that->m_psi= PSI_CALL(start_file_open_wait)(locker, src_file,
src_line);
PSI_FILE_CALL(start_file_open_wait)
(locker, src_file, src_line);
that->m_file= my_fopen(filename, flags, myFlags);
PSI_CALL(end_file_open_wait)(locker);
that->m_psi= PSI_FILE_CALL(end_file_open_wait)(locker, that->m_file);
if (unlikely(that->m_file == NULL))
{
my_free(that);
@ -851,13 +850,13 @@ inline_mysql_file_fclose(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_STREAM_CLOSE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_STREAM_CLOSE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
result= my_fclose(file->m_file, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_close_wait)(locker, result);
my_free(file);
return result;
}
@ -881,17 +880,17 @@ inline_mysql_file_fread(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_read;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_READ);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_READ);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_fread(file->m_file, buffer, count, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_read= (result == 0) ? count : 0;
else
bytes_read= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_read);
PSI_FILE_CALL(end_file_wait)(locker, bytes_read);
return result;
}
#endif
@ -912,17 +911,17 @@ inline_mysql_file_fwrite(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_written;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_fwrite(file->m_file, buffer, count, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_written= (result == 0) ? count : 0;
else
bytes_written= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_written);
PSI_FILE_CALL(end_file_wait)(locker, bytes_written);
return result;
}
#endif
@ -942,13 +941,13 @@ inline_mysql_file_fseek(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_SEEK);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_SEEK);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_fseek(file->m_file, pos, whence, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -968,13 +967,13 @@ inline_mysql_file_ftell(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_stream_locker)(&state, file->m_psi,
PSI_FILE_TELL);
locker= PSI_FILE_CALL(get_thread_file_stream_locker)
(&state, file->m_psi, PSI_FILE_TELL);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_ftell(file->m_file, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -994,13 +993,13 @@ inline_mysql_file_create(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE,
filename, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_CREATE, filename, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_open_wait)(locker, src_file, src_line);
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
file= my_create(filename, create_flags, access_flags, myFlags);
PSI_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
return file;
}
#endif
@ -1024,7 +1023,7 @@ inline_mysql_file_create_temp(
*/
file= create_temp_file(to, dir, pfx, mode, myFlags);
#ifdef HAVE_PSI_FILE_INTERFACE
PSI_CALL(create_file)(key, to, file);
PSI_FILE_CALL(create_file)(key, to, file);
#endif
return file;
}
@ -1040,13 +1039,13 @@ inline_mysql_file_open(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_OPEN,
filename, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_OPEN, filename, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_open_wait)(locker, src_file, src_line);
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
file= my_open(filename, flags, myFlags);
PSI_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
return file;
}
#endif
@ -1066,13 +1065,13 @@ inline_mysql_file_close(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file,
PSI_FILE_CLOSE);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_CLOSE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
result= my_close(file, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_close_wait)(locker, result);
return result;
}
#endif
@ -1093,17 +1092,17 @@ inline_mysql_file_read(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_read;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file,
PSI_FILE_READ);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_READ);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_read(file, buffer, count, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_read= (result == 0) ? count : 0;
else
bytes_read= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_read);
PSI_FILE_CALL(end_file_wait)(locker, bytes_read);
return result;
}
#endif
@ -1124,17 +1123,17 @@ inline_mysql_file_write(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_written;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_write(file, buffer, count, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_written= (result == 0) ? count : 0;
else
bytes_written= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_written);
PSI_FILE_CALL(end_file_wait)(locker, bytes_written);
return result;
}
#endif
@ -1155,16 +1154,17 @@ inline_mysql_file_pread(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_read;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_READ);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_READ);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_pread(file, buffer, count, offset, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_read= (result == 0) ? count : 0;
else
bytes_read= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_read);
PSI_FILE_CALL(end_file_wait)(locker, bytes_read);
return result;
}
#endif
@ -1185,17 +1185,17 @@ inline_mysql_file_pwrite(
struct PSI_file_locker *locker;
PSI_file_locker_state state;
size_t bytes_written;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file,
PSI_FILE_WRITE);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_WRITE);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, count, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, count, src_file, src_line);
result= my_pwrite(file, buffer, count, offset, flags);
if (flags & (MY_NABP | MY_FNABP))
bytes_written= (result == 0) ? count : 0;
else
bytes_written= (result != MY_FILE_ERROR) ? result : 0;
PSI_CALL(end_file_wait)(locker, bytes_written);
PSI_FILE_CALL(end_file_wait)(locker, bytes_written);
return result;
}
#endif
@ -1215,12 +1215,13 @@ inline_mysql_file_seek(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_SEEK);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_SEEK);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_seek(file, pos, whence, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -1240,12 +1241,13 @@ inline_mysql_file_tell(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, file, PSI_FILE_TELL);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, file, PSI_FILE_TELL);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_tell(file, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -1265,13 +1267,13 @@ inline_mysql_file_delete(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE,
name, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_DELETE, name, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
result= my_delete(name, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_close_wait)(locker, result);
return result;
}
#endif
@ -1291,13 +1293,13 @@ inline_mysql_file_rename(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_RENAME,
to, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_RENAME, to, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_rename(from, to, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -1318,14 +1320,14 @@ inline_mysql_file_create_with_symlink(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_CREATE,
filename, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_CREATE, filename, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_open_wait)(locker, src_file, src_line);
PSI_FILE_CALL(start_file_open_wait)(locker, src_file, src_line);
file= my_create_with_symlink(linkname, filename, create_flags, access_flags,
flags);
PSI_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor)(locker, file);
return file;
}
#endif
@ -1346,13 +1348,13 @@ inline_mysql_file_delete_with_symlink(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_DELETE,
name, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_DELETE, name, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_close_wait)(locker, src_file, src_line);
result= my_delete_with_symlink(name, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_close_wait)(locker, result);
return result;
}
#endif
@ -1372,13 +1374,13 @@ inline_mysql_file_rename_with_symlink(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_name_locker)(&state, key, PSI_FILE_RENAME,
to, &locker);
locker= PSI_FILE_CALL(get_thread_file_name_locker)
(&state, key, PSI_FILE_RENAME, to, &locker);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_rename_with_symlink(from, to, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif
@ -1398,12 +1400,13 @@ inline_mysql_file_sync(
#ifdef HAVE_PSI_FILE_INTERFACE
struct PSI_file_locker *locker;
PSI_file_locker_state state;
locker= PSI_CALL(get_thread_file_descriptor_locker)(&state, fd, PSI_FILE_SYNC);
locker= PSI_FILE_CALL(get_thread_file_descriptor_locker)
(&state, fd, PSI_FILE_SYNC);
if (likely(locker != NULL))
{
PSI_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
PSI_FILE_CALL(start_file_wait)(locker, (size_t) 0, src_file, src_line);
result= my_sync(fd, flags);
PSI_CALL(end_file_wait)(locker, (size_t) 0);
PSI_FILE_CALL(end_file_wait)(locker, (size_t) 0);
return result;
}
#endif

View File

@ -70,7 +70,7 @@ inline_mysql_start_idle_wait(PSI_idle_locker_state *state,
const char *src_file, int src_line)
{
struct PSI_idle_locker *locker;
locker= PSI_CALL(start_idle_wait)(state, src_file, src_line);
locker= PSI_IDLE_CALL(start_idle_wait)(state, src_file, src_line);
return locker;
}
@ -82,7 +82,7 @@ static inline void
inline_mysql_end_idle_wait(struct PSI_idle_locker *locker)
{
if (likely(locker != NULL))
PSI_CALL(end_idle_wait)(locker);
PSI_IDLE_CALL(end_idle_wait)(locker);
}
#endif

View File

@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
#ifdef __WIN__
#include <ws2def.h>
#include <winsock2.h>
#include <MSWSock.h>
#define SOCKBUF_T char
#else
#include <netinet/in.h>
@ -121,7 +122,7 @@ mysql_socket_set_address(
{
#ifdef HAVE_PSI_SOCKET_INTERFACE
if (socket.m_psi != NULL)
PSI_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len);
PSI_SOCKET_CALL(set_socket_info)(socket.m_psi, NULL, addr, addr_len);
#endif
}
@ -141,7 +142,7 @@ MYSQL_SOCKET socket __attribute__ ((unused))
{
#ifdef HAVE_PSI_SOCKET_INTERFACE
if (socket.m_psi != NULL)
PSI_CALL(set_socket_thread_owner)(socket.m_psi);
PSI_SOCKET_CALL(set_socket_thread_owner)(socket.m_psi);
#endif
}
@ -247,8 +248,8 @@ inline_mysql_start_socket_wait(PSI_socket_locker_state *state,
struct PSI_socket_locker *locker;
if (mysql_socket.m_psi != NULL)
{
locker= PSI_CALL(start_socket_wait)(state, mysql_socket.m_psi, op,
byte_count, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(state, mysql_socket.m_psi, op, byte_count, src_file, src_line);
}
else
locker= NULL;
@ -263,7 +264,7 @@ static inline void
inline_mysql_end_socket_wait(struct PSI_socket_locker *locker, size_t byte_count)
{
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, byte_count);
PSI_SOCKET_CALL(end_socket_wait)(locker, byte_count);
}
/**
@ -276,7 +277,7 @@ static inline void
inline_mysql_socket_set_state(MYSQL_SOCKET socket, enum PSI_socket_state state)
{
if (socket.m_psi != NULL)
PSI_CALL(set_socket_state)(socket.m_psi, state);
PSI_SOCKET_CALL(set_socket_state)(socket.m_psi, state);
}
#endif /* HAVE_PSI_SOCKET_INTERFACE */
@ -537,7 +538,7 @@ static inline void inline_mysql_socket_register(
PSI_socket_info *info,
int count)
{
PSI_CALL(register_socket)(category, info, count);
PSI_SOCKET_CALL(register_socket)(category, info, count);
}
#endif
@ -551,16 +552,15 @@ inline_mysql_socket_socket
#endif
int domain, int type, int protocol)
{
MYSQL_SOCKET mysql_socket;
MYSQL_SOCKET mysql_socket= MYSQL_INVALID_SOCKET;
mysql_socket.fd= socket(domain, type, protocol);
#ifdef HAVE_PSI_SOCKET_INTERFACE
mysql_socket.m_psi= PSI_CALL(init_socket)(key, (const my_socket*)&mysql_socket.fd);
if (likely(mysql_socket.fd != INVALID_SOCKET && mysql_socket.m_psi != NULL))
PSI_CALL(set_socket_info)(mysql_socket.m_psi, &mysql_socket.fd, NULL, 0);
#else
mysql_socket.m_psi= NULL;
if (likely(mysql_socket.fd != INVALID_SOCKET))
{
mysql_socket.m_psi= PSI_SOCKET_CALL(init_socket)
(key, (const my_socket*)&mysql_socket.fd, NULL, 0);
}
#endif
return mysql_socket;
}
@ -583,17 +583,18 @@ inline_mysql_socket_bind
/* Instrumentation start */
PSI_socket_locker_state state;
PSI_socket_locker *locker;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
/* Instrumented code */
result= bind(mysql_socket.fd, addr, len);
/* Instrumentation end */
PSI_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, len);
if (result == 0)
PSI_SOCKET_CALL(set_socket_info)(mysql_socket.m_psi, NULL, addr, len);
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -622,15 +623,15 @@ inline_mysql_socket_getsockname
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
/* Instrumented code */
result= getsockname(mysql_socket.fd, addr, len);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -660,15 +661,15 @@ inline_mysql_socket_connect
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
/* Instrumented code */
result= connect(mysql_socket.fd, addr, len);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -698,15 +699,15 @@ inline_mysql_socket_getpeername
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_BIND, (size_t)0, src_file, src_line);
/* Instrumented code */
result= getpeername(mysql_socket.fd, addr, len);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -736,18 +737,18 @@ inline_mysql_socket_send
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_SEND, n, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
/* Instrumented code */
result= send(mysql_socket.fd, buf, n, flags);
result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
/* Instrumentation end */
if (locker != NULL)
{
size_t bytes_written;
bytes_written= (result > -1) ? result : 0;
PSI_CALL(end_socket_wait)(locker, bytes_written);
PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
}
return result;
@ -755,7 +756,7 @@ inline_mysql_socket_send
#endif
/* Non instrumented code */
result= send(mysql_socket.fd, buf, n, flags);
result= send(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
return result;
}
@ -778,18 +779,18 @@ inline_mysql_socket_recv
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
/* Instrumented code */
result= recv(mysql_socket.fd, buf, n, flags);
result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
/* Instrumentation end */
if (locker != NULL)
{
size_t bytes_read;
bytes_read= (result > -1) ? result : 0;
PSI_CALL(end_socket_wait)(locker, bytes_read);
PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
}
return result;
@ -797,7 +798,7 @@ inline_mysql_socket_recv
#endif
/* Non instrumented code */
result= recv(mysql_socket.fd, buf, n, flags);
result= recv(mysql_socket.fd, buf, IF_WIN((int),) n, flags);
return result;
}
@ -820,18 +821,18 @@ inline_mysql_socket_sendto
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_SEND, n, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_SEND, n, src_file, src_line);
/* Instrumented code */
result= sendto(mysql_socket.fd, buf, n, flags, addr, addr_len);
result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
/* Instrumentation end */
if (locker != NULL)
{
size_t bytes_written;
bytes_written = (result > -1) ? result : 0;
PSI_CALL(end_socket_wait)(locker, bytes_written);
PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_written);
}
return result;
@ -839,7 +840,7 @@ inline_mysql_socket_sendto
#endif
/* Non instrumented code */
result= sendto(mysql_socket.fd, buf, n, flags, addr, addr_len);
result= sendto(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
return result;
}
@ -863,18 +864,18 @@ inline_mysql_socket_recvfrom
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_RECV, (size_t)0, src_file, src_line);
/* Instrumented code */
result= recvfrom(mysql_socket.fd, buf, n, flags, addr, addr_len);
result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
/* Instrumentation end */
if (locker != NULL)
{
size_t bytes_read;
bytes_read = (result > -1) ? result : 0;
PSI_CALL(end_socket_wait)(locker, bytes_read);
PSI_SOCKET_CALL(end_socket_wait)(locker, bytes_read);
}
return result;
@ -882,7 +883,7 @@ inline_mysql_socket_recvfrom
#endif
/* Non instrumented code */
result= recvfrom(mysql_socket.fd, buf, n, flags, addr, addr_len);
result= recvfrom(mysql_socket.fd, buf, IF_WIN((int),) n, flags, addr, addr_len);
return result;
}
@ -905,15 +906,15 @@ inline_mysql_socket_getsockopt
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
/* Instrumented code */
result= getsockopt(mysql_socket.fd, level, optname, optval, optlen);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -944,15 +945,15 @@ inline_mysql_socket_setsockopt
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_OPT, (size_t)0, src_file, src_line);
/* Instrumented code */
result= setsockopt(mysql_socket.fd, level, optname, optval, optlen);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -982,15 +983,15 @@ inline_mysql_socket_listen
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
/* Instrumented code */
result= listen(mysql_socket.fd, backlog);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
@ -1021,15 +1022,15 @@ inline_mysql_socket_accept
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, socket_listen.m_psi,
PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, socket_listen.m_psi, PSI_SOCKET_CONNECT, (size_t)0, src_file, src_line);
/* Instrumented code */
socket_accept.fd= accept(socket_listen.fd, addr, &addr_length);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
}
else
#endif
@ -1039,14 +1040,12 @@ inline_mysql_socket_accept
}
#ifdef HAVE_PSI_SOCKET_INTERFACE
/* Initialize the instrument with the new socket descriptor and address */
socket_accept.m_psi=
PSI_CALL(init_socket)(key, (const my_socket*)&socket_accept.fd);
/* FIXME: simplify this with just 1 call to init_socket(). */
if (socket_accept.m_psi != NULL)
PSI_CALL(set_socket_info)(socket_accept.m_psi, &socket_accept.fd, addr,
addr_length);
if (likely(socket_accept.fd != INVALID_SOCKET))
{
/* Initialize the instrument with the new socket descriptor and address */
socket_accept.m_psi= PSI_SOCKET_CALL(init_socket)
(key, (const my_socket*)&socket_accept.fd, addr, addr_length);
}
#endif
return socket_accept;
@ -1070,18 +1069,18 @@ inline_mysql_socket_close
/* Instrumentation start */
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_CLOSE, (size_t)0, src_file, src_line);
/* Instrumented code */
result= closesocket(mysql_socket.fd);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
/* Remove the instrumentation for this socket. */
if (mysql_socket.m_psi != NULL)
PSI_CALL(destroy_socket)(mysql_socket.m_psi);
PSI_SOCKET_CALL(destroy_socket)(mysql_socket.m_psi);
return result;
}
@ -1105,28 +1104,53 @@ inline_mysql_socket_shutdown
{
int result;
/* Instrumentation start */
#ifdef __WIN__
static LPFN_DISCONNECTEX DisconnectEx = NULL;
if (DisconnectEx == NULL)
{
DWORD dwBytesReturned;
GUID guidDisconnectEx = WSAID_DISCONNECTEX;
WSAIoctl(mysql_socket.fd, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidDisconnectEx, sizeof(GUID),
&DisconnectEx, sizeof(DisconnectEx),
&dwBytesReturned, NULL, NULL);
}
#endif
/* Instrumentation start */
#ifdef HAVE_PSI_SOCKET_INTERFACE
if (mysql_socket.m_psi != NULL)
{
PSI_socket_locker *locker;
PSI_socket_locker_state state;
locker= PSI_CALL(start_socket_wait)(&state, mysql_socket.m_psi,
PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line);
locker= PSI_SOCKET_CALL(start_socket_wait)
(&state, mysql_socket.m_psi, PSI_SOCKET_SHUTDOWN, (size_t)0, src_file, src_line);
/* Instrumented code */
result= shutdown(mysql_socket.fd, how);
#ifdef __WIN__
if (DisconnectEx)
result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
(DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
else
#endif
result= shutdown(mysql_socket.fd, how);
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_socket_wait)(locker, (size_t)0);
PSI_SOCKET_CALL(end_socket_wait)(locker, (size_t)0);
return result;
}
#endif
/* Non instrumented code */
result= shutdown(mysql_socket.fd, how);
#ifdef __WIN__
if (DisconnectEx)
result= (DisconnectEx(mysql_socket.fd, (LPOVERLAPPED) NULL,
(DWORD) 0, (DWORD) 0) == TRUE) ? 0 : -1;
else
#endif
result= shutdown(mysql_socket.fd, how);
return result;
}

View File

@ -53,7 +53,7 @@
static inline void inline_mysql_stage_register(
const char *category, PSI_stage_info **info, int count)
{
PSI_CALL(register_stage)(category, info, count);
PSI_STAGE_CALL(register_stage)(category, info, count);
}
#endif
@ -62,7 +62,7 @@ static inline void
inline_mysql_set_stage(PSI_stage_key key,
const char *src_file, int src_line)
{
PSI_CALL(start_stage)(key, src_file, src_line);
PSI_STAGE_CALL(start_stage)(key, src_file, src_line);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
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
@ -63,10 +63,10 @@
#endif
#ifdef HAVE_PSI_STATEMENT_INTERFACE
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
inline_mysql_start_statement(STATE, K, DB, DB_LEN, __FILE__, __LINE__)
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS) \
inline_mysql_start_statement(STATE, K, DB, DB_LEN, CS, __FILE__, __LINE__)
#else
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \
#define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN, CS) \
NULL
#endif
@ -122,7 +122,7 @@
static inline void inline_mysql_statement_register(
const char *category, PSI_statement_info *info, int count)
{
PSI_CALL(register_statement)(category, info, count);
PSI_STATEMENT_CALL(register_statement)(category, info, count);
}
#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE
@ -132,7 +132,7 @@ inline_mysql_digest_start(PSI_statement_locker *locker)
PSI_digest_locker* digest_locker= NULL;
if (likely(locker != NULL))
digest_locker= PSI_CALL(digest_start)(locker);
digest_locker= PSI_STATEMENT_CALL(digest_start)(locker);
return digest_locker;
}
#endif
@ -143,7 +143,7 @@ inline_mysql_add_token(PSI_digest_locker *locker, uint token,
void *yylval)
{
if (likely(locker != NULL))
locker= PSI_CALL(digest_add_token)(locker, token,
locker= PSI_STATEMENT_CALL(digest_add_token)(locker, token,
(OPAQUE_LEX_YYSTYPE*)yylval);
return locker;
}
@ -153,12 +153,13 @@ static inline struct PSI_statement_locker *
inline_mysql_start_statement(PSI_statement_locker_state *state,
PSI_statement_key key,
const char *db, uint db_len,
const CHARSET_INFO *charset,
const char *src_file, int src_line)
{
PSI_statement_locker *locker;
locker= PSI_CALL(get_thread_statement_locker)(state, key);
locker= PSI_STATEMENT_CALL(get_thread_statement_locker)(state, key, charset);
if (likely(locker != NULL))
PSI_CALL(start_statement)(locker, db, db_len, src_file, src_line);
PSI_STATEMENT_CALL(start_statement)(locker, db, db_len, src_file, src_line);
return locker;
}
@ -168,7 +169,7 @@ inline_mysql_refine_statement(PSI_statement_locker *locker,
{
if (likely(locker != NULL))
{
locker= PSI_CALL(refine_statement)(locker, key);
locker= PSI_STATEMENT_CALL(refine_statement)(locker, key);
}
return locker;
}
@ -179,7 +180,7 @@ inline_mysql_set_statement_text(PSI_statement_locker *locker,
{
if (likely(locker != NULL))
{
PSI_CALL(set_statement_text)(locker, text, text_len);
PSI_STATEMENT_CALL(set_statement_text)(locker, text, text_len);
}
}
@ -189,7 +190,7 @@ inline_mysql_set_statement_lock_time(PSI_statement_locker *locker,
{
if (likely(locker != NULL))
{
PSI_CALL(set_statement_lock_time)(locker, count);
PSI_STATEMENT_CALL(set_statement_lock_time)(locker, count);
}
}
@ -199,7 +200,7 @@ inline_mysql_set_statement_rows_sent(PSI_statement_locker *locker,
{
if (likely(locker != NULL))
{
PSI_CALL(set_statement_rows_sent)(locker, count);
PSI_STATEMENT_CALL(set_statement_rows_sent)(locker, count);
}
}
@ -209,7 +210,7 @@ inline_mysql_set_statement_rows_examined(PSI_statement_locker *locker,
{
if (likely(locker != NULL))
{
PSI_CALL(set_statement_rows_examined)(locker, count);
PSI_STATEMENT_CALL(set_statement_rows_examined)(locker, count);
}
}
@ -217,9 +218,9 @@ static inline void
inline_mysql_end_statement(struct PSI_statement_locker *locker,
Diagnostics_area *stmt_da)
{
PSI_CALL(end_stage)();
PSI_STAGE_CALL(end_stage)();
if (likely(locker != NULL))
PSI_CALL(end_statement)(locker, stmt_da);
PSI_STATEMENT_CALL(end_statement)(locker, stmt_da);
}
#endif

View File

@ -30,18 +30,20 @@
*/
#ifdef HAVE_PSI_TABLE_INTERFACE
#define PSI_CALL_unbind_table PSI_CALL(unbind_table)
#define PSI_CALL_rebind_table PSI_CALL(rebind_table)
#define PSI_CALL_open_table PSI_CALL(open_table)
#define PSI_CALL_close_table PSI_CALL(close_table)
#define PSI_CALL_get_table_share PSI_CALL(get_table_share)
#define PSI_CALL_drop_table_share PSI_CALL(drop_table_share)
#define PSI_CALL_unbind_table PSI_TABLE_CALL(unbind_table)
#define PSI_CALL_rebind_table PSI_TABLE_CALL(rebind_table)
#define PSI_CALL_open_table PSI_TABLE_CALL(open_table)
#define PSI_CALL_close_table PSI_TABLE_CALL(close_table)
#define PSI_CALL_get_table_share PSI_TABLE_CALL(get_table_share)
#define PSI_CALL_release_table_share PSI_TABLE_CALL(release_table_share)
#define PSI_CALL_drop_table_share PSI_TABLE_CALL(drop_table_share)
#else
#define PSI_CALL_unbind_table(A1) /* no-op */
#define PSI_CALL_rebind_table(A1,A2,A3) NULL
#define PSI_CALL_close_table(A1) /* no-op */
#define PSI_CALL_open_table(A1,A2) NULL
#define PSI_CALL_get_table_share(A1,A2) NULL
#define PSI_CALL_release_table_share(A1) /* no-op */
#define PSI_CALL_drop_table_share(A1,A2,A3,A4,A5) /* no-op */
#endif
@ -76,22 +78,22 @@
@sa MYSQL_END_TABLE_WAIT.
*/
#ifdef HAVE_PSI_TABLE_INTERFACE
#define MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD) \
{ \
if (PSI != NULL) \
{ \
PSI_table_locker *locker; \
PSI_table_locker_state state; \
locker= PSI_CALL(start_table_io_wait)(& state, PSI, OP, INDEX, \
__FILE__, __LINE__); \
PAYLOAD \
if (locker != NULL) \
PSI_CALL(end_table_io_wait)(locker); \
} \
else \
{ \
PAYLOAD \
} \
#define MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD) \
{ \
if (PSI != NULL) \
{ \
PSI_table_locker *locker; \
PSI_table_locker_state state; \
locker= PSI_TABLE_CALL(start_table_io_wait) \
(& state, PSI, OP, INDEX, __FILE__, __LINE__); \
PAYLOAD \
if (locker != NULL) \
PSI_TABLE_CALL(end_table_io_wait)(locker); \
} \
else \
{ \
PAYLOAD \
} \
}
#else
#define MYSQL_TABLE_IO_WAIT(PSI, OP, INDEX, FLAGS, PAYLOAD) \
@ -109,22 +111,22 @@
@sa MYSQL_END_TABLE_WAIT.
*/
#ifdef HAVE_PSI_TABLE_INTERFACE
#define MYSQL_TABLE_LOCK_WAIT(PSI, OP, FLAGS, PAYLOAD) \
{ \
if (PSI != NULL) \
{ \
PSI_table_locker *locker; \
PSI_table_locker_state state; \
locker= PSI_CALL(start_table_lock_wait)(& state, PSI, OP, FLAGS, \
__FILE__, __LINE__); \
PAYLOAD \
if (locker != NULL) \
PSI_CALL(end_table_lock_wait)(locker); \
} \
else \
{ \
PAYLOAD \
} \
#define MYSQL_TABLE_LOCK_WAIT(PSI, OP, FLAGS, PAYLOAD) \
{ \
if (PSI != NULL) \
{ \
PSI_table_locker *locker; \
PSI_table_locker_state state; \
locker= PSI_TABLE_CALL(start_table_lock_wait) \
(& state, PSI, OP, FLAGS, __FILE__, __LINE__); \
PAYLOAD \
if (locker != NULL) \
PSI_TABLE_CALL(end_table_lock_wait)(locker); \
} \
else \
{ \
PAYLOAD \
} \
}
#else
#define MYSQL_TABLE_LOCK_WAIT(PSI, OP, FLAGS, PAYLOAD) \
@ -180,7 +182,8 @@ inline_mysql_start_table_lock_wait(PSI_table_locker_state *state,
if (psi != NULL)
{
struct PSI_table_locker *locker;
locker= PSI_CALL(start_table_lock_wait)(state, psi, op, flags, src_file, src_line);
locker= PSI_TABLE_CALL(start_table_lock_wait)
(state, psi, op, flags, src_file, src_line);
return locker;
}
return NULL;
@ -194,7 +197,7 @@ static inline void
inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker)
{
if (locker != NULL)
PSI_CALL(end_table_lock_wait)(locker);
PSI_TABLE_CALL(end_table_lock_wait)(locker);
}
#endif

View File

@ -597,7 +597,7 @@ static inline void inline_mysql_mutex_register(
)
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
PSI_CALL(register_mutex)(category, info, count);
PSI_MUTEX_CALL(register_mutex)(category, info, count);
#endif
}
@ -613,7 +613,7 @@ static inline int inline_mysql_mutex_init(
)
{
#ifdef HAVE_PSI_MUTEX_INTERFACE
that->m_psi= PSI_CALL(init_mutex)(key, &that->m_mutex);
that->m_psi= PSI_MUTEX_CALL(init_mutex)(key, &that->m_mutex);
#else
that->m_psi= NULL;
#endif
@ -636,7 +636,7 @@ static inline int inline_mysql_mutex_destroy(
#ifdef HAVE_PSI_MUTEX_INTERFACE
if (that->m_psi != NULL)
{
PSI_CALL(destroy_mutex)(that->m_psi);
PSI_MUTEX_CALL(destroy_mutex)(that->m_psi);
that->m_psi= NULL;
}
#endif
@ -664,7 +664,7 @@ static inline int inline_mysql_mutex_lock(
/* Instrumentation start */
PSI_mutex_locker *locker;
PSI_mutex_locker_state state;
locker= PSI_CALL(start_mutex_wait)(&state, that->m_psi,
locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi,
PSI_MUTEX_LOCK, src_file, src_line);
/* Instrumented code */
@ -678,7 +678,7 @@ static inline int inline_mysql_mutex_lock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_mutex_wait)(locker, result);
PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
return result;
}
@ -711,7 +711,7 @@ static inline int inline_mysql_mutex_trylock(
/* Instrumentation start */
PSI_mutex_locker *locker;
PSI_mutex_locker_state state;
locker= PSI_CALL(start_mutex_wait)(&state, that->m_psi,
locker= PSI_MUTEX_CALL(start_mutex_wait)(&state, that->m_psi,
PSI_MUTEX_TRYLOCK, src_file, src_line);
/* Instrumented code */
@ -725,7 +725,7 @@ static inline int inline_mysql_mutex_trylock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_mutex_wait)(locker, result);
PSI_MUTEX_CALL(end_mutex_wait)(locker, result);
return result;
}
@ -754,7 +754,7 @@ static inline int inline_mysql_mutex_unlock(
#ifdef HAVE_PSI_MUTEX_INTERFACE
if (that->m_psi != NULL)
PSI_CALL(unlock_mutex)(that->m_psi);
PSI_MUTEX_CALL(unlock_mutex)(that->m_psi);
#endif
#ifdef SAFE_MUTEX
@ -781,7 +781,7 @@ static inline void inline_mysql_rwlock_register(
)
{
#ifdef HAVE_PSI_RWLOCK_INTERFACE
PSI_CALL(register_rwlock)(category, info, count);
PSI_RWLOCK_CALL(register_rwlock)(category, info, count);
#endif
}
@ -792,7 +792,7 @@ static inline int inline_mysql_rwlock_init(
mysql_rwlock_t *that)
{
#ifdef HAVE_PSI_RWLOCK_INTERFACE
that->m_psi= PSI_CALL(init_rwlock)(key, &that->m_rwlock);
that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_rwlock);
#else
that->m_psi= NULL;
#endif
@ -810,7 +810,7 @@ static inline int inline_mysql_prlock_init(
mysql_prlock_t *that)
{
#ifdef HAVE_PSI_RWLOCK_INTERFACE
that->m_psi= PSI_CALL(init_rwlock)(key, &that->m_prlock);
that->m_psi= PSI_RWLOCK_CALL(init_rwlock)(key, &that->m_prlock);
#else
that->m_psi= NULL;
#endif
@ -824,7 +824,7 @@ static inline int inline_mysql_rwlock_destroy(
#ifdef HAVE_PSI_RWLOCK_INTERFACE
if (that->m_psi != NULL)
{
PSI_CALL(destroy_rwlock)(that->m_psi);
PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi);
that->m_psi= NULL;
}
#endif
@ -838,7 +838,7 @@ static inline int inline_mysql_prlock_destroy(
#ifdef HAVE_PSI_RWLOCK_INTERFACE
if (that->m_psi != NULL)
{
PSI_CALL(destroy_rwlock)(that->m_psi);
PSI_RWLOCK_CALL(destroy_rwlock)(that->m_psi);
that->m_psi= NULL;
}
#endif
@ -861,7 +861,7 @@ static inline int inline_mysql_rwlock_rdlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_rdwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
PSI_RWLOCK_READLOCK, src_file, src_line);
/* Instrumented code */
@ -869,7 +869,7 @@ static inline int inline_mysql_rwlock_rdlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_rdwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
return result;
}
@ -897,7 +897,7 @@ static inline int inline_mysql_prlock_rdlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_rdwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
PSI_RWLOCK_READLOCK, src_file, src_line);
/* Instrumented code */
@ -905,7 +905,7 @@ static inline int inline_mysql_prlock_rdlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_rdwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
return result;
}
@ -933,7 +933,7 @@ static inline int inline_mysql_rwlock_wrlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_wrwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
PSI_RWLOCK_WRITELOCK, src_file, src_line);
/* Instrumented code */
@ -941,7 +941,7 @@ static inline int inline_mysql_rwlock_wrlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_wrwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
return result;
}
@ -969,7 +969,7 @@ static inline int inline_mysql_prlock_wrlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_wrwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
PSI_RWLOCK_WRITELOCK, src_file, src_line);
/* Instrumented code */
@ -977,7 +977,7 @@ static inline int inline_mysql_prlock_wrlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_wrwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
return result;
}
@ -1005,7 +1005,7 @@ static inline int inline_mysql_rwlock_tryrdlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_rdwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_rdwait)(&state, that->m_psi,
PSI_RWLOCK_TRYREADLOCK, src_file, src_line);
/* Instrumented code */
@ -1013,7 +1013,7 @@ static inline int inline_mysql_rwlock_tryrdlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_rdwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_rdwait)(locker, result);
return result;
}
@ -1040,7 +1040,7 @@ static inline int inline_mysql_rwlock_trywrlock(
/* Instrumentation start */
PSI_rwlock_locker *locker;
PSI_rwlock_locker_state state;
locker= PSI_CALL(start_rwlock_wrwait)(&state, that->m_psi,
locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)(&state, that->m_psi,
PSI_RWLOCK_TRYWRITELOCK, src_file, src_line);
/* Instrumented code */
@ -1048,7 +1048,7 @@ static inline int inline_mysql_rwlock_trywrlock(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_rwlock_wrwait)(locker, result);
PSI_RWLOCK_CALL(end_rwlock_wrwait)(locker, result);
return result;
}
@ -1066,7 +1066,7 @@ static inline int inline_mysql_rwlock_unlock(
int result;
#ifdef HAVE_PSI_RWLOCK_INTERFACE
if (that->m_psi != NULL)
PSI_CALL(unlock_rwlock)(that->m_psi);
PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi);
#endif
result= rw_unlock(&that->m_rwlock);
return result;
@ -1079,7 +1079,7 @@ static inline int inline_mysql_prlock_unlock(
int result;
#ifdef HAVE_PSI_RWLOCK_INTERFACE
if (that->m_psi != NULL)
PSI_CALL(unlock_rwlock)(that->m_psi);
PSI_RWLOCK_CALL(unlock_rwlock)(that->m_psi);
#endif
result= rw_pr_unlock(&that->m_prlock);
return result;
@ -1099,7 +1099,7 @@ static inline void inline_mysql_cond_register(
)
{
#ifdef HAVE_PSI_COND_INTERFACE
PSI_CALL(register_cond)(category, info, count);
PSI_COND_CALL(register_cond)(category, info, count);
#endif
}
@ -1111,7 +1111,7 @@ static inline int inline_mysql_cond_init(
const pthread_condattr_t *attr)
{
#ifdef HAVE_PSI_COND_INTERFACE
that->m_psi= PSI_CALL(init_cond)(key, &that->m_cond);
that->m_psi= PSI_COND_CALL(init_cond)(key, &that->m_cond);
#else
that->m_psi= NULL;
#endif
@ -1124,7 +1124,7 @@ static inline int inline_mysql_cond_destroy(
#ifdef HAVE_PSI_COND_INTERFACE
if (that->m_psi != NULL)
{
PSI_CALL(destroy_cond)(that->m_psi);
PSI_COND_CALL(destroy_cond)(that->m_psi);
that->m_psi= NULL;
}
#endif
@ -1147,7 +1147,7 @@ static inline int inline_mysql_cond_wait(
/* Instrumentation start */
PSI_cond_locker *locker;
PSI_cond_locker_state state;
locker= PSI_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
PSI_COND_WAIT, src_file, src_line);
/* Instrumented code */
@ -1155,7 +1155,7 @@ static inline int inline_mysql_cond_wait(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_cond_wait)(locker, result);
PSI_COND_CALL(end_cond_wait)(locker, result);
return result;
}
@ -1184,7 +1184,7 @@ static inline int inline_mysql_cond_timedwait(
/* Instrumentation start */
PSI_cond_locker *locker;
PSI_cond_locker_state state;
locker= PSI_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
locker= PSI_COND_CALL(start_cond_wait)(&state, that->m_psi, mutex->m_psi,
PSI_COND_TIMEDWAIT, src_file, src_line);
/* Instrumented code */
@ -1192,7 +1192,7 @@ static inline int inline_mysql_cond_timedwait(
/* Instrumentation end */
if (locker != NULL)
PSI_CALL(end_cond_wait)(locker, result);
PSI_COND_CALL(end_cond_wait)(locker, result);
return result;
}
@ -1210,7 +1210,7 @@ static inline int inline_mysql_cond_signal(
int result;
#ifdef HAVE_PSI_COND_INTERFACE
if (that->m_psi != NULL)
PSI_CALL(signal_cond)(that->m_psi);
PSI_COND_CALL(signal_cond)(that->m_psi);
#endif
result= pthread_cond_signal(&that->m_cond);
return result;
@ -1222,7 +1222,7 @@ static inline int inline_mysql_cond_broadcast(
int result;
#ifdef HAVE_PSI_COND_INTERFACE
if (that->m_psi != NULL)
PSI_CALL(broadcast_cond)(that->m_psi);
PSI_COND_CALL(broadcast_cond)(that->m_psi);
#endif
result= pthread_cond_broadcast(&that->m_cond);
return result;
@ -1241,7 +1241,7 @@ static inline void inline_mysql_thread_register(
)
{
#ifdef HAVE_PSI_THREAD_INTERFACE
PSI_CALL(register_thread)(category, info, count);
PSI_THREAD_CALL(register_thread)(category, info, count);
#endif
}
@ -1252,14 +1252,14 @@ static inline int inline_mysql_thread_create(
void *(*start_routine)(void*), void *arg)
{
int result;
result= PSI_CALL(spawn_thread)(key, thread, attr, start_routine, arg);
result= PSI_THREAD_CALL(spawn_thread)(key, thread, attr, start_routine, arg);
return result;
}
static inline void inline_mysql_thread_set_psi_id(ulong id)
{
struct PSI_thread *psi= PSI_CALL(get_thread)();
PSI_CALL(set_thread_id)(psi, id);
struct PSI_thread *psi= PSI_THREAD_CALL(get_thread)();
PSI_THREAD_CALL(set_thread_id)(psi, id);
}
#endif

View File

@ -899,6 +899,10 @@ struct PSI_file_locker_state_v1
enum PSI_file_operation m_operation;
/** Current file. */
struct PSI_file *m_file;
/** Current file name. */
const char *m_name;
/** Current file class. */
void *m_class;
/** Current thread. */
struct PSI_thread *m_thread;
/** Operation number of bytes. */
@ -958,6 +962,8 @@ struct PSI_digest_storage
{
my_bool m_full;
int m_byte_count;
/** Character set number. */
uint m_charset_number;
unsigned char m_token_array[PSI_MAX_DIGEST_STORAGE_SIZE];
};
typedef struct PSI_digest_storage PSI_digest_storage;
@ -969,6 +975,9 @@ struct PSI_digest_locker_state
};
typedef struct PSI_digest_locker_state PSI_digest_locker_state;
/* Duplicate of NAME_LEN, to avoid dependency on mysql_com.h */
#define PSI_SCHEMA_NAME_LEN (64 * 3)
/**
State data storage for @c get_thread_statement_locker_v1_t,
@c get_thread_statement_locker_v1_t.
@ -1029,6 +1038,10 @@ struct PSI_statement_locker_state_v1
ulong m_sort_scan;
/** Statement digest. */
PSI_digest_locker_state m_digest_state;
/** Current schema name. */
char m_schema_name[PSI_SCHEMA_NAME_LEN];
/** Length in bytes of @c m_schema_name. */
uint m_schema_name_length;
};
/**
@ -1187,10 +1200,13 @@ typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond);
Socket instrumentation initialisation API.
@param key the registered mutex key
@param socket descriptor
@param addr the socket ip address
@param addr_len length of socket ip address
@return an instrumented socket
*/
typedef struct PSI_socket* (*init_socket_v1_t)
(PSI_socket_key key, const my_socket *fd);
(PSI_socket_key key, const my_socket *fd,
const struct sockaddr *addr, socklen_t addr_len);
/**
socket instrumentation destruction API.
@ -1290,7 +1306,7 @@ typedef int (*spawn_thread_v1_t)(PSI_thread_key key,
@return an instrumented thread
*/
typedef struct PSI_thread* (*new_thread_v1_t)
(PSI_thread_key key, const void *identity, ulong thread_id);
(PSI_thread_key key, const void *identity, ulonglong thread_id);
/**
Assign an id to an instrumented thread.
@ -1298,7 +1314,7 @@ typedef struct PSI_thread* (*new_thread_v1_t)
@param id the id to assign
*/
typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread,
unsigned long id);
ulonglong id);
/**
Get the instrumentation for the running thread.
@ -1570,16 +1586,18 @@ typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker);
@param op the operation to perform
@param src_file the source file name
@param src_line the source line number
@return an instrumented file handle
*/
typedef struct PSI_file* (*start_file_open_wait_v1_t)
typedef void (*start_file_open_wait_v1_t)
(struct PSI_file_locker *locker, const char *src_file, uint src_line);
/**
End a file instrumentation open operation, for file streams.
@param locker the file locker.
@param result the opened file (NULL indicates failure, non NULL success).
@return an instrumented file handle
*/
typedef void (*end_file_open_wait_v1_t)(struct PSI_file_locker *locker);
typedef struct PSI_file* (*end_file_open_wait_v1_t)
(struct PSI_file_locker *locker, void *result);
/**
End a file instrumentation open operation, for non stream files.
@ -1616,6 +1634,25 @@ typedef void (*start_file_wait_v1_t)
typedef void (*end_file_wait_v1_t)
(struct PSI_file_locker *locker, size_t count);
/**
Start a file instrumentation close operation.
@param locker the file locker
@param op the operation to perform
@param src_file the source file name
@param src_line the source line number
*/
typedef void (*start_file_close_wait_v1_t)
(struct PSI_file_locker *locker, const char *src_file, uint src_line);
/**
End a file instrumentation close operation.
@param locker the file locker.
@param rc the close operation return code (0 for success).
@return an instrumented file handle
*/
typedef void (*end_file_close_wait_v1_t)
(struct PSI_file_locker *locker, int rc);
/**
Start a new stage, and implicitly end the previous stage.
@param key the key of the new stage
@ -1632,11 +1669,12 @@ typedef void (*end_stage_v1_t) (void);
Get a statement instrumentation locker.
@param state data storage for the locker
@param key the statement instrumentation key
@param charset client character set
@return a statement locker, or NULL
*/
typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t)
(struct PSI_statement_locker_state_v1 *state,
PSI_statement_key key);
PSI_statement_key key, const void *charset);
/**
Refine a statement locker to a more specific key.
@ -1870,6 +1908,19 @@ typedef struct PSI_digest_locker * (*digest_start_v1_t)
typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
(struct PSI_digest_locker *locker, uint token, struct OPAQUE_LEX_YYSTYPE *yylval);
/**
Stores an array of connection attributes
@param buffer char array of length encoded connection attributes
in network format
@param length legnth of the data in buffer
@param from_cs charset in which @buffer is encodded
@return state
@retval non-0 attributes truncated
@retval 0 stored the attribute
*/
typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length,
const void *from_cs);
/**
Performance Schema Interface, version 1.
@since PSI_VERSION_1
@ -2005,6 +2056,10 @@ struct PSI_v1
start_file_wait_v1_t start_file_wait;
/** @sa end_file_wait_v1_t. */
end_file_wait_v1_t end_file_wait;
/** @sa start_file_close_wait_v1_t. */
start_file_close_wait_v1_t start_file_close_wait;
/** @sa end_file_close_wait_v1_t. */
end_file_close_wait_v1_t end_file_close_wait;
/** @sa start_stage_v1_t. */
start_stage_v1_t start_stage;
/** @sa end_stage_v1_t. */
@ -2065,6 +2120,8 @@ struct PSI_v1
digest_start_v1_t digest_start;
/** @sa digest_add_token_v1_t. */
digest_add_token_v1_t digest_add_token;
/** @sa set_thread_connect_attrs_v1_t. */
set_thread_connect_attrs_v1_t set_thread_connect_attrs;
};
/** @} (end of group Group_PSI_v1) */
@ -2318,7 +2375,54 @@ typedef struct PSI_stage_info_none PSI_stage_info;
extern MYSQL_PLUGIN_IMPORT PSI *PSI_server;
#define PSI_CALL(M) PSI_server->M
/*
Allow to override PSI_XXX_CALL at compile time
with more efficient implementations, if available.
If nothing better is available,
make a dynamic call using the PSI_server function pointer.
*/
#ifndef PSI_MUTEX_CALL
#define PSI_MUTEX_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_RWLOCK_CALL
#define PSI_RWLOCK_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_COND_CALL
#define PSI_COND_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_THREAD_CALL
#define PSI_THREAD_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_FILE_CALL
#define PSI_FILE_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_SOCKET_CALL
#define PSI_SOCKET_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_STAGE_CALL
#define PSI_STAGE_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_STATEMENT_CALL
#define PSI_STATEMENT_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_TABLE_CALL
#define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#ifndef PSI_IDLE_CALL
#define PSI_IDLE_CALL(M) PSI_DYNAMIC_CALL(M)
#endif
#define PSI_DYNAMIC_CALL(M) PSI_server->M
/** @} */

View File

@ -221,6 +221,8 @@ struct PSI_file_locker_state_v1
uint m_flags;
enum PSI_file_operation m_operation;
struct PSI_file *m_file;
const char *m_name;
void *m_class;
struct PSI_thread *m_thread;
size_t m_number_of_bytes;
ulonglong m_timer_start;
@ -243,6 +245,7 @@ struct PSI_digest_storage
{
my_bool m_full;
int m_byte_count;
uint m_charset_number;
unsigned char m_token_array[1024];
};
typedef struct PSI_digest_storage PSI_digest_storage;
@ -278,6 +281,8 @@ struct PSI_statement_locker_state_v1
ulong m_sort_rows;
ulong m_sort_scan;
PSI_digest_locker_state m_digest_state;
char m_schema_name[(64 * 3)];
uint m_schema_name_length;
};
struct PSI_socket_locker_state_v1
{
@ -318,7 +323,8 @@ typedef struct PSI_cond* (*init_cond_v1_t)
(PSI_cond_key key, const void *identity);
typedef void (*destroy_cond_v1_t)(struct PSI_cond *cond);
typedef struct PSI_socket* (*init_socket_v1_t)
(PSI_socket_key key, const my_socket *fd);
(PSI_socket_key key, const my_socket *fd,
const struct sockaddr *addr, socklen_t addr_len);
typedef void (*destroy_socket_v1_t)(struct PSI_socket *socket);
typedef struct PSI_table_share* (*get_table_share_v1_t)
(my_bool temporary, struct TABLE_SHARE *share);
@ -340,9 +346,9 @@ typedef int (*spawn_thread_v1_t)(PSI_thread_key key,
const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
typedef struct PSI_thread* (*new_thread_v1_t)
(PSI_thread_key key, const void *identity, ulong thread_id);
(PSI_thread_key key, const void *identity, ulonglong thread_id);
typedef void (*set_thread_id_v1_t)(struct PSI_thread *thread,
unsigned long id);
ulonglong id);
typedef struct PSI_thread* (*get_thread_v1_t)(void);
typedef void (*set_thread_user_v1_t)(const char *user, int user_len);
typedef void (*set_thread_user_host_v1_t)(const char *user, int user_len,
@ -420,9 +426,10 @@ typedef struct PSI_table_locker* (*start_table_lock_wait_v1_t)
ulong flags,
const char *src_file, uint src_line);
typedef void (*end_table_lock_wait_v1_t)(struct PSI_table_locker *locker);
typedef struct PSI_file* (*start_file_open_wait_v1_t)
typedef void (*start_file_open_wait_v1_t)
(struct PSI_file_locker *locker, const char *src_file, uint src_line);
typedef void (*end_file_open_wait_v1_t)(struct PSI_file_locker *locker);
typedef struct PSI_file* (*end_file_open_wait_v1_t)
(struct PSI_file_locker *locker, void *result);
typedef void (*end_file_open_wait_and_bind_to_descriptor_v1_t)
(struct PSI_file_locker *locker, File file);
typedef void (*start_file_wait_v1_t)
@ -430,12 +437,16 @@ typedef void (*start_file_wait_v1_t)
const char *src_file, uint src_line);
typedef void (*end_file_wait_v1_t)
(struct PSI_file_locker *locker, size_t count);
typedef void (*start_file_close_wait_v1_t)
(struct PSI_file_locker *locker, const char *src_file, uint src_line);
typedef void (*end_file_close_wait_v1_t)
(struct PSI_file_locker *locker, int rc);
typedef void (*start_stage_v1_t)
(PSI_stage_key key, const char *src_file, int src_line);
typedef void (*end_stage_v1_t) (void);
typedef struct PSI_statement_locker* (*get_thread_statement_locker_v1_t)
(struct PSI_statement_locker_state_v1 *state,
PSI_statement_key key);
PSI_statement_key key, const void *charset);
typedef struct PSI_statement_locker* (*refine_statement_v1_t)
(struct PSI_statement_locker *locker,
PSI_statement_key key);
@ -499,6 +510,8 @@ typedef struct PSI_digest_locker * (*digest_start_v1_t)
(struct PSI_statement_locker *locker);
typedef struct PSI_digest_locker* (*digest_add_token_v1_t)
(struct PSI_digest_locker *locker, uint token, struct OPAQUE_LEX_YYSTYPE *yylval);
typedef int (*set_thread_connect_attrs_v1_t)(const char *buffer, uint length,
const void *from_cs);
struct PSI_v1
{
register_mutex_v1_t register_mutex;
@ -566,6 +579,8 @@ struct PSI_v1
end_file_open_wait_and_bind_to_descriptor;
start_file_wait_v1_t start_file_wait;
end_file_wait_v1_t end_file_wait;
start_file_close_wait_v1_t start_file_close_wait;
end_file_close_wait_v1_t end_file_close_wait;
start_stage_v1_t start_stage;
end_stage_v1_t end_stage;
get_thread_statement_locker_v1_t get_thread_statement_locker;
@ -596,6 +611,7 @@ struct PSI_v1
set_socket_thread_owner_v1_t set_socket_thread_owner;
digest_start_v1_t digest_start;
digest_add_token_v1_t digest_add_token;
set_thread_connect_attrs_v1_t set_thread_connect_attrs;
};
typedef struct PSI_v1 PSI;
typedef struct PSI_mutex_info_v1 PSI_mutex_info;

View File

@ -339,9 +339,16 @@ extern void (*debug_sync_C_callback_ptr)(MYSQL_THD, const char *, size_t);
if (debug_sync_service) \
debug_sync_service(thd, STRING_WITH_LEN(name)); \
} while(0)
#define DEBUG_SYNC_C_IF_THD(thd, name) \
do { \
if (debug_sync_service && thd) \
debug_sync_service((MYSQL_THD) thd, STRING_WITH_LEN(name)); \
} while(0)
#else
#define DEBUG_SYNC(thd,name) do { } while(0)
#endif
#define DEBUG_SYNC(thd,name) do { } while(0)
#define DEBUG_SYNC_C_IF_THD(thd, _sync_point_name_) do { } while(0)
#endif /* defined(ENABLED_DEBUG_SYNC) */
/* compatibility macro */
#define DEBUG_SYNC_C(name) DEBUG_SYNC(NULL, name)

View File

@ -0,0 +1,64 @@
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
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; version 2 of the
License.
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 St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
This service provides functions to report error conditions and log to
mysql error log.
*/
#ifndef MYSQL_SERVICE_MY_PLUGIN_LOG_INCLUDED
#define MYSQL_SERVICE_MY_PLUGIN_LOG_INCLUDED
#ifndef MYSQL_ABI_CHECK
#include <stdarg.h>
#endif
/* keep in sync with the loglevel enum in my_sys.h */
enum plugin_log_level
{
MY_ERROR_LEVEL,
MY_WARNING_LEVEL,
MY_INFORMATION_LEVEL
};
#ifdef __cplusplus
extern "C" {
#endif
extern struct my_plugin_log_service
{
/** write a message to the log */
int (*my_plugin_log_message)(MYSQL_PLUGIN *, enum plugin_log_level, const char *, ...);
} *my_plugin_log_service;
#ifdef MYSQL_DYNAMIC_PLUGIN
#define my_plugin_log_message my_plugin_log_service->my_plugin_log_message
#else
int my_plugin_log_message(MYSQL_PLUGIN *plugin, enum plugin_log_level level,
const char *format, ...);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,57 @@
#ifndef MYSQL_SERVICE_SHA1_INCLUDED
/* Copyright (c) 2013, Monty Program Ab
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; version 2 of the License.
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 St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
my sha1 service
Functions to calculate SHA1 hash from a memory buffer
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MYSQL_ABI_CHECK
#include <stdlib.h>
#endif
#define MY_SHA1_HASH_SIZE 20 /* Hash size in bytes */
extern struct my_sha1_service_st {
void (*my_sha1_type)(unsigned char*, const char*, size_t);
void (*my_sha1_multi_type)(unsigned char*, ...);
} *my_sha1_service;
#ifdef MYSQL_DYNAMIC_PLUGIN
#define my_sha1(A,B,C) my_sha1_service->my_sha1_type(A,B,C)
#define my_sha1_multi my_sha1_service->my_sha1_multi_type
#else
void my_sha1(unsigned char*, const char*, size_t);
void my_sha1_multi(unsigned char*, ...);
#endif
#ifdef __cplusplus
}
#endif
#define MYSQL_SERVICE_SHA1_INCLUDED
#endif

View File

@ -26,6 +26,7 @@ extern "C" {
#include <mysql/service_debug_sync.h>
#include <mysql/service_kill_statement.h>
#include <mysql/service_thd_timezone.h>
#include <mysql/service_sha1.h>
#ifdef __cplusplus
}

View File

@ -68,6 +68,7 @@
#define TABLE_COMMENT_MAXLEN 2048
#define COLUMN_COMMENT_MAXLEN 1024
#define INDEX_COMMENT_MAXLEN 1024
#define TABLE_PARTITION_COMMENT_MAXLEN 1024
/*
USER_HOST_BUFF_SIZE -- length of string buffer, that is enough to contain
@ -142,13 +143,19 @@ enum enum_server_command
#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */
#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */
#define FIELD_IN_PART_FUNC_FLAG (1 << 19)/* Field part of partition func */
#define FIELD_IN_ADD_INDEX (1<< 20) /* Intern: Field used in ADD INDEX */
/**
Intern: Field in TABLE object for new version of altered table,
which participates in a newly added index.
*/
#define FIELD_IN_ADD_INDEX (1 << 20)
#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */
#define FIELD_FLAGS_STORAGE_MEDIA 22 /* Field storage media, bit 22-23,
reserved by MySQL Cluster */
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25,
reserved by MySQL Cluster */
#define HAS_EXPLICIT_VALUE (1 << 26) /* An INSERT/UPDATE operation supplied
#define FIELD_FLAGS_STORAGE_MEDIA 22 /* Field storage media, bit 22-23 */
#define FIELD_FLAGS_STORAGE_MEDIA_MASK (3 << FIELD_FLAGS_STORAGE_MEDIA)
#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */
#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT)
#define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */
#define HAS_EXPLICIT_VALUE (1 << 27) /* An INSERT/UPDATE operation supplied
an explicit default value */
#define REFRESH_GRANT (1ULL << 0) /* Refresh grant tables */
@ -177,11 +184,12 @@ enum enum_server_command
#define REFRESH_QUERY_CACHE_FREE (1ULL << 17) /* pack query cache */
#define REFRESH_DES_KEY_FILE (1ULL << 18)
#define REFRESH_USER_RESOURCES (1ULL << 19)
#define REFRESH_FOR_EXPORT (1ULL << 20) /* FLUSH TABLES ... FOR EXPORT */
#define REFRESH_TABLE_STATS (1ULL << 20) /* Refresh table stats hash table */
#define REFRESH_INDEX_STATS (1ULL << 21) /* Refresh index stats hash table */
#define REFRESH_USER_STATS (1ULL << 22) /* Refresh user stats hash table */
#define REFRESH_CLIENT_STATS (1ULL << 23) /* Refresh client stats hash table */
#define REFRESH_TABLE_STATS (1ULL << 27) /* Refresh table stats hash table */
#define REFRESH_INDEX_STATS (1ULL << 28) /* Refresh index stats hash table */
#define REFRESH_USER_STATS (1ULL << 29) /* Refresh user stats hash table */
#define REFRESH_CLIENT_STATS (1ULL << 30) /* Refresh client stats hash table */
#define REFRESH_FAST (1ULL << 31) /* Intern flag */
@ -206,8 +214,15 @@ enum enum_server_command
#define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */
#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */
#define CLIENT_PROGRESS (1UL << 29) /* Client support progress indicator */
#define CLIENT_PLUGIN_AUTH (1UL << 19) /* Client supports plugin authentication */
#define CLIENT_CONNECT_ATTRS (1UL << 20) /* Client supports connection attributes */
/* Enable authentication response packet to be larger than 255 bytes. */
#define CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA (1UL << 21)
/* Don't close the connection for a connection with expired password. */
#define CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS (1UL << 22)
#define CLIENT_PROGRESS (1UL << 29) /* Client support progress indicator */
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
/*
It used to be that if mysql_real_connect() failed, it would delete any
@ -251,6 +266,12 @@ enum enum_server_command
CLIENT_PROGRESS | \
CLIENT_PLUGIN_AUTH)
/*
To be added later:
CLIENT_CONNECT_ATTRS, CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA,
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS
*/
/*
Switch off the flags that are optional and depending on build flags
If any of the optional flags is supported by the build it will be switched

View File

@ -24,6 +24,8 @@ void my_make_scrambled_password_323(char *to, const char *password,
size_t pass_len);
void my_make_scrambled_password(char *to, const char *password,
size_t pass_len);
void my_make_scrambled_password_sha1(char *to, const char *password,
size_t pass_len);
void hash_password(ulong *result, const char *password, uint password_len);

View File

@ -20,10 +20,13 @@
#define SERVICE_VERSION void *
#endif
#define VERSION_debug_sync 0x1000
#define VERSION_kill_statement 0x1000
#define VERSION_my_snprintf 0x0100
#define VERSION_thd_alloc 0x0100
#define VERSION_thd_wait 0x0100
#define VERSION_progress_report 0x0100
#define VERSION_debug_sync 0x1000
#define VERSION_kill_statement 0x1000
#define VERSION_thd_timezone 0x0100
#define VERSION_my_sha1 0x0100

View File

@ -1,8 +1,7 @@
#ifndef SHA1_INCLUDED
#define SHA1_INCLUDED
/* Copyright (c) 2002, 2006 MySQL AB, 2009 Sun Microsystems, Inc.
Use is subject to license terms.
/* Copyright (c) 2013, Monty Program Ab
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
@ -18,88 +17,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
This is the header file for code which implements the Secure
Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
April 17, 1995.
Many of the variable names in this code, especially the
single character names, were used because those were the names
used in the publication.
Please read the file sha1.c for more information.
Modified 2002 by Peter Zaitsev to better follow MySQL standards
Original Source from: http://www.faqs.org/rfcs/rfc3174.html
Copyright (C) The Internet Society (2001). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Acknowledgement
Funding for the RFC Editor function is currently provided by the
Internet Society.
*/
enum sha_result_codes
{
SHA_SUCCESS = 0,
SHA_NULL, /* Null pointer parameter */
SHA_INPUT_TOO_LONG, /* input data too long */
SHA_STATE_ERROR /* called Input after Result */
};
#define SHA1_HASH_SIZE 20 /* Hash size in bytes */
/*
This structure will hold context information for the SHA-1
hashing operation
*/
typedef struct SHA1_CONTEXT
{
ulonglong Length; /* Message length in bits */
uint32 Intermediate_Hash[SHA1_HASH_SIZE/4]; /* Message Digest */
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the message digest corrupted? */
int16 Message_Block_Index; /* Index into message block array */
uint8 Message_Block[64]; /* 512-bit message blocks */
} SHA1_CONTEXT;
/*
Function Prototypes
*/
C_MODE_START
int mysql_sha1_reset(SHA1_CONTEXT*);
int mysql_sha1_input(SHA1_CONTEXT*, const uint8 *, unsigned int);
int mysql_sha1_result(SHA1_CONTEXT* , uint8 Message_Digest[SHA1_HASH_SIZE]);
C_MODE_END
#include <mysql/service_sha1.h>
#define SHA1_HASH_SIZE MY_SHA1_HASH_SIZE
#define compute_sha1_hash(A,B,C) my_sha1(A,B,C)
#define compute_sha1_hash_multi(A,B,C,D,E) my_sha1_multi(A,B,C,D,E,NULL)
#endif /* SHA__INCLUDED */

View File

@ -21,6 +21,7 @@ extern "C" {
#endif
#include <mysql.h>
#include <hash.h>
extern const char *unknown_sqlstate;
extern const char *cant_connect_sqlstate;
@ -34,6 +35,7 @@ struct st_mysql_options_extention {
char *default_auth;
char *ssl_crl; /* PEM CRL file */
char *ssl_crlpath; /* PEM directory of CRL-s? */
char *server_public_key_path;
void (*report_progress)(const MYSQL *mysql,
unsigned int stage,
unsigned int max_stage,

View File

@ -49,7 +49,6 @@ void thd_set_killed(THD *thd);
void thd_clear_errors(THD *thd);
void thd_set_thread_stack(THD *thd, char *stack_start);
void thd_lock_thread_count(THD *thd);
void thd_unlock_thread_count(THD *thd);
void thd_close_connection(THD *thd);
THD *thd_get_current_thd();
void thd_lock_data(THD *thd);

80
libevent/CMakeLists.txt Normal file
View File

@ -0,0 +1,80 @@
# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
#
# 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; version 2 of the License.
#
# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
# Common defines and includes
IF(WITH_INNODB_MEMCACHED AND UNIX)
ADD_DEFINITIONS(-DHAVE_CONFIG_H)
INCLUDE_DIRECTORIES(${LIBEVENT_INCLUDE_DIR}/compat/sys
${LIBEVENT_INCLUDE_DIR})
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_SHARED_LIBRARY_C_FLAGS} -I${LIBEVENT_INCLUDE_DIR}")
SET(LIBEVENT_CORE_SOURCES
event.h
event-internal.h
evutil.h
log.h
event.c
buffer.c
evbuffer.c
log.c
evutil.c)
SET(LIBEVENT_EXTRA_SOURCES
event_tagging.c
http.c
evhttp.h
http-internal.h
evdns.h
evrpc.c
evrpc.h
evrpc-internal.h
strlcpy.c
strlcpy-internal.h)
IF(HAVE_SIGNAL_H)
SET(LIBEVENT_SIGNAL_SOURCES signal.c)
ENDIF()
IF(HAVE_POLL_H)
SET(LIBEVENT_POLL_SOURCES poll.c)
ENDIF()
IF(HAVE_SELECT)
SET(LIBEVENT_SELECT_SOURCE select.c)
ENDIF()
IF(HAVE_SYS_EPOLL_H)
SET(LIBEVENT_EPOLL_SOURCES epoll.c epoll_sub.c)
ENDIF()
IF(HAVE_SYS_DEVPOLL_H)
SET(LIBEVENT_DEVPOLL_SOURCES devpoll.c)
ENDIF()
IF(HAVE_EVENT_PORTS)
SET(LIBEVENT_EVPORT_SOURCES evport.c)
ENDIF()
IF(HAVE_WORKING_KQUEUE)
SET(LIBEVENT_KQUEUE_SOURCES kqueue.c)
ENDIF()
ADD_LIBRARY(event_share SHARED ${LIBEVENT_CORE_SOURCES} ${LIBEVENT_EXTRA_SOURCES} ${LIBEVENT_SIGNAL_SOURCES} ${LIBEVENT_POLL_SOURCES} ${LIBEVENT_SELECT_SOURCE} ${LIBEVENT_EPOLL_SOURCES} ${LIBEVENT_DEVPOLL_SOURCES} ${LIBEVENT_EVPORT_SOURCES} ${LIBEVENT_KQUEUE_SOURCES})
ADD_LIBRARY(event STATIC ${LIBEVENT_CORE_SOURCES} ${LIBEVENT_EXTRA_SOURCES} ${LIBEVENT_SIGNAL_SOURCES} ${LIBEVENT_POLL_SOURCES} ${LIBEVENT_SELECT_SOURCE} ${LIBEVENT_EPOLL_SOURCES} ${LIBEVENT_DEVPOLL_SOURCES} ${LIBEVENT_EVPORT_SOURCES} ${LIBEVENT_KQUEUE_SOURCES})
ENDIF()

190
libevent/ChangeLog Normal file
View File

@ -0,0 +1,190 @@
Changes in 1.4.12-stable:
o Try to contain degree of failure when running on a win32 version so heavily firewalled that we can't fake a socketpair.
o Fix an obscure timing-dependent, allocator-dependent crash in the evdns code.
o Use __VA_ARGS__ syntax for varargs macros in event_rpcgen when compiler is not GCC.
o Activate fd events in a pseudorandom order with O(N) backends, so that we don't systematically favor low fds (select) or earlier-added fds (poll, win32).
o Fix another pair of fencepost bugs in epoll.c. [Patch from Adam Langley.]
o Do not break evdns connections to nameservers when our IP changes.
o Set truncated flag correctly in evdns server replies.
o Disable strict aliasing with GCC: our code is not compliant with it.
Changes in 1.4.11-stable:
o Fix a bug when removing a timeout from the heap. [Patch from Marko Kreen]
o Remove the limit on size of HTTP headers by removing static buffers.
o Fix a nasty dangling pointer bug in epoll.c that could occur after epoll_recalc(). [Patch from Kevin Springborn]
o Distribute Win32-Code/event-config.h, not ./event-config.h
Changes in 1.4.10-stable:
o clean up buffered http connection data on reset; reported by Brian O'Kelley
o bug fix and potential race condition in signal handling; from Alexander Drozdov
o rename the Solaris event ports backend to evport
o support compilation on Haiku
o fix signal processing when a signal callback delivers a signal; from Alexander Drozdov
o const-ify some arguments to evdns functions.
o off-by-one error in epoll_recalc; reported by Victor Goya
o include Doxyfile in tar ball; from Jeff Garzik
o correctly parse queries with encoded \r, \n or + characters
Changes in 1.4.9-stable:
o event_add would not return error for some backends; from Dean McNamee
o Clear the timer cache on entering the event loop; reported by Victor Chang
o Only bind the socket on connect when a local address has been provided; reported by Alejo Sanchez
o Allow setting of local port for evhttp connections to support millions of connections from a single system; from Richard Jones.
o Clear the timer cache when leaving the event loop; reported by Robin Haberkorn
o Fix a typo in setting the global event base; reported by lance.
o Fix a memory leak when reading multi-line headers
o Fix a memory leak by not running explicit close detection for server connections
Changes in 1.4.8-stable:
o Match the query in DNS replies to the query in the request; from Vsevolod Stakhov.
o Fix a merge problem in which name_from_addr returned pointers to the stack; found by Jiang Hong.
o Do not remove Accept-Encoding header
Changes in 1.4.7-stable:
o Fix a bug where headers arriving in multiple packets were not parsed; fix from Jiang Hong; test by me.
Changes in 1.4.6-stable:
o evutil.h now includes <stdarg.h> directly
o switch all uses of [v]snprintf over to evutil
o Correct handling of trailing headers in chunked replies; from Scott Lamb.
o Support multi-line HTTP headers; based on a patch from Moshe Litvin
o Reject negative Content-Length headers; anonymous bug report
o Detect CLOCK_MONOTONIC at runtime for evdns; anonymous bug report
o Fix a bug where deleting signals with the kqueue backend would cause subsequent adds to fail
o Support multiple events listening on the same signal; make signals regular events that go on the same event queue; problem report by Alexander Drozdov.
o Deal with evbuffer_read() returning -1 on EINTR|EAGAIN; from Adam Langley.
o Fix a bug in which the DNS server would incorrectly set the type of a cname reply to a.
o Fix a bug where setting the timeout on a bufferevent would take not effect if the event was already pending.
o Fix a memory leak when using signals for some event bases; reported by Alexander Drozdov.
o Add libevent.vcproj file to distribution to help with Windows build.
o Fix a problem with epoll() and reinit; problem report by Alexander Drozdov.
o Fix off-by-one errors in devpoll; from Ian Bell
o Make event_add not change any state if it fails; reported by Ian Bell.
o Do not warn on accept when errno is either EAGAIN or EINTR
Changes in 1.4.5-stable:
o Fix connection keep-alive behavior for HTTP/1.0
o Fix use of freed memory in event_reinit; pointed out by Peter Postma
o Constify struct timeval * where possible; pointed out by Forest Wilkinson
o allow min_heap_erase to be called on removed members; from liusifan.
o Rename INPUT and OUTPUT to EVRPC_INPUT and EVRPC_OUTPUT. Retain INPUT/OUTPUT aliases on on-win32 platforms for backwards compatibility.
o Do not use SO_REUSEADDR when connecting
o Fix Windows build
o Fix a bug in event_rpcgen when generated fixed-sized entries
Changes in 1.4.4-stable:
o Correct the documentation on buffer printf functions.
o Don't warn on unimplemented epoll_create(): this isn't a problem, just a reason to fall back to poll or select.
o Correctly handle timeouts larger than 35 minutes on Linux with epoll.c. This is probably a kernel defect, but we'll have to support old kernels anyway even if it gets fixed.
o Fix a potential stack corruption bug in tagging on 64-bit CPUs.
o expose bufferevent_setwatermark via header files and fix high watermark on read
o fix a bug in bufferevent read water marks and add a test for them
o introduce bufferevent_setcb and bufferevent_setfd to allow better manipulation of bufferevents
o use libevent's internal timercmp on all platforms, to avoid bugs on old platforms where timercmp(a,b,<=) is buggy.
o reduce system calls for getting current time by caching it.
o fix evhttp_bind_socket() so that multiple sockets can be bound by the same http server.
o Build test directory correctly with CPPFLAGS set.
o Fix build under Visual C++ 2005.
o Expose evhttp_accept_socket() API.
o Merge windows gettimeofday() replacement into a new evutil_gettimeofday() function.
o Fix autoconf script behavior on IRIX.
o Make sure winsock2.h include always comes before windows.h include.
Changes in 1.4.3-stable:
o include Content-Length in reply for HTTP/1.0 requests with keep-alive
o Patch from Tani Hosokawa: make some functions in http.c threadsafe.
o Do not free the kqop file descriptor in other processes, also allow it to be 0; from Andrei Nigmatulin
o make event_rpcgen.py generate code include event-config.h; reported by Sam Banks.
o make event methods static so that they are not exported; from Andrei Nigmatulin
o make RPC replies use application/octet-stream as mime type
o do not delete uninitialized timeout event in evdns
Changes in 1.4.2-rc:
o remove pending timeouts on event_base_free()
o also check EAGAIN for Solaris' event ports; from W.C.A. Wijngaards
o devpoll and evport need reinit; tested by W.C.A Wijngaards
o event_base_get_method; from Springande Ulv
o Send CRLF after each chunk in HTTP output, for compliance with RFC2626. Patch from "propanbutan". Fixes bug 1894184.
o Add a int64_t parsing function, with unit tests, so we can apply Scott Lamb's fix to allow large HTTP values.
o Use a 64-bit field to hold HTTP content-lengths. Patch from Scott Lamb.
o Allow regression code to build even without Python installed
o remove NDEBUG ifdefs from evdns.c
o update documentation of event_loop and event_base_loop; from Tani Hosokawa.
o detect integer types properly on platforms without stdint.h
o Remove "AM_MAINTAINER_MODE" declaration in configure.in: now makefiles and configure should get re-generated automatically when Makefile.am or configure.in chanes.
o do not insert event into list when evsel->add fails
Changes in 1.4.1-beta:
o free minheap on event_base_free(); from Christopher Layne
o debug cleanups in signal.c; from Christopher Layne
o provide event_base_new() that does not set the current_base global
o bufferevent_write now uses a const source argument; report from Charles Kerr
o better documentation for event_base_loopexit; from Scott Lamb.
o Make kqueue have the same behavior as other backends when a signal is caught between event_add() and event_loop(). Previously, it would catch and ignore such signals.
o Make kqueue restore signal handlers correctly when event_del() is called.
o provide event_reinit() to reintialize an event_base after fork
o small improvements to evhttp documentation
o always generate Date and Content-Length headers for HTTP/1.1 replies
o set the correct event base for HTTP close events
o New function, event_{base_}loopbreak. Like event_loopexit, it makes an event loop stop executing and return. Unlike event_loopexit, it keeps subsequent pending events from getting executed. Patch from Scott Lamb
o Removed obsoleted recalc code
o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures.
o fix a bug with event_rpcgen for integers
o move EV_PERSIST handling out of the event backends
o support for 32-bit tag numbers in rpc structures; this is wire compatible, but changes the API slightly.
o prefix {encode,decode}_tag functions with evtag to avoid collisions
o Correctly handle DNS replies with no answers set (Fixes bug 1846282)
o The configure script now takes an --enable-gcc-warnigns option that turns on many optional gcc warnings. (Nick has been building with these for a while, but they might be useful to other developers.)
o When building with GCC, use the "format" attribute to verify type correctness of calls to printf-like functions.
o removed linger from http server socket; reported by Ilya Martynov
o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
o demote most http warnings to debug messages
o Fix Solaris compilation; from Magne Mahre
o Add a "Date" header to HTTP responses, as required by HTTP 1.1.
o Support specifying the local address of an evhttp_connection using set_local_address
o Fix a memory leak in which failed HTTP connections would not free the request object
o Make adding of array members in event_rpcgen more efficient, but doubling memory allocation
o Fix a memory leak in the DNS server
o Fix compilation when DNS_USE_OPENSSL_FOR_ID is enabled
o Fix buffer size and string generation in evdns_resolve_reverse_ipv6().
o Respond to nonstandard DNS queries with "NOTIMPL" rather than by ignoring them.
o In DNS responses, the CD flag should be preserved, not the TC flag.
o Fix http.c to compile properly with USE_DEBUG; from Christopher Layne
o Handle NULL timeouts correctly on Solaris; from Trond Norbye
o Recalculate pending events properly when reallocating event array on Solaris; from Trond Norbye
o Add Doxygen documentation to header files; from Mark Heily
o Add a evdns_set_transaction_id_fn() function to override the default
transaction ID generation code.
o Add an evutil module (with header evutil.h) to implement our standard cross-platform hacks, on the theory that somebody else would like to use them too.
o Fix signals implementation on windows.
o Fix http module on windows to close sockets properly.
o Make autogen.sh script run correctly on systems where /bin/sh isn't bash. (Patch from Trond Norbye, rewritten by Hagne Mahre and then Hannah Schroeter.)
o Skip calling gettime() in timeout_process if we are not in fact waiting for any events. (Patch from Trond Norbye)
o Make test subdirectory compile under mingw.
o Fix win32 buffer.c behavior so that it is correct for sockets (which do not like ReadFile and WriteFile).
o Make the test.sh script run unit tests for the evpoll method.
o Make the entire evdns.h header enclosed in "extern C" as appropriate.
o Fix implementation of strsep on platforms that lack it
o Fix implementation of getaddrinfo on platforms that lack it; mainly, this will make Windows http.c work better. Original patch by Lubomir Marinov.
o Fix evport implementation: port_disassociate called on unassociated events resulting in bogus errors; more efficient memory management; from Trond Norbye and Prakash Sangappa
o support for hooks on rpc input and output; can be used to implement rpc independent processing such as compression or authentication.
o use a min heap instead of a red-black tree for timeouts; as a result finding the min is a O(1) operation now; from Maxim Yegorushkin
o associate an event base with an rpc pool
o added two additional libraries: libevent_core and libevent_extra in addition to the regular libevent. libevent_core contains only the event core whereas libevent_extra contains dns, http and rpc support
o Begin using libtool's library versioning support correctly. If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility.
o Fix evhttp.h compilation when TAILQ_ENTRY is not defined.
o Small code cleanups in epoll_dispatch().
o Increase the maximum number of addresses read from a packet in evdns to 32.
o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much. Let us know if there's a good reason to put it back in.
o Rename the "class" field in evdns_server_request to dns_question_class, so that it won't break compilation under C++. Use a macro so that old code won't break. Mark the macro as deprecated.
o Fix DNS unit tests so that having a DNS server with broken IPv6 support is no longer cause for aborting the unit tests.
o Make event_base_free() succeed even if there are pending non-internal events on a base. This may still leak memory and fds, but at least it no longer crashes.
o Post-process the config.h file into a new, installed event-config.h file that we can install, and whose macros will be safe to include in header files.
o Remove the long-deprecated acconfig.h file.
o Do not require #include <sys/types.h> before #include <event.h>.
o Add new evutil_timer* functions to wrap (or replace) the regular timeval manipulation functions.
o Fix many build issues when using the Microsoft C compiler.
o Remove a bash-ism in autogen.sh
o When calling event_del on a signal, restore the signal handler's previous value rather than setting it to SIG_DFL. Patch from Christopher Layne.
o Make the logic for active events work better with internal events; patch from Christopher Layne.
o We do not need to specially remove a timeout before calling event_del; patch from Christopher Layne.

230
libevent/Doxyfile Normal file
View File

@ -0,0 +1,230 @@
# Doxyfile 1.5.1
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, ...]
# For lists items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ")
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.
PROJECT_NAME = libevent
# Place all output under 'doxygen/'
OUTPUT_DIRECTORY = doxygen/
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like the Qt-style comments (thus requiring an
# explicit @brief command for a brief description.
JAVADOC_AUTOBRIEF = YES
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.
OPTIMIZE_OUTPUT_FOR_C = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.
SORT_BRIEF_DOCS = YES
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = event.h evdns.h evhttp.h evrpc.h
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.
GENERATE_HTML = YES
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, a4wide, letter, legal and
# executive. If left blank a4wide will be used.
PAPER_TYPE = a4wide
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!
LATEX_HEADER =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.
PDF_HYPERLINKS = NO
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.
USE_PDFLATEX = NO
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.
LATEX_BATCHMODE = NO
# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages
GENERATE_MAN = YES
# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)
MAN_EXTENSION = .3
# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.
MAN_LINKS = YES
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.
MACRO_EXPANSION = NO
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.
EXPAND_ONLY_PREDEF = NO
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# in the INCLUDE_PATH (see below) will be search if a #include is found.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED = TAILQ_ENTRY RB_ENTRY _EVENT_DEFINED_TQENTRY
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition.
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all function-like macros that are alone
# on a line, have an all uppercase name, and do not end with a semicolon. Such
# function macros are typically used for boiler-plate code, and will confuse
# the parser if not removed.
SKIP_FUNCTION_MACROS = YES

124
libevent/Makefile.am Normal file
View File

@ -0,0 +1,124 @@
AUTOMAKE_OPTIONS = foreign no-dependencies
# This is the point release for libevent. It shouldn't include any
# a/b/c/d/e notations.
RELEASE = 1.4
# This is the version info for the libevent binary API. It has three
# numbers:
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
# API are we supplying?
# Age -- How many previous binary API versions do we also
# support?
#
# If we release a new version that does not change the binary API,
# increment Revision.
#
# If we release a new version that changes the binary API, but does
# not break programs compiled against the old binary API, increment
# Current and Age. Set Revision to 0, since this is the first
# implementation of the new API.
#
# Otherwise, we're changing the binary API and breaking bakward
# compatibility with old binaries. Increment Current. Set Age to 0,
# since we're backward compatible with no previous APIs. Set Revision
# to 0 too.
# History:
# Libevent 1.4.1 was 2:0:0
# Libevent 1.4.2 should be 3:0:0
# Libevent 1.4.5 is 3:0:1 (we forgot to increment in the past)
VERSION_INFO = 3:3:1
bin_SCRIPTS = event_rpcgen.py
EXTRA_DIST = autogen.sh event.h event-internal.h log.h evsignal.h evdns.3 \
evrpc.h evrpc-internal.h min_heap.h \
event.3 \
Doxyfile \
kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \
evport.c devpoll.c event_rpcgen.py \
sample/Makefile.am sample/Makefile.in sample/event-test.c \
sample/signal-test.c sample/time-test.c \
test/Makefile.am test/Makefile.in test/bench.c test/regress.c \
test/test-eof.c test/test-weof.c test/test-time.c \
test/test-init.c test/test.sh \
compat/sys/queue.h compat/sys/_time.h \
WIN32-Code/config.h \
WIN32-Code/event-config.h \
WIN32-Code/win32.c \
WIN32-Code/tree.h \
WIN32-Prj/event_test/event_test.dsp \
WIN32-Prj/event_test/test.txt WIN32-Prj/libevent.dsp \
WIN32-Prj/libevent.dsw WIN32-Prj/signal_test/signal_test.dsp \
WIN32-Prj/time_test/time_test.dsp WIN32-Prj/regress/regress.vcproj \
WIN32-Prj/libevent.sln WIN32-Prj/libevent.vcproj
lib_LTLIBRARIES = libevent.la libevent_core.la libevent_extra.la
if BUILD_WIN32
SUBDIRS = . sample
SYS_LIBS = -lws2_32
SYS_SRC = WIN32-Code/win32.c
SYS_INCLUDES = -IWIN32-Code
else
SUBDIRS = . sample test
SYS_LIBS =
SYS_SRC =
SYS_INCLUDES =
endif
BUILT_SOURCES = event-config.h
event-config.h: config.h
echo '/* event-config.h' > $@
echo ' * Generated by autoconf; post-processed by libevent.' >> $@
echo ' * Do not edit this file.' >> $@
echo ' * Do not rely on macros in this file existing in later versions.'>> $@
echo ' */' >> $@
echo '#ifndef _EVENT_CONFIG_H_' >> $@
echo '#define _EVENT_CONFIG_H_' >> $@
sed -e 's/#define /#define _EVENT_/' \
-e 's/#undef /#undef _EVENT_/' \
-e 's/#ifndef /#ifndef _EVENT_/' < config.h >> $@
echo "#endif" >> $@
CORE_SRC = event.c buffer.c evbuffer.c log.c evutil.c $(SYS_SRC)
EXTRA_SRC = event_tagging.c http.c evhttp.h http-internal.h evdns.c \
evdns.h evrpc.c evrpc.h evrpc-internal.h \
strlcpy.c strlcpy-internal.h strlcpy-internal.h
libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
libevent_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
libevent_core_la_SOURCES = $(CORE_SRC)
libevent_core_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
libevent_core_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
libevent_extra_la_SOURCES = $(EXTRA_SRC)
libevent_extra_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
libevent_extra_la_LDFLAGS = -release $(RELEASE) -version-info $(VERSION_INFO)
include_HEADERS = event.h evhttp.h evdns.h evrpc.h evutil.h
nodist_include_HEADERS = event-config.h
INCLUDES = -I$(srcdir)/compat $(SYS_INCLUDES)
man_MANS = event.3 evdns.3
verify: libevent.la
cd test && make verify
doxygen: FORCE
doxygen $(srcdir)/Doxyfile
FORCE:
DISTCLEANFILES = *~ event-config.h

57
libevent/README Normal file
View File

@ -0,0 +1,57 @@
To build libevent, type
$ ./configure && make
(If you got libevent from the subversion repository, you will
first need to run the included "autogen.sh" script in order to
generate the configure script.)
Install as root via
# make install
You can run the regression tests by
$ make verify
Before, reporting any problems, please run the regression tests.
To enable the low-level tracing build the library as:
CFLAGS=-DUSE_DEBUG ./configure [...]
Acknowledgements:
-----------------
The following people have helped with suggestions, ideas, code or
fixing bugs:
Alejo
Weston Andros Adamson
William Ahern
Stas Bekman
Andrew Danforth
Mike Davis
Shie Erlich
Alexander von Gernler
Artur Grabowski
Aaron Hopkins
Claudio Jeker
Scott Lamb
Adam Langley
Philip Lewis
David Libenzi
Nick Mathewson
Andrey Matveev
Richard Nyberg
Jon Oberheide
Phil Oleson
Dave Pacheco
Tassilo von Parseval
Pierre Phaneuf
Jon Poland
Bert JW Regeer
Dug Song
Taral
If I have forgotten your name, please contact me.

View File

@ -0,0 +1,244 @@
/* event-config.h
* Generated by autoconf; post-processed by libevent.
* Do not edit this file.
* Do not rely on macros in this file existing in later versions.
*/
#ifndef _EVENT_CONFIG_H_
#define _EVENT_CONFIG_H_
/* config.h. Generated by configure. */
/* config.h.in. Generated from configure.in by autoheader. */
/* Define if clock_gettime is available in libc */
/* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */
/* Define is no secure id variant is available */
#define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1
/* Define to 1 if you have the `clock_gettime' function. */
/* #undef _EVENT_HAVE_CLOCK_GETTIME */
/* Define if /dev/poll is available */
/* #undef _EVENT_HAVE_DEVPOLL */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef _EVENT_HAVE_DLFCN_H */
/* Define if your system supports the epoll system calls */
/* #undef _EVENT_HAVE_EPOLL */
/* Define to 1 if you have the `epoll_ctl' function. */
/* #undef _EVENT_HAVE_EPOLL_CTL */
/* Define if your system supports event ports */
/* #undef _EVENT_HAVE_EVENT_PORTS */
/* Define to 1 if you have the `fcntl' function. */
/* #undef _EVENT_HAVE_FCNTL */
/* Define to 1 if you have the <fcntl.h> header file. */
#define _EVENT_HAVE_FCNTL_H 1
/* Define to 1 if you have the `getaddrinfo' function. */
/* #undef _EVENT_HAVE_GETADDRINFO */
/* Define to 1 if you have the `getnameinfo' function. */
/* #undef _EVENT_HAVE_GETNAMEINFO */
/* Define to 1 if you have the `gettimeofday' function. */
/* #define _EVENT_HAVE_GETTIMEOFDAY 1 */
/* Define to 1 if you have the `inet_ntop' function. */
/* #undef _EVENT_HAVE_INET_NTOP */
/* Define to 1 if you have the <inttypes.h> header file. */
/* #undef _EVENT_HAVE_INTTYPES_H 1 */
/* Define to 1 if you have the `kqueue' function. */
/* #undef _EVENT_HAVE_KQUEUE */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef _EVENT_HAVE_LIBNSL */
/* Define to 1 if you have the `resolv' library (-lresolv). */
/* #undef _EVENT_HAVE_LIBRESOLV */
/* Define to 1 if you have the `rt' library (-lrt). */
/* #undef _EVENT_HAVE_LIBRT */
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef _EVENT_HAVE_LIBSOCKET */
/* Define to 1 if you have the <memory.h> header file. */
#define _EVENT_HAVE_MEMORY_H 1
/* Define to 1 if you have the <netinet/in6.h> header file. */
/* #undef _EVENT_HAVE_NETINET_IN6_H */
/* Define to 1 if you have the `poll' function. */
/* #undef _EVENT_HAVE_POLL */
/* Define to 1 if you have the <poll.h> header file. */
/* #undef _EVENT_HAVE_POLL_H */
/* Define to 1 if you have the `port_create' function. */
/* #undef _EVENT_HAVE_PORT_CREATE */
/* Define to 1 if you have the <port.h> header file. */
/* #undef _EVENT_HAVE_PORT_H */
/* Define to 1 if you have the `select' function. */
/* #undef _EVENT_HAVE_SELECT */
/* Define if F_SETFD is defined in <fcntl.h> */
/* #undef _EVENT_HAVE_SETFD */
/* Define to 1 if you have the `sigaction' function. */
/* #undef _EVENT_HAVE_SIGACTION */
/* Define to 1 if you have the `signal' function. */
#define _EVENT_HAVE_SIGNAL 1
/* Define to 1 if you have the <signal.h> header file. */
#define _EVENT_HAVE_SIGNAL_H 1
/* Define to 1 if you have the <stdarg.h> header file. */
#define _EVENT_HAVE_STDARG_H 1
/* Define to 1 if you have the <stdint.h> header file. */
/* #define _EVENT_HAVE_STDINT_H 1 */
/* Define to 1 if you have the <stdlib.h> header file. */
#define _EVENT_HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define _EVENT_HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define _EVENT_HAVE_STRING_H 1
/* Define to 1 if you have the `strlcpy' function. */
/* #undef _EVENT_HAVE_STRLCPY */
/* Define to 1 if you have the `strsep' function. */
/* #undef _EVENT_HAVE_STRSEP */
/* Define to 1 if you have the `strtok_r' function. */
/* #undef _EVENT_HAVE_STRTOK_R */
/* Define to 1 if the system has the type `struct in6_addr'. */
#define _EVENT_HAVE_STRUCT_IN6_ADDR 1
/* Define to 1 if you have the <sys/devpoll.h> header file. */
/* #undef _EVENT_HAVE_SYS_DEVPOLL_H */
/* Define to 1 if you have the <sys/epoll.h> header file. */
/* #undef _EVENT_HAVE_SYS_EPOLL_H */
/* Define to 1 if you have the <sys/event.h> header file. */
/* #undef _EVENT_HAVE_SYS_EVENT_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
/* #undef _EVENT_HAVE_SYS_IOCTL_H */
/* Define to 1 if you have the <sys/queue.h> header file. */
/* #undef _EVENT_HAVE_SYS_QUEUE_H */
/* Define to 1 if you have the <sys/select.h> header file. */
/* #undef _EVENT_HAVE_SYS_SELECT_H */
/* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef _EVENT_HAVE_SYS_SOCKET_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define _EVENT_HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
/* #define _EVENT_HAVE_SYS_TIME_H 1 */
/* Define to 1 if you have the <sys/types.h> header file. */
/* #define _EVENT_HAVE_SYS_TYPES_H 1 */
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
/* #undef _EVENT_HAVE_TAILQFOREACH */
/* Define if timeradd is defined in <sys/time.h> */
/* #undef _EVENT_HAVE_TIMERADD */
/* Define if timerclear is defined in <sys/time.h> */
/* #define _EVENT_HAVE_TIMERCLEAR 1 */
/* Define if timercmp is defined in <sys/time.h> */
#define _EVENT_HAVE_TIMERCMP 1
/* Define if timerisset is defined in <sys/time.h> */
#define _EVENT_HAVE_TIMERISSET 1
/* Define to 1 if you have the <unistd.h> header file. */
/* #define _EVENT_HAVE_UNISTD_H 1 */
/* Define to 1 if you have the `vasprintf' function. */
/* #undef _EVENT_HAVE_VASPRINTF */
/* Define if kqueue works correctly with pipes */
/* #undef _EVENT_HAVE_WORKING_KQUEUE */
/* Name of package */
#define _EVENT_PACKAGE "libevent"
/* Define to the address where bug reports for this package should be sent. */
#define _EVENT_PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define _EVENT_PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define _EVENT_PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define _EVENT_PACKAGE_TARNAME ""
/* Define to the version of this package. */
#define _EVENT_PACKAGE_VERSION ""
/* Define to 1 if you have the ANSI C header files. */
#define _EVENT_STDC_HEADERS 1
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#define _EVENT_TIME_WITH_SYS_TIME 1
/* Version number of package */
#define _EVENT_VERSION "1.3.99-trunk"
/* Define to appropriate substitue if compiler doesnt have __func__ */
/* #undef _EVENT___func__ */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef _EVENT_const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef _EVENT___cplusplus
#define _EVENT_inline __inline
#endif
/* Define to `int' if <sys/types.h> does not define. */
/* #undef _EVENT_pid_t */
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef _EVENT_size_t */
/* Define to unsigned int if you dont have it */
#define _EVENT_socklen_t unsigned int
/* Define to `unsigned short' if <sys/types.h> does not define. */
/* #undef _EVENT_uint16_t */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef _EVENT_uint32_t */
/* Define to `unsigned long long' if <sys/types.h> does not define. */
/* #undef _EVENT_uint64_t */
/* Define to `unsigned char' if <sys/types.h> does not define. */
/* #undef _EVENT_uint8_t */
#endif

View File

@ -0,0 +1,93 @@
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <sys/timeb.h>
#include <time.h>
#ifdef __GNUC__
/*our prototypes for timeval and timezone are in here, just in case the above
headers don't have them*/
#include "misc.h"
#endif
/****************************************************************************
*
* Function: gettimeofday(struct timeval *, struct timezone *)
*
* Purpose: Get current time of day.
*
* Arguments: tv => Place to store the curent time of day.
* tz => Ignored.
*
* Returns: 0 => Success.
*
****************************************************************************/
#ifndef HAVE_GETTIMEOFDAY
int gettimeofday(struct timeval *tv, struct timezone *tz) {
struct _timeb tb;
if(tv == NULL)
return -1;
_ftime(&tb);
tv->tv_sec = (long) tb.time;
tv->tv_usec = ((int) tb.millitm) * 1000;
return 0;
}
#endif
#if 0
int
win_read(int fd, void *buf, unsigned int length)
{
DWORD dwBytesRead;
int res = ReadFile((HANDLE) fd, buf, length, &dwBytesRead, NULL);
if (res == 0) {
DWORD error = GetLastError();
if (error == ERROR_NO_DATA)
return (0);
return (-1);
} else
return (dwBytesRead);
}
int
win_write(int fd, void *buf, unsigned int length)
{
DWORD dwBytesWritten;
int res = WriteFile((HANDLE) fd, buf, length, &dwBytesWritten, NULL);
if (res == 0) {
DWORD error = GetLastError();
if (error == ERROR_NO_DATA)
return (0);
return (-1);
} else
return (dwBytesWritten);
}
int
socketpair(int d, int type, int protocol, int *sv)
{
static int count;
char buf[64];
HANDLE fd;
DWORD dwMode;
sprintf(buf, "\\\\.\\pipe\\levent-%d", count++);
/* Create a duplex pipe which will behave like a socket pair */
fd = CreateNamedPipe(buf, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_NOWAIT,
PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL);
if (fd == INVALID_HANDLE_VALUE)
return (-1);
sv[0] = (int)fd;
fd = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd == INVALID_HANDLE_VALUE)
return (-1);
dwMode = PIPE_NOWAIT;
SetNamedPipeHandleState(fd, &dwMode, NULL, NULL);
sv[1] = (int)fd;
return (0);
}
#endif

View File

@ -0,0 +1,11 @@
#ifndef MISC_H
#define MISC_H
struct timezone;
struct timeval;
#ifndef HAVE_GETTIMEOFDAY
int gettimeofday(struct timeval *,struct timezone *);
#endif
#endif

1354
libevent/WIN32-Code/tree.h Normal file

File diff suppressed because it is too large Load Diff

486
libevent/WIN32-Code/win32.c Normal file
View File

@ -0,0 +1,486 @@
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2003 Michael A. Davis <mike@datanerds.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef _MSC_VER
#include "./config.h"
#else
/* Avoid the windows/msvc thing. */
#include "../config.h"
#endif
#include <winsock2.h>
#include <windows.h>
#include <sys/types.h>
#include <sys/queue.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#define RB_AUGMENT(x) (void)(x)
#include "./tree.h"
#include "log.h"
#include "event.h"
#include "event-internal.h"
#define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
extern struct event_list timequeue;
extern struct event_list addqueue;
#if 0
extern struct event_list signalqueue;
#endif
struct win_fd_set {
u_int fd_count;
SOCKET fd_array[1];
};
int evsigcaught[NSIG];
volatile sig_atomic_t signal_caught = 0;
/* MSDN says this is required to handle SIGFPE */
volatile double SIGFPE_REQ = 0.0f;
#if 0
static void signal_handler(int sig);
void signal_process(void);
int signal_recalc(void);
#endif
struct event_entry {
RB_ENTRY(event_entry) node;
SOCKET sock;
int read_pos;
int write_pos;
struct event *read_event;
struct event *write_event;
};
static int
compare(struct event_entry *a, struct event_entry *b)
{
if (a->sock < b->sock)
return -1;
else if (a->sock > b->sock)
return 1;
else
return 0;
}
struct win32op {
int fd_setsz;
struct win_fd_set *readset_in;
struct win_fd_set *writeset_in;
struct win_fd_set *readset_out;
struct win_fd_set *writeset_out;
struct win_fd_set *exset_out;
RB_HEAD(event_map, event_entry) event_root;
unsigned signals_are_broken : 1;
};
RB_PROTOTYPE(event_map, event_entry, node, compare);
RB_GENERATE(event_map, event_entry, node, compare);
void *win32_init (struct event_base *);
int win32_insert (void *, struct event *);
int win32_del (void *, struct event *);
int win32_dispatch (struct event_base *base, void *, struct timeval *);
void win32_dealloc (struct event_base *, void *);
struct eventop win32ops = {
"win32",
win32_init,
win32_insert,
win32_del,
win32_dispatch,
win32_dealloc,
0
};
#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
static int
realloc_fd_sets(struct win32op *op, size_t new_size)
{
size_t size;
assert(new_size >= op->readset_in->fd_count &&
new_size >= op->writeset_in->fd_count);
assert(new_size >= 1);
size = FD_SET_ALLOC_SIZE(new_size);
if (!(op->readset_in = realloc(op->readset_in, size)))
return (-1);
if (!(op->writeset_in = realloc(op->writeset_in, size)))
return (-1);
if (!(op->readset_out = realloc(op->readset_out, size)))
return (-1);
if (!(op->exset_out = realloc(op->exset_out, size)))
return (-1);
if (!(op->writeset_out = realloc(op->writeset_out, size)))
return (-1);
op->fd_setsz = new_size;
return (0);
}
static int
timeval_to_ms(struct timeval *tv)
{
return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
}
static struct event_entry*
get_event_entry(struct win32op *op, SOCKET s, int create)
{
struct event_entry key, *val;
key.sock = s;
val = RB_FIND(event_map, &op->event_root, &key);
if (val || !create)
return val;
if (!(val = calloc(1, sizeof(struct event_entry)))) {
event_warn("%s: calloc", __func__);
return NULL;
}
val->sock = s;
val->read_pos = val->write_pos = -1;
RB_INSERT(event_map, &op->event_root, val);
return val;
}
static int
do_fd_set(struct win32op *op, struct event_entry *ent, int read)
{
SOCKET s = ent->sock;
struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
if (read) {
if (ent->read_pos >= 0)
return (0);
} else {
if (ent->write_pos >= 0)
return (0);
}
if (set->fd_count == op->fd_setsz) {
if (realloc_fd_sets(op, op->fd_setsz*2))
return (-1);
/* set pointer will have changed and needs reiniting! */
set = read ? op->readset_in : op->writeset_in;
}
set->fd_array[set->fd_count] = s;
if (read)
ent->read_pos = set->fd_count;
else
ent->write_pos = set->fd_count;
return (set->fd_count++);
}
static int
do_fd_clear(struct win32op *op, struct event_entry *ent, int read)
{
int i;
struct win_fd_set *set = read ? op->readset_in : op->writeset_in;
if (read) {
i = ent->read_pos;
ent->read_pos = -1;
} else {
i = ent->write_pos;
ent->write_pos = -1;
}
if (i < 0)
return (0);
if (--set->fd_count != i) {
struct event_entry *ent2;
SOCKET s2;
s2 = set->fd_array[i] = set->fd_array[set->fd_count];
ent2 = get_event_entry(op, s2, 0);
if (!ent) /* This indicates a bug. */
return (0);
if (read)
ent2->read_pos = i;
else
ent2->write_pos = i;
}
return (0);
}
#define NEVENT 64
void *
win32_init(struct event_base *_base)
{
struct win32op *winop;
size_t size;
if (!(winop = calloc(1, sizeof(struct win32op))))
return NULL;
winop->fd_setsz = NEVENT;
size = FD_SET_ALLOC_SIZE(NEVENT);
if (!(winop->readset_in = malloc(size)))
goto err;
if (!(winop->writeset_in = malloc(size)))
goto err;
if (!(winop->readset_out = malloc(size)))
goto err;
if (!(winop->writeset_out = malloc(size)))
goto err;
if (!(winop->exset_out = malloc(size)))
goto err;
RB_INIT(&winop->event_root);
winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;
winop->readset_out->fd_count = winop->writeset_out->fd_count
= winop->exset_out->fd_count = 0;
if (evsignal_init(_base) < 0)
winop->signals_are_broken = 1;
return (winop);
err:
XFREE(winop->readset_in);
XFREE(winop->writeset_in);
XFREE(winop->readset_out);
XFREE(winop->writeset_out);
XFREE(winop->exset_out);
XFREE(winop);
return (NULL);
}
int
win32_insert(void *op, struct event *ev)
{
struct win32op *win32op = op;
struct event_entry *ent;
if (ev->ev_events & EV_SIGNAL) {
if (win32op->signals_are_broken)
return (-1);
return (evsignal_add(ev));
}
if (!(ev->ev_events & (EV_READ|EV_WRITE)))
return (0);
ent = get_event_entry(win32op, ev->ev_fd, 1);
if (!ent)
return (-1); /* out of memory */
event_debug(("%s: adding event for %d", __func__, (int)ev->ev_fd));
if (ev->ev_events & EV_READ) {
if (do_fd_set(win32op, ent, 1)<0)
return (-1);
ent->read_event = ev;
}
if (ev->ev_events & EV_WRITE) {
if (do_fd_set(win32op, ent, 0)<0)
return (-1);
ent->write_event = ev;
}
return (0);
}
int
win32_del(void *op, struct event *ev)
{
struct win32op *win32op = op;
struct event_entry *ent;
if (ev->ev_events & EV_SIGNAL)
return (evsignal_del(ev));
if (!(ent = get_event_entry(win32op, ev->ev_fd, 0)))
return (-1);
event_debug(("%s: Removing event for %d", __func__, ev->ev_fd));
if (ev == ent->read_event) {
do_fd_clear(win32op, ent, 1);
ent->read_event = NULL;
}
if (ev == ent->write_event) {
do_fd_clear(win32op, ent, 0);
ent->write_event = NULL;
}
if (!ent->read_event && !ent->write_event) {
RB_REMOVE(event_map, &win32op->event_root, ent);
free(ent);
}
return 0;
}
static void
fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in)
{
out->fd_count = in->fd_count;
memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET)));
}
/*
static void dump_fd_set(struct win_fd_set *s)
{
unsigned int i;
printf("[ ");
for(i=0;i<s->fd_count;++i)
printf("%d ",(int)s->fd_array[i]);
printf("]\n");
}
*/
int
win32_dispatch(struct event_base *base, void *op,
struct timeval *tv)
{
struct win32op *win32op = op;
int res = 0;
unsigned j, i;
int fd_count;
SOCKET s;
struct event_entry *ent;
fd_set_copy(win32op->readset_out, win32op->readset_in);
fd_set_copy(win32op->exset_out, win32op->readset_in);
fd_set_copy(win32op->writeset_out, win32op->writeset_in);
fd_count =
(win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?
win32op->readset_out->fd_count : win32op->writeset_out->fd_count;
if (!fd_count) {
/* Windows doesn't like you to call select() with no sockets */
Sleep(timeval_to_ms(tv));
evsignal_process(base);
return (0);
}
res = select(fd_count,
(struct fd_set*)win32op->readset_out,
(struct fd_set*)win32op->writeset_out,
(struct fd_set*)win32op->exset_out, tv);
event_debug(("%s: select returned %d", __func__, res));
if(res <= 0) {
evsignal_process(base);
return res;
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
if (win32op->readset_out->fd_count) {
i = rand() % win32op->readset_out->fd_count;
for (j=0; j<win32op->readset_out->fd_count; ++j) {
if (++i >= win32op->readset_out->fd_count)
i = 0;
s = win32op->readset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
}
}
if (win32op->exset_out->fd_count) {
i = rand() % win32op->exset_out->fd_count;
for (j=0; j<win32op->exset_out->fd_count; ++j) {
if (++i >= win32op->exset_out->fd_count)
i = 0;
s = win32op->exset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->read_event)
event_active(ent->read_event, EV_READ, 1);
}
}
if (win32op->writeset_out->fd_count) {
i = rand() % win32op->writeset_out->fd_count;
for (j=0; j<win32op->writeset_out->fd_count; ++j) {
if (++i >= win32op->exset_out->fd_count)
i = 0;
s = win32op->writeset_out->fd_array[i];
if ((ent = get_event_entry(win32op, s, 0)) && ent->write_event)
event_active(ent->write_event, EV_WRITE, 1);
}
}
return (0);
}
void
win32_dealloc(struct event_base *_base, void *arg)
{
struct win32op *win32op = arg;
evsignal_dealloc(_base);
if (win32op->readset_in)
free(win32op->readset_in);
if (win32op->writeset_in)
free(win32op->writeset_in);
if (win32op->readset_out)
free(win32op->readset_out);
if (win32op->writeset_out)
free(win32op->writeset_out);
if (win32op->exset_out)
free(win32op->exset_out);
/* XXXXX free the tree. */
memset(win32op, 0, sizeof(win32op));
free(win32op);
}
#if 0
static void
signal_handler(int sig)
{
evsigcaught[sig]++;
signal_caught = 1;
}
int
signal_recalc(void)
{
struct event *ev;
/* Reinstall our signal handler. */
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
if((int)signal(EVENT_SIGNAL(ev), signal_handler) == -1)
return (-1);
}
return (0);
}
void
signal_process(void)
{
struct event *ev;
short ncalls;
TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
ncalls = evsigcaught[EVENT_SIGNAL(ev)];
if (ncalls) {
if (!(ev->ev_events & EV_PERSIST))
event_del(ev);
event_active(ev, EV_SIGNAL, ncalls);
}
}
memset(evsigcaught, 0, sizeof(evsigcaught));
signal_caught = 0;
}
#endif

View File

@ -0,0 +1,74 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "event_test"=".\event_test\event_test.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name libevent
End Project Dependency
}}}
###############################################################################
Project: "libevent"=".\libevent.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "signal_test"=".\signal_test\signal_test.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name libevent
End Project Dependency
}}}
###############################################################################
Project: "time_test"=".\time_test\time_test.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name libevent
End Project Dependency
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@ -0,0 +1,53 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "event_test", "event_test\event_test.vcproj", "{52099A8B-455B-4BE9-8E61-A3D6E8A4338D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libevent", "libevent.vcproj", "{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "signal_test", "signal_test\signal_test.vcproj", "{768DB9DD-2694-4274-89B8-74106E8F7786}"
ProjectSection(ProjectDependencies) = postProject
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9} = {B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "time_test", "time_test\time_test.vcproj", "{D4BE29FB-E45C-4177-9647-74BBAFDC1257}"
ProjectSection(ProjectDependencies) = postProject
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9} = {B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regress", "regress\regress.vcproj", "{F7C26008-6066-4AD3-8543-452EFE58BD2E}"
ProjectSection(ProjectDependencies) = postProject
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9} = {B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{52099A8B-455B-4BE9-8E61-A3D6E8A4338D}.Debug|Win32.ActiveCfg = Debug|Win32
{52099A8B-455B-4BE9-8E61-A3D6E8A4338D}.Debug|Win32.Build.0 = Debug|Win32
{52099A8B-455B-4BE9-8E61-A3D6E8A4338D}.Release|Win32.ActiveCfg = Release|Win32
{52099A8B-455B-4BE9-8E61-A3D6E8A4338D}.Release|Win32.Build.0 = Release|Win32
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}.Debug|Win32.ActiveCfg = Debug|Win32
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}.Debug|Win32.Build.0 = Debug|Win32
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}.Release|Win32.ActiveCfg = Release|Win32
{B98ABFCE-24D4-4B70-94DE-EF7F1E0662F9}.Release|Win32.Build.0 = Release|Win32
{768DB9DD-2694-4274-89B8-74106E8F7786}.Debug|Win32.ActiveCfg = Debug|Win32
{768DB9DD-2694-4274-89B8-74106E8F7786}.Debug|Win32.Build.0 = Debug|Win32
{768DB9DD-2694-4274-89B8-74106E8F7786}.Release|Win32.ActiveCfg = Release|Win32
{768DB9DD-2694-4274-89B8-74106E8F7786}.Release|Win32.Build.0 = Release|Win32
{D4BE29FB-E45C-4177-9647-74BBAFDC1257}.Debug|Win32.ActiveCfg = Debug|Win32
{D4BE29FB-E45C-4177-9647-74BBAFDC1257}.Debug|Win32.Build.0 = Debug|Win32
{D4BE29FB-E45C-4177-9647-74BBAFDC1257}.Release|Win32.ActiveCfg = Release|Win32
{D4BE29FB-E45C-4177-9647-74BBAFDC1257}.Release|Win32.Build.0 = Release|Win32
{F7C26008-6066-4AD3-8543-452EFE58BD2E}.Debug|Win32.ActiveCfg = Debug|Win32
{F7C26008-6066-4AD3-8543-452EFE58BD2E}.Debug|Win32.Build.0 = Debug|Win32
{F7C26008-6066-4AD3-8543-452EFE58BD2E}.Release|Win32.ActiveCfg = Release|Win32
{F7C26008-6066-4AD3-8543-452EFE58BD2E}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

11
libevent/autogen.sh Normal file
View File

@ -0,0 +1,11 @@
#!/bin/sh
LIBTOOLIZE=libtoolize
SYSNAME=`uname`
if [ "x$SYSNAME" = "xDarwin" ] ; then
LIBTOOLIZE=glibtoolize
fi
aclocal && \
autoheader && \
$LIBTOOLIZE && \
autoconf && \
automake --add-missing --copy

451
libevent/buffer.c Normal file
View File

@ -0,0 +1,451 @@
/*
* Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#ifdef HAVE_VASPRINTF
/* If we have vasprintf, we need to define this before we include stdio.h. */
#define _GNU_SOURCE
#endif
#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "event.h"
#include "config.h"
#include "evutil.h"
struct evbuffer *
evbuffer_new(void)
{
struct evbuffer *buffer;
buffer = calloc(1, sizeof(struct evbuffer));
return (buffer);
}
void
evbuffer_free(struct evbuffer *buffer)
{
if (buffer->orig_buffer != NULL)
free(buffer->orig_buffer);
free(buffer);
}
/*
* This is a destructive add. The data from one buffer moves into
* the other buffer.
*/
#define SWAP(x,y) do { \
(x)->buffer = (y)->buffer; \
(x)->orig_buffer = (y)->orig_buffer; \
(x)->misalign = (y)->misalign; \
(x)->totallen = (y)->totallen; \
(x)->off = (y)->off; \
} while (0)
int
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
{
int res;
/* Short cut for better performance */
if (outbuf->off == 0) {
struct evbuffer tmp;
size_t oldoff = inbuf->off;
/* Swap them directly */
SWAP(&tmp, outbuf);
SWAP(outbuf, inbuf);
SWAP(inbuf, &tmp);
/*
* Optimization comes with a price; we need to notify the
* buffer if necessary of the changes. oldoff is the amount
* of data that we transfered from inbuf to outbuf
*/
if (inbuf->off != oldoff && inbuf->cb != NULL)
(*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
if (oldoff && outbuf->cb != NULL)
(*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
return (0);
}
res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
if (res == 0) {
/* We drain the input buffer on success */
evbuffer_drain(inbuf, inbuf->off);
}
return (res);
}
int
evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
{
char *buffer;
size_t space;
size_t oldoff = buf->off;
int sz;
va_list aq;
/* make sure that at least some space is available */
evbuffer_expand(buf, 64);
for (;;) {
size_t used = buf->misalign + buf->off;
buffer = (char *)buf->buffer + buf->off;
assert(buf->totallen >= used);
space = buf->totallen - used;
#ifndef va_copy
#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
#endif
va_copy(aq, ap);
sz = evutil_vsnprintf(buffer, space, fmt, aq);
va_end(aq);
if (sz < 0)
return (-1);
if ((size_t)sz < space) {
buf->off += sz;
if (buf->cb != NULL)
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
return (sz);
}
if (evbuffer_expand(buf, sz + 1) == -1)
return (-1);
}
/* NOTREACHED */
}
int
evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
{
int res = -1;
va_list ap;
va_start(ap, fmt);
res = evbuffer_add_vprintf(buf, fmt, ap);
va_end(ap);
return (res);
}
/* Reads data from an event buffer and drains the bytes read */
int
evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
{
size_t nread = datlen;
if (nread >= buf->off)
nread = buf->off;
memcpy(data, buf->buffer, nread);
evbuffer_drain(buf, nread);
return (nread);
}
/*
* Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
* The returned buffer needs to be freed by the called.
*/
char *
evbuffer_readline(struct evbuffer *buffer)
{
u_char *data = EVBUFFER_DATA(buffer);
size_t len = EVBUFFER_LENGTH(buffer);
char *line;
unsigned int i;
for (i = 0; i < len; i++) {
if (data[i] == '\r' || data[i] == '\n')
break;
}
if (i == len)
return (NULL);
if ((line = malloc(i + 1)) == NULL) {
fprintf(stderr, "%s: out of memory\n", __func__);
evbuffer_drain(buffer, i);
return (NULL);
}
memcpy(line, data, i);
line[i] = '\0';
/*
* Some protocols terminate a line with '\r\n', so check for
* that, too.
*/
if ( i < len - 1 ) {
char fch = data[i], sch = data[i+1];
/* Drain one more character if needed */
if ( (sch == '\r' || sch == '\n') && sch != fch )
i += 1;
}
evbuffer_drain(buffer, i + 1);
return (line);
}
/* Adds data to an event buffer */
static void
evbuffer_align(struct evbuffer *buf)
{
memmove(buf->orig_buffer, buf->buffer, buf->off);
buf->buffer = buf->orig_buffer;
buf->misalign = 0;
}
/* Expands the available space in the event buffer to at least datlen */
int
evbuffer_expand(struct evbuffer *buf, size_t datlen)
{
size_t need = buf->misalign + buf->off + datlen;
/* If we can fit all the data, then we don't have to do anything */
if (buf->totallen >= need)
return (0);
/*
* If the misalignment fulfills our data needs, we just force an
* alignment to happen. Afterwards, we have enough space.
*/
if (buf->misalign >= datlen) {
evbuffer_align(buf);
} else {
void *newbuf;
size_t length = buf->totallen;
if (length < 256)
length = 256;
while (length < need)
length <<= 1;
if (buf->orig_buffer != buf->buffer)
evbuffer_align(buf);
if ((newbuf = realloc(buf->buffer, length)) == NULL)
return (-1);
buf->orig_buffer = buf->buffer = newbuf;
buf->totallen = length;
}
return (0);
}
int
evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
{
size_t need = buf->misalign + buf->off + datlen;
size_t oldoff = buf->off;
if (buf->totallen < need) {
if (evbuffer_expand(buf, datlen) == -1)
return (-1);
}
memcpy(buf->buffer + buf->off, data, datlen);
buf->off += datlen;
if (datlen && buf->cb != NULL)
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
return (0);
}
void
evbuffer_drain(struct evbuffer *buf, size_t len)
{
size_t oldoff = buf->off;
if (len >= buf->off) {
buf->off = 0;
buf->buffer = buf->orig_buffer;
buf->misalign = 0;
goto done;
}
buf->buffer += len;
buf->misalign += len;
buf->off -= len;
done:
/* Tell someone about changes in this buffer */
if (buf->off != oldoff && buf->cb != NULL)
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
}
/*
* Reads data from a file descriptor into a buffer.
*/
#define EVBUFFER_MAX_READ 4096
int
evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
{
u_char *p;
size_t oldoff = buf->off;
int n = EVBUFFER_MAX_READ;
#if defined(FIONREAD)
#ifdef WIN32
long lng = n;
if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) {
#else
if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
#endif
n = EVBUFFER_MAX_READ;
} else if (n > EVBUFFER_MAX_READ && n > howmuch) {
/*
* It's possible that a lot of data is available for
* reading. We do not want to exhaust resources
* before the reader has a chance to do something
* about it. If the reader does not tell us how much
* data we should read, we artifically limit it.
*/
if ((size_t)n > buf->totallen << 2)
n = buf->totallen << 2;
if (n < EVBUFFER_MAX_READ)
n = EVBUFFER_MAX_READ;
}
#endif
if (howmuch < 0 || howmuch > n)
howmuch = n;
/* If we don't have FIONREAD, we might waste some space here */
if (evbuffer_expand(buf, howmuch) == -1)
return (-1);
/* We can append new data at this point */
p = buf->buffer + buf->off;
#ifndef WIN32
n = read(fd, p, howmuch);
#else
n = recv(fd, p, howmuch, 0);
#endif
if (n == -1)
return (-1);
if (n == 0)
return (0);
buf->off += n;
/* Tell someone about changes in this buffer */
if (buf->off != oldoff && buf->cb != NULL)
(*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
return (n);
}
int
evbuffer_write(struct evbuffer *buffer, int fd)
{
int n;
#ifndef WIN32
n = write(fd, buffer->buffer, buffer->off);
#else
n = send(fd, buffer->buffer, buffer->off, 0);
#endif
if (n == -1)
return (-1);
if (n == 0)
return (0);
evbuffer_drain(buffer, n);
return (n);
}
u_char *
evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
{
u_char *search = buffer->buffer, *end = search + buffer->off;
u_char *p;
while (search < end &&
(p = memchr(search, *what, end - search)) != NULL) {
if (p + len > end)
break;
if (memcmp(p, what, len) == 0)
return (p);
search = p + 1;
}
return (NULL);
}
void evbuffer_setcb(struct evbuffer *buffer,
void (*cb)(struct evbuffer *, size_t, size_t, void *),
void *cbarg)
{
buffer->cb = cb;
buffer->cbarg = cbarg;
}

163
libevent/compat/sys/_time.h Normal file
View File

@ -0,0 +1,163 @@
/* $OpenBSD: time.h,v 1.11 2000/10/10 13:36:48 itojun Exp $ */
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)time.h 8.2 (Berkeley) 7/10/94
*/
#ifndef _SYS_TIME_H_
#define _SYS_TIME_H_
#include <sys/types.h>
/*
* Structure returned by gettimeofday(2) system call,
* and used in other calls.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
/*
* Structure defined by POSIX.1b to be like a timeval.
*/
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
};
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
}
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of dst correction */
};
#define DST_NONE 0 /* not on dst */
#define DST_USA 1 /* USA style dst */
#define DST_AUST 2 /* Australian style dst */
#define DST_WET 3 /* Western European dst */
#define DST_MET 4 /* Middle European dst */
#define DST_EET 5 /* Eastern European dst */
#define DST_CAN 6 /* Canada */
/* Operations on timevals. */
#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timercmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
#define timeradd(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
if ((vvp)->tv_usec >= 1000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_usec -= 1000000; \
} \
} while (0)
#define timersub(tvp, uvp, vvp) \
do { \
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
if ((vvp)->tv_usec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_usec += 1000000; \
} \
} while (0)
/* Operations on timespecs. */
#define timespecclear(tsp) (tsp)->tv_sec = (tsp)->tv_nsec = 0
#define timespecisset(tsp) ((tsp)->tv_sec || (tsp)->tv_nsec)
#define timespeccmp(tsp, usp, cmp) \
(((tsp)->tv_sec == (usp)->tv_sec) ? \
((tsp)->tv_nsec cmp (usp)->tv_nsec) : \
((tsp)->tv_sec cmp (usp)->tv_sec))
#define timespecadd(tsp, usp, vsp) \
do { \
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
if ((vsp)->tv_nsec >= 1000000000L) { \
(vsp)->tv_sec++; \
(vsp)->tv_nsec -= 1000000000L; \
} \
} while (0)
#define timespecsub(tsp, usp, vsp) \
do { \
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
if ((vsp)->tv_nsec < 0) { \
(vsp)->tv_sec--; \
(vsp)->tv_nsec += 1000000000L; \
} \
} while (0)
/*
* Names of the interval timers, and structure
* defining a timer setting.
*/
#define ITIMER_REAL 0
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2
struct itimerval {
struct timeval it_interval; /* timer interval */
struct timeval it_value; /* current value */
};
/*
* Getkerninfo clock information structure
*/
struct clockinfo {
int hz; /* clock frequency */
int tick; /* micro-seconds per hz tick */
int tickadj; /* clock skew rate for adjtime() */
int stathz; /* statistics clock frequency */
int profhz; /* profiling clock frequency */
};
#define CLOCK_REALTIME 0
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
#define TIMER_RELTIME 0x0 /* relative timer */
#define TIMER_ABSTIME 0x1 /* absolute timer */
/* --- stuff got cut here - niels --- */
#endif /* !_SYS_TIME_H_ */

488
libevent/compat/sys/queue.h Normal file
View File

@ -0,0 +1,488 @@
/* $OpenBSD: queue.h,v 1.16 2000/09/07 19:47:59 art Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#ifndef WIN32
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
#endif
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* tail queue access methods
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
} while (0)
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue access methods
*/
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_END(head) ((void *)(head))
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
#define CIRCLEQ_EMPTY(head) \
(CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
#define CIRCLEQ_FOREACH(var, head, field) \
for((var) = CIRCLEQ_FIRST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_NEXT(var, field))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for((var) = CIRCLEQ_LAST(head); \
(var) != CIRCLEQ_END(head); \
(var) = CIRCLEQ_PREV(var, field))
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) do { \
(head)->cqh_first = CIRCLEQ_END(head); \
(head)->cqh_last = CIRCLEQ_END(head); \
} while (0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
} while (0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
} while (0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
if ((head)->cqh_last == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
} while (0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.cqe_next = CIRCLEQ_END(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
} while (0)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
} while (0)
#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
CIRCLEQ_END(head)) \
(head).cqh_last = (elm2); \
else \
(elm2)->field.cqe_next->field.cqe_prev = (elm2); \
if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
CIRCLEQ_END(head)) \
(head).cqh_first = (elm2); \
else \
(elm2)->field.cqe_prev->field.cqe_next = (elm2); \
} while (0)
#endif /* !_SYS_QUEUE_H_ */

387
libevent/configure.in Normal file
View File

@ -0,0 +1,387 @@
dnl configure.in for libevent
dnl Dug Song <dugsong@monkey.org>
AC_INIT(event.c)
AM_INIT_AUTOMAKE(libevent,1.4.12-stable)
AM_CONFIG_HEADER(config.h)
dnl AM_MAINTAINER_MODE
dnl Initialize prefix.
if test "$prefix" = "NONE"; then
prefix="/usr/local"
fi
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_GCC_TRADITIONAL
if test "$GCC" = yes ; then
CFLAGS="$CFLAGS -Wall"
# And disable the strict-aliasing optimization, since it breaks
# our sockaddr-handling code in strange ways.
CFLAGS="$CFLAGS -fno-strict-aliasing"
fi
AC_ARG_ENABLE(gcc-warnings,
AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings with GCC))
AC_PROG_LIBTOOL
dnl Uncomment "AC_DISABLE_SHARED" to make shared librraries not get
dnl built by default. You can also turn shared libs on and off from
dnl the command line with --enable-shared and --disable-shared.
dnl AC_DISABLE_SHARED
AC_SUBST(LIBTOOL_DEPS)
dnl Checks for libraries.
AC_CHECK_LIB(socket, socket)
AC_CHECK_LIB(resolv, inet_aton)
AC_CHECK_LIB(rt, clock_gettime)
AC_CHECK_LIB(nsl, inet_ntoa)
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h sys/param.h sys/ioctl.h sys/select.h sys/devpoll.h port.h netinet/in6.h sys/socket.h)
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
AC_EGREP_CPP(yes,
[
#include <sys/queue.h>
#ifdef TAILQ_FOREACH
yes
#endif
], [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TAILQFOREACH, 1,
[Define if TAILQ_FOREACH is defined in <sys/queue.h>])],
AC_MSG_RESULT(no)
)
fi
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
AC_MSG_CHECKING(for timeradd in sys/time.h)
AC_EGREP_CPP(yes,
[
#include <sys/time.h>
#ifdef timeradd
yes
#endif
], [ AC_DEFINE(HAVE_TIMERADD, 1,
[Define if timeradd is defined in <sys/time.h>])
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
)
fi
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
AC_MSG_CHECKING(for timercmp in sys/time.h)
AC_EGREP_CPP(yes,
[
#include <sys/time.h>
#ifdef timercmp
yes
#endif
], [ AC_DEFINE(HAVE_TIMERCMP, 1,
[Define if timercmp is defined in <sys/time.h>])
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
)
fi
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
AC_MSG_CHECKING(for timerclear in sys/time.h)
AC_EGREP_CPP(yes,
[
#include <sys/time.h>
#ifdef timerclear
yes
#endif
], [ AC_DEFINE(HAVE_TIMERCLEAR, 1,
[Define if timerclear is defined in <sys/time.h>])
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
)
fi
if test "x$ac_cv_header_sys_time_h" = "xyes"; then
AC_MSG_CHECKING(for timerisset in sys/time.h)
AC_EGREP_CPP(yes,
[
#include <sys/time.h>
#ifdef timerisset
yes
#endif
], [ AC_DEFINE(HAVE_TIMERISSET, 1,
[Define if timerisset is defined in <sys/time.h>])
AC_MSG_RESULT(yes)] ,AC_MSG_RESULT(no)
)
fi
dnl - check if the macro WIN32 is defined on this compiler.
dnl - (this is how we check for a windows version of GCC)
AC_MSG_CHECKING(for WIN32)
AC_TRY_COMPILE(,
[
#ifndef WIN32
die horribly
#endif
],
bwin32=true; AC_MSG_RESULT(yes),
bwin32=false; AC_MSG_RESULT(no),
)
AM_CONDITIONAL(BUILD_WIN32, test x$bwin32 = xtrue)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_HEADER_TIME
dnl Checks for library functions.
AC_CHECK_FUNCS(gettimeofday vasprintf fcntl clock_gettime strtok_r strsep getaddrinfo getnameinfo strlcpy inet_ntop signal sigaction strtoll)
AC_CHECK_SIZEOF(long)
if test "x$ac_cv_func_clock_gettime" = "xyes"; then
AC_DEFINE(DNS_USE_CPU_CLOCK_FOR_ID, 1, [Define if clock_gettime is available in libc])
else
AC_DEFINE(DNS_USE_GETTIMEOFDAY_FOR_ID, 1, [Define is no secure id variant is available])
fi
AC_MSG_CHECKING(for F_SETFD in fcntl.h)
AC_EGREP_CPP(yes,
[
#define _GNU_SOURCE
#include <fcntl.h>
#ifdef F_SETFD
yes
#endif
], [ AC_DEFINE(HAVE_SETFD, 1,
[Define if F_SETFD is defined in <fcntl.h>])
AC_MSG_RESULT(yes) ], AC_MSG_RESULT(no))
needsignal=no
haveselect=no
AC_CHECK_FUNCS(select, [haveselect=yes], )
if test "x$haveselect" = "xyes" ; then
AC_LIBOBJ(select)
needsignal=yes
fi
havepoll=no
AC_CHECK_FUNCS(poll, [havepoll=yes], )
if test "x$havepoll" = "xyes" ; then
AC_LIBOBJ(poll)
needsignal=yes
fi
haveepoll=no
AC_CHECK_FUNCS(epoll_ctl, [haveepoll=yes], )
if test "x$haveepoll" = "xyes" ; then
AC_DEFINE(HAVE_EPOLL, 1,
[Define if your system supports the epoll system calls])
AC_LIBOBJ(epoll)
needsignal=yes
fi
havedevpoll=no
if test "x$ac_cv_header_sys_devpoll_h" = "xyes"; then
AC_DEFINE(HAVE_DEVPOLL, 1,
[Define if /dev/poll is available])
AC_LIBOBJ(devpoll)
fi
havekqueue=no
if test "x$ac_cv_header_sys_event_h" = "xyes"; then
AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
if test "x$havekqueue" = "xyes" ; then
AC_MSG_CHECKING(for working kqueue)
AC_TRY_RUN(
#include <sys/types.h>
#include <sys/time.h>
#include <sys/event.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int
main(int argc, char **argv)
{
int kq;
int n;
int fd[[2]];
struct kevent ev;
struct timespec ts;
char buf[[8000]];
if (pipe(fd) == -1)
exit(1);
if (fcntl(fd[[1]], F_SETFL, O_NONBLOCK) == -1)
exit(1);
while ((n = write(fd[[1]], buf, sizeof(buf))) == sizeof(buf))
;
if ((kq = kqueue()) == -1)
exit(1);
ev.ident = fd[[1]];
ev.filter = EVFILT_WRITE;
ev.flags = EV_ADD | EV_ENABLE;
n = kevent(kq, &ev, 1, NULL, 0, NULL);
if (n == -1)
exit(1);
read(fd[[0]], buf, sizeof(buf));
ts.tv_sec = 0;
ts.tv_nsec = 0;
n = kevent(kq, NULL, 0, &ev, 1, &ts);
if (n == -1 || n == 0)
exit(1);
exit(0);
}, [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_WORKING_KQUEUE, 1,
[Define if kqueue works correctly with pipes])
AC_LIBOBJ(kqueue)], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
fi
fi
haveepollsyscall=no
if test "x$ac_cv_header_sys_epoll_h" = "xyes"; then
if test "x$haveepoll" = "xno" ; then
AC_MSG_CHECKING(for epoll system call)
AC_TRY_RUN(
#include <stdint.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/epoll.h>
#include <unistd.h>
int
epoll_create(int size)
{
return (syscall(__NR_epoll_create, size));
}
int
main(int argc, char **argv)
{
int epfd;
epfd = epoll_create(256);
exit (epfd == -1 ? 1 : 0);
}, [AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_EPOLL, 1,
[Define if your system supports the epoll system calls])
needsignal=yes
AC_LIBOBJ(epoll_sub)
AC_LIBOBJ(epoll)], AC_MSG_RESULT(no), AC_MSG_RESULT(no))
fi
fi
haveeventports=no
AC_CHECK_FUNCS(port_create, [haveeventports=yes], )
if test "x$haveeventports" = "xyes" ; then
AC_DEFINE(HAVE_EVENT_PORTS, 1,
[Define if your system supports event ports])
AC_LIBOBJ(evport)
needsignal=yes
fi
if test "x$bwin32" = "xtrue"; then
needsignal=yes
fi
if test "x$bwin32" = "xtrue"; then
needsignal=yes
fi
if test "x$needsignal" = "xyes" ; then
AC_LIBOBJ(signal)
fi
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_CHECK_TYPES([uint64_t, uint32_t, uint16_t, uint8_t], , ,
[#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
#include <inttypes.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif])
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(short)
AC_CHECK_TYPES([struct in6_addr], , ,
[#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif])
AC_MSG_CHECKING([for socklen_t])
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>],
[socklen_t x;],
AC_MSG_RESULT([yes]),
[AC_MSG_RESULT([no])
AC_DEFINE(socklen_t, unsigned int,
[Define to unsigned int if you dont have it])]
)
AC_MSG_CHECKING([whether our compiler supports __func__])
AC_TRY_COMPILE([],
[ const char *cp = __func__; ],
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
AC_MSG_CHECKING([whether our compiler supports __FUNCTION__])
AC_TRY_COMPILE([],
[ const char *cp = __FUNCTION__; ],
AC_MSG_RESULT([yes])
AC_DEFINE(__func__, __FUNCTION__,
[Define to appropriate substitue if compiler doesnt have __func__]),
AC_MSG_RESULT([no])
AC_DEFINE(__func__, __FILE__,
[Define to appropriate substitue if compiler doesnt have __func__])))
# Add some more warnings which we use in development but not in the
# released versions. (Some relevant gcc versions can't handle these.)
if test x$enable_gcc_warnings = xyes; then
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
#if !defined(__GNUC__) || (__GNUC__ < 4)
#error
#endif]), have_gcc4=yes, have_gcc4=no)
AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
#error
#endif]), have_gcc42=yes, have_gcc42=no)
CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
CFLAGS="$CFLAGS -Wno-unused-parameter -Wno-sign-compare -Wstrict-aliasing"
if test x$have_gcc4 = xyes ; then
# These warnings break gcc 3.3.5 and work on gcc 4.0.2
CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement"
#CFLAGS="$CFLAGS -Wold-style-definition"
fi
if test x$have_gcc42 = xyes ; then
# These warnings break gcc 4.0.2 and work on gcc 4.2
CFLAGS="$CFLAGS -Waddress -Wnormalized=id -Woverride-init"
fi
##This will break the world on some 64-bit architectures
# CFLAGS="$CFLAGS -Winline"
fi
AC_OUTPUT(Makefile test/Makefile sample/Makefile)

417
libevent/devpoll.c Normal file
View File

@ -0,0 +1,417 @@
/*
* Copyright 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/types.h>
#include <sys/resource.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <sys/_time.h>
#endif
#include <sys/queue.h>
#include <sys/devpoll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include "event.h"
#include "event-internal.h"
#include "evsignal.h"
#include "log.h"
/* due to limitations in the devpoll interface, we need to keep track of
* all file descriptors outself.
*/
struct evdevpoll {
struct event *evread;
struct event *evwrite;
};
struct devpollop {
struct evdevpoll *fds;
int nfds;
struct pollfd *events;
int nevents;
int dpfd;
struct pollfd *changes;
int nchanges;
};
static void *devpoll_init (struct event_base *);
static int devpoll_add (void *, struct event *);
static int devpoll_del (void *, struct event *);
static int devpoll_dispatch (struct event_base *, void *, struct timeval *);
static void devpoll_dealloc (struct event_base *, void *);
const struct eventop devpollops = {
"devpoll",
devpoll_init,
devpoll_add,
devpoll_del,
devpoll_dispatch,
devpoll_dealloc,
1 /* need reinit */
};
#define NEVENT 32000
static int
devpoll_commit(struct devpollop *devpollop)
{
/*
* Due to a bug in Solaris, we have to use pwrite with an offset of 0.
* Write is limited to 2GB of data, until it will fail.
*/
if (pwrite(devpollop->dpfd, devpollop->changes,
sizeof(struct pollfd) * devpollop->nchanges, 0) == -1)
return(-1);
devpollop->nchanges = 0;
return(0);
}
static int
devpoll_queue(struct devpollop *devpollop, int fd, int events) {
struct pollfd *pfd;
if (devpollop->nchanges >= devpollop->nevents) {
/*
* Change buffer is full, must commit it to /dev/poll before
* adding more
*/
if (devpoll_commit(devpollop) != 0)
return(-1);
}
pfd = &devpollop->changes[devpollop->nchanges++];
pfd->fd = fd;
pfd->events = events;
pfd->revents = 0;
return(0);
}
static void *
devpoll_init(struct event_base *base)
{
int dpfd, nfiles = NEVENT;
struct rlimit rl;
struct devpollop *devpollop;
/* Disable devpoll when this environment variable is set */
if (getenv("EVENT_NODEVPOLL"))
return (NULL);
if (!(devpollop = calloc(1, sizeof(struct devpollop))))
return (NULL);
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
rl.rlim_cur != RLIM_INFINITY)
nfiles = rl.rlim_cur;
/* Initialize the kernel queue */
if ((dpfd = open("/dev/poll", O_RDWR)) == -1) {
event_warn("open: /dev/poll");
free(devpollop);
return (NULL);
}
devpollop->dpfd = dpfd;
/* Initialize fields */
devpollop->events = calloc(nfiles, sizeof(struct pollfd));
if (devpollop->events == NULL) {
free(devpollop);
close(dpfd);
return (NULL);
}
devpollop->nevents = nfiles;
devpollop->fds = calloc(nfiles, sizeof(struct evdevpoll));
if (devpollop->fds == NULL) {
free(devpollop->events);
free(devpollop);
close(dpfd);
return (NULL);
}
devpollop->nfds = nfiles;
devpollop->changes = calloc(nfiles, sizeof(struct pollfd));
if (devpollop->changes == NULL) {
free(devpollop->fds);
free(devpollop->events);
free(devpollop);
close(dpfd);
return (NULL);
}
evsignal_init(base);
return (devpollop);
}
static int
devpoll_recalc(struct event_base *base, void *arg, int max)
{
struct devpollop *devpollop = arg;
if (max >= devpollop->nfds) {
struct evdevpoll *fds;
int nfds;
nfds = devpollop->nfds;
while (nfds <= max)
nfds <<= 1;
fds = realloc(devpollop->fds, nfds * sizeof(struct evdevpoll));
if (fds == NULL) {
event_warn("realloc");
return (-1);
}
devpollop->fds = fds;
memset(fds + devpollop->nfds, 0,
(nfds - devpollop->nfds) * sizeof(struct evdevpoll));
devpollop->nfds = nfds;
}
return (0);
}
static int
devpoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
struct devpollop *devpollop = arg;
struct pollfd *events = devpollop->events;
struct dvpoll dvp;
struct evdevpoll *evdp;
int i, res, timeout = -1;
if (devpollop->nchanges)
devpoll_commit(devpollop);
if (tv != NULL)
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
dvp.dp_fds = devpollop->events;
dvp.dp_nfds = devpollop->nevents;
dvp.dp_timeout = timeout;
res = ioctl(devpollop->dpfd, DP_POLL, &dvp);
if (res == -1) {
if (errno != EINTR) {
event_warn("ioctl: DP_POLL");
return (-1);
}
evsignal_process(base);
return (0);
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: devpoll_wait reports %d", __func__, res));
for (i = 0; i < res; i++) {
int which = 0;
int what = events[i].revents;
struct event *evread = NULL, *evwrite = NULL;
assert(events[i].fd < devpollop->nfds);
evdp = &devpollop->fds[events[i].fd];
if (what & POLLHUP)
what |= POLLIN | POLLOUT;
else if (what & POLLERR)
what |= POLLIN | POLLOUT;
if (what & POLLIN) {
evread = evdp->evread;
which |= EV_READ;
}
if (what & POLLOUT) {
evwrite = evdp->evwrite;
which |= EV_WRITE;
}
if (!which)
continue;
if (evread != NULL && !(evread->ev_events & EV_PERSIST))
event_del(evread);
if (evwrite != NULL && evwrite != evread &&
!(evwrite->ev_events & EV_PERSIST))
event_del(evwrite);
if (evread != NULL)
event_active(evread, EV_READ, 1);
if (evwrite != NULL)
event_active(evwrite, EV_WRITE, 1);
}
return (0);
}
static int
devpoll_add(void *arg, struct event *ev)
{
struct devpollop *devpollop = arg;
struct evdevpoll *evdp;
int fd, events;
if (ev->ev_events & EV_SIGNAL)
return (evsignal_add(ev));
fd = ev->ev_fd;
if (fd >= devpollop->nfds) {
/* Extend the file descriptor array as necessary */
if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
return (-1);
}
evdp = &devpollop->fds[fd];
/*
* It's not necessary to OR the existing read/write events that we
* are currently interested in with the new event we are adding.
* The /dev/poll driver ORs any new events with the existing events
* that it has cached for the fd.
*/
events = 0;
if (ev->ev_events & EV_READ) {
if (evdp->evread && evdp->evread != ev) {
/* There is already a different read event registered */
return(-1);
}
events |= POLLIN;
}
if (ev->ev_events & EV_WRITE) {
if (evdp->evwrite && evdp->evwrite != ev) {
/* There is already a different write event registered */
return(-1);
}
events |= POLLOUT;
}
if (devpoll_queue(devpollop, fd, events) != 0)
return(-1);
/* Update events responsible */
if (ev->ev_events & EV_READ)
evdp->evread = ev;
if (ev->ev_events & EV_WRITE)
evdp->evwrite = ev;
return (0);
}
static int
devpoll_del(void *arg, struct event *ev)
{
struct devpollop *devpollop = arg;
struct evdevpoll *evdp;
int fd, events;
int needwritedelete = 1, needreaddelete = 1;
if (ev->ev_events & EV_SIGNAL)
return (evsignal_del(ev));
fd = ev->ev_fd;
if (fd >= devpollop->nfds)
return (0);
evdp = &devpollop->fds[fd];
events = 0;
if (ev->ev_events & EV_READ)
events |= POLLIN;
if (ev->ev_events & EV_WRITE)
events |= POLLOUT;
/*
* The only way to remove an fd from the /dev/poll monitored set is
* to use POLLREMOVE by itself. This removes ALL events for the fd
* provided so if we care about two events and are only removing one
* we must re-add the other event after POLLREMOVE.
*/
if (devpoll_queue(devpollop, fd, POLLREMOVE) != 0)
return(-1);
if ((events & (POLLIN|POLLOUT)) != (POLLIN|POLLOUT)) {
/*
* We're not deleting all events, so we must resubmit the
* event that we are still interested in if one exists.
*/
if ((events & POLLIN) && evdp->evwrite != NULL) {
/* Deleting read, still care about write */
devpoll_queue(devpollop, fd, POLLOUT);
needwritedelete = 0;
} else if ((events & POLLOUT) && evdp->evread != NULL) {
/* Deleting write, still care about read */
devpoll_queue(devpollop, fd, POLLIN);
needreaddelete = 0;
}
}
if (needreaddelete)
evdp->evread = NULL;
if (needwritedelete)
evdp->evwrite = NULL;
return (0);
}
static void
devpoll_dealloc(struct event_base *base, void *arg)
{
struct devpollop *devpollop = arg;
evsignal_dealloc(base);
if (devpollop->fds)
free(devpollop->fds);
if (devpollop->events)
free(devpollop->events);
if (devpollop->changes)
free(devpollop->changes);
if (devpollop->dpfd >= 0)
close(devpollop->dpfd);
memset(devpollop, 0, sizeof(struct devpollop));
free(devpollop);
}

373
libevent/epoll.c Normal file
View File

@ -0,0 +1,373 @@
/*
* Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdint.h>
#include <sys/types.h>
#include <sys/resource.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <sys/_time.h>
#endif
#include <sys/queue.h>
#include <sys/epoll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "event.h"
#include "event-internal.h"
#include "evsignal.h"
#include "log.h"
/* due to limitations in the epoll interface, we need to keep track of
* all file descriptors outself.
*/
struct evepoll {
struct event *evread;
struct event *evwrite;
};
struct epollop {
struct evepoll *fds;
int nfds;
struct epoll_event *events;
int nevents;
int epfd;
};
static void *epoll_init (struct event_base *);
static int epoll_add (void *, struct event *);
static int epoll_del (void *, struct event *);
static int epoll_dispatch (struct event_base *, void *, struct timeval *);
static void epoll_dealloc (struct event_base *, void *);
const struct eventop epollops = {
"epoll",
epoll_init,
epoll_add,
epoll_del,
epoll_dispatch,
epoll_dealloc,
1 /* need reinit */
};
#ifdef HAVE_SETFD
#define FD_CLOSEONEXEC(x) do { \
if (fcntl(x, F_SETFD, 1) == -1) \
event_warn("fcntl(%d, F_SETFD)", x); \
} while (0)
#else
#define FD_CLOSEONEXEC(x)
#endif
#define NEVENT 32000
/* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
* values bigger than (LONG_MAX - 999ULL)/HZ. HZ in the wild can be
* as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
* largest number of msec we can support here is 2147482. Let's
* round that down by 47 seconds.
*/
#define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
static void *
epoll_init(struct event_base *base)
{
int epfd, nfiles = NEVENT;
struct rlimit rl;
struct epollop *epollop;
/* Disable epollueue when this environment variable is set */
if (getenv("EVENT_NOEPOLL"))
return (NULL);
if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
rl.rlim_cur != RLIM_INFINITY) {
/*
* Solaris is somewhat retarded - it's important to drop
* backwards compatibility when making changes. So, don't
* dare to put rl.rlim_cur here.
*/
nfiles = rl.rlim_cur - 1;
}
/* Initalize the kernel queue */
if ((epfd = epoll_create(nfiles)) == -1) {
if (errno != ENOSYS)
event_warn("epoll_create");
return (NULL);
}
FD_CLOSEONEXEC(epfd);
if (!(epollop = calloc(1, sizeof(struct epollop))))
return (NULL);
epollop->epfd = epfd;
/* Initalize fields */
epollop->events = malloc(nfiles * sizeof(struct epoll_event));
if (epollop->events == NULL) {
free(epollop);
return (NULL);
}
epollop->nevents = nfiles;
epollop->fds = calloc(nfiles, sizeof(struct evepoll));
if (epollop->fds == NULL) {
free(epollop->events);
free(epollop);
return (NULL);
}
epollop->nfds = nfiles;
evsignal_init(base);
return (epollop);
}
static int
epoll_recalc(struct event_base *base, void *arg, int max)
{
struct epollop *epollop = arg;
if (max >= epollop->nfds) {
struct evepoll *fds;
int nfds;
nfds = epollop->nfds;
while (nfds <= max)
nfds <<= 1;
fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
if (fds == NULL) {
event_warn("realloc");
return (-1);
}
epollop->fds = fds;
memset(fds + epollop->nfds, 0,
(nfds - epollop->nfds) * sizeof(struct evepoll));
epollop->nfds = nfds;
}
return (0);
}
static int
epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
struct epollop *epollop = arg;
struct epoll_event *events = epollop->events;
struct evepoll *evep;
int i, res, timeout = -1;
if (tv != NULL)
timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
/* Linux kernels can wait forever if the timeout is too big;
* see comment on MAX_EPOLL_TIMEOUT_MSEC. */
timeout = MAX_EPOLL_TIMEOUT_MSEC;
}
res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
if (res == -1) {
if (errno != EINTR) {
event_warn("epoll_wait");
return (-1);
}
evsignal_process(base);
return (0);
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: epoll_wait reports %d", __func__, res));
for (i = 0; i < res; i++) {
int what = events[i].events;
struct event *evread = NULL, *evwrite = NULL;
int fd = events[i].data.fd;
if (fd < 0 || fd >= epollop->nfds)
continue;
evep = &epollop->fds[fd];
if (what & (EPOLLHUP|EPOLLERR)) {
evread = evep->evread;
evwrite = evep->evwrite;
} else {
if (what & EPOLLIN) {
evread = evep->evread;
}
if (what & EPOLLOUT) {
evwrite = evep->evwrite;
}
}
if (!(evread||evwrite))
continue;
if (evread != NULL)
event_active(evread, EV_READ, 1);
if (evwrite != NULL)
event_active(evwrite, EV_WRITE, 1);
}
return (0);
}
static int
epoll_add(void *arg, struct event *ev)
{
struct epollop *epollop = arg;
struct epoll_event epev = {0, {0}};
struct evepoll *evep;
int fd, op, events;
if (ev->ev_events & EV_SIGNAL)
return (evsignal_add(ev));
fd = ev->ev_fd;
if (fd >= epollop->nfds) {
/* Extent the file descriptor array as necessary */
if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
return (-1);
}
evep = &epollop->fds[fd];
op = EPOLL_CTL_ADD;
events = 0;
if (evep->evread != NULL) {
events |= EPOLLIN;
op = EPOLL_CTL_MOD;
}
if (evep->evwrite != NULL) {
events |= EPOLLOUT;
op = EPOLL_CTL_MOD;
}
if (ev->ev_events & EV_READ)
events |= EPOLLIN;
if (ev->ev_events & EV_WRITE)
events |= EPOLLOUT;
epev.data.fd = fd;
epev.events = events;
if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
return (-1);
/* Update events responsible */
if (ev->ev_events & EV_READ)
evep->evread = ev;
if (ev->ev_events & EV_WRITE)
evep->evwrite = ev;
return (0);
}
static int
epoll_del(void *arg, struct event *ev)
{
struct epollop *epollop = arg;
struct epoll_event epev = {0, {0}};
struct evepoll *evep;
int fd, events, op;
int needwritedelete = 1, needreaddelete = 1;
if (ev->ev_events & EV_SIGNAL)
return (evsignal_del(ev));
fd = ev->ev_fd;
if (fd >= epollop->nfds)
return (0);
evep = &epollop->fds[fd];
op = EPOLL_CTL_DEL;
events = 0;
if (ev->ev_events & EV_READ)
events |= EPOLLIN;
if (ev->ev_events & EV_WRITE)
events |= EPOLLOUT;
if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
if ((events & EPOLLIN) && evep->evwrite != NULL) {
needwritedelete = 0;
events = EPOLLOUT;
op = EPOLL_CTL_MOD;
} else if ((events & EPOLLOUT) && evep->evread != NULL) {
needreaddelete = 0;
events = EPOLLIN;
op = EPOLL_CTL_MOD;
}
}
epev.events = events;
epev.data.fd = fd;
if (needreaddelete)
evep->evread = NULL;
if (needwritedelete)
evep->evwrite = NULL;
if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
return (-1);
return (0);
}
static void
epoll_dealloc(struct event_base *base, void *arg)
{
struct epollop *epollop = arg;
evsignal_dealloc(base);
if (epollop->fds)
free(epollop->fds);
if (epollop->events)
free(epollop->events);
if (epollop->epfd >= 0)
close(epollop->epfd);
memset(epollop, 0, sizeof(struct epollop));
free(epollop);
}

52
libevent/epoll_sub.c Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright 2003 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdint.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/epoll.h>
#include <unistd.h>
int
epoll_create(int size)
{
return (syscall(__NR_epoll_create, size));
}
int
epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
return (syscall(__NR_epoll_ctl, epfd, op, fd, event));
}
int
epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout)
{
return (syscall(__NR_epoll_wait, epfd, events, maxevents, timeout));
}

455
libevent/evbuffer.c Normal file
View File

@ -0,0 +1,455 @@
/*
* Copyright (c) 2002-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef WIN32
#include <winsock2.h>
#endif
#include "evutil.h"
#include "event.h"
/* prototypes */
void bufferevent_read_pressure_cb(struct evbuffer *, size_t, size_t, void *);
static int
bufferevent_add(struct event *ev, int timeout)
{
struct timeval tv, *ptv = NULL;
if (timeout) {
evutil_timerclear(&tv);
tv.tv_sec = timeout;
ptv = &tv;
}
return (event_add(ev, ptv));
}
/*
* This callback is executed when the size of the input buffer changes.
* We use it to apply back pressure on the reading side.
*/
void
bufferevent_read_pressure_cb(struct evbuffer *buf, size_t old, size_t now,
void *arg) {
struct bufferevent *bufev = arg;
/*
* If we are below the watermark then reschedule reading if it's
* still enabled.
*/
if (bufev->wm_read.high == 0 || now < bufev->wm_read.high) {
evbuffer_setcb(buf, NULL, NULL);
if (bufev->enabled & EV_READ)
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
}
}
static void
bufferevent_readcb(int fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
int res = 0;
short what = EVBUFFER_READ;
size_t len;
int howmuch = -1;
if (event == EV_TIMEOUT) {
what |= EVBUFFER_TIMEOUT;
goto error;
}
/*
* If we have a high watermark configured then we don't want to
* read more data than would make us reach the watermark.
*/
if (bufev->wm_read.high != 0) {
howmuch = bufev->wm_read.high - EVBUFFER_LENGTH(bufev->input);
/* we might have lowered the watermark, stop reading */
if (howmuch <= 0) {
struct evbuffer *buf = bufev->input;
event_del(&bufev->ev_read);
evbuffer_setcb(buf,
bufferevent_read_pressure_cb, bufev);
return;
}
}
res = evbuffer_read(bufev->input, fd, howmuch);
if (res == -1) {
if (errno == EAGAIN || errno == EINTR)
goto reschedule;
/* error case */
what |= EVBUFFER_ERROR;
} else if (res == 0) {
/* eof case */
what |= EVBUFFER_EOF;
}
if (res <= 0)
goto error;
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
/* See if this callbacks meets the water marks */
len = EVBUFFER_LENGTH(bufev->input);
if (bufev->wm_read.low != 0 && len < bufev->wm_read.low)
return;
if (bufev->wm_read.high != 0 && len >= bufev->wm_read.high) {
struct evbuffer *buf = bufev->input;
event_del(&bufev->ev_read);
/* Now schedule a callback for us when the buffer changes */
evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
}
/* Invoke the user callback - must always be called last */
if (bufev->readcb != NULL)
(*bufev->readcb)(bufev, bufev->cbarg);
return;
reschedule:
bufferevent_add(&bufev->ev_read, bufev->timeout_read);
return;
error:
(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
static void
bufferevent_writecb(int fd, short event, void *arg)
{
struct bufferevent *bufev = arg;
int res = 0;
short what = EVBUFFER_WRITE;
if (event == EV_TIMEOUT) {
what |= EVBUFFER_TIMEOUT;
goto error;
}
if (EVBUFFER_LENGTH(bufev->output)) {
res = evbuffer_write(bufev->output, fd);
if (res == -1) {
#ifndef WIN32
/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
*set errno. thus this error checking is not portable*/
if (errno == EAGAIN ||
errno == EINTR ||
errno == EINPROGRESS)
goto reschedule;
/* error case */
what |= EVBUFFER_ERROR;
#else
goto reschedule;
#endif
} else if (res == 0) {
/* eof case */
what |= EVBUFFER_EOF;
}
if (res <= 0)
goto error;
}
if (EVBUFFER_LENGTH(bufev->output) != 0)
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
/*
* Invoke the user callback if our buffer is drained or below the
* low watermark.
*/
if (bufev->writecb != NULL &&
EVBUFFER_LENGTH(bufev->output) <= bufev->wm_write.low)
(*bufev->writecb)(bufev, bufev->cbarg);
return;
reschedule:
if (EVBUFFER_LENGTH(bufev->output) != 0)
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
return;
error:
(*bufev->errorcb)(bufev, what, bufev->cbarg);
}
/*
* Create a new buffered event object.
*
* The read callback is invoked whenever we read new data.
* The write callback is invoked whenever the output buffer is drained.
* The error callback is invoked on a write/read error or on EOF.
*
* Both read and write callbacks maybe NULL. The error callback is not
* allowed to be NULL and have to be provided always.
*/
struct bufferevent *
bufferevent_new(int fd, evbuffercb readcb, evbuffercb writecb,
everrorcb errorcb, void *cbarg)
{
struct bufferevent *bufev;
if ((bufev = calloc(1, sizeof(struct bufferevent))) == NULL)
return (NULL);
if ((bufev->input = evbuffer_new()) == NULL) {
free(bufev);
return (NULL);
}
if ((bufev->output = evbuffer_new()) == NULL) {
evbuffer_free(bufev->input);
free(bufev);
return (NULL);
}
event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
bufferevent_setcb(bufev, readcb, writecb, errorcb, cbarg);
/*
* Set to EV_WRITE so that using bufferevent_write is going to
* trigger a callback. Reading needs to be explicitly enabled
* because otherwise no data will be available.
*/
bufev->enabled = EV_WRITE;
return (bufev);
}
void
bufferevent_setcb(struct bufferevent *bufev,
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg)
{
bufev->readcb = readcb;
bufev->writecb = writecb;
bufev->errorcb = errorcb;
bufev->cbarg = cbarg;
}
void
bufferevent_setfd(struct bufferevent *bufev, int fd)
{
event_del(&bufev->ev_read);
event_del(&bufev->ev_write);
event_set(&bufev->ev_read, fd, EV_READ, bufferevent_readcb, bufev);
event_set(&bufev->ev_write, fd, EV_WRITE, bufferevent_writecb, bufev);
if (bufev->ev_base != NULL) {
event_base_set(bufev->ev_base, &bufev->ev_read);
event_base_set(bufev->ev_base, &bufev->ev_write);
}
/* might have to manually trigger event registration */
}
int
bufferevent_priority_set(struct bufferevent *bufev, int priority)
{
if (event_priority_set(&bufev->ev_read, priority) == -1)
return (-1);
if (event_priority_set(&bufev->ev_write, priority) == -1)
return (-1);
return (0);
}
/* Closing the file descriptor is the responsibility of the caller */
void
bufferevent_free(struct bufferevent *bufev)
{
event_del(&bufev->ev_read);
event_del(&bufev->ev_write);
evbuffer_free(bufev->input);
evbuffer_free(bufev->output);
free(bufev);
}
/*
* Returns 0 on success;
* -1 on failure.
*/
int
bufferevent_write(struct bufferevent *bufev, const void *data, size_t size)
{
int res;
res = evbuffer_add(bufev->output, data, size);
if (res == -1)
return (res);
/* If everything is okay, we need to schedule a write */
if (size > 0 && (bufev->enabled & EV_WRITE))
bufferevent_add(&bufev->ev_write, bufev->timeout_write);
return (res);
}
int
bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf)
{
int res;
res = bufferevent_write(bufev, buf->buffer, buf->off);
if (res != -1)
evbuffer_drain(buf, buf->off);
return (res);
}
size_t
bufferevent_read(struct bufferevent *bufev, void *data, size_t size)
{
struct evbuffer *buf = bufev->input;
if (buf->off < size)
size = buf->off;
/* Copy the available data to the user buffer */
memcpy(data, buf->buffer, size);
if (size)
evbuffer_drain(buf, size);
return (size);
}
int
bufferevent_enable(struct bufferevent *bufev, short event)
{
if (event & EV_READ) {
if (bufferevent_add(&bufev->ev_read, bufev->timeout_read) == -1)
return (-1);
}
if (event & EV_WRITE) {
if (bufferevent_add(&bufev->ev_write, bufev->timeout_write) == -1)
return (-1);
}
bufev->enabled |= event;
return (0);
}
int
bufferevent_disable(struct bufferevent *bufev, short event)
{
if (event & EV_READ) {
if (event_del(&bufev->ev_read) == -1)
return (-1);
}
if (event & EV_WRITE) {
if (event_del(&bufev->ev_write) == -1)
return (-1);
}
bufev->enabled &= ~event;
return (0);
}
/*
* Sets the read and write timeout for a buffered event.
*/
void
bufferevent_settimeout(struct bufferevent *bufev,
int timeout_read, int timeout_write) {
bufev->timeout_read = timeout_read;
bufev->timeout_write = timeout_write;
if (event_pending(&bufev->ev_read, EV_READ, NULL))
bufferevent_add(&bufev->ev_read, timeout_read);
if (event_pending(&bufev->ev_write, EV_WRITE, NULL))
bufferevent_add(&bufev->ev_write, timeout_write);
}
/*
* Sets the water marks
*/
void
bufferevent_setwatermark(struct bufferevent *bufev, short events,
size_t lowmark, size_t highmark)
{
if (events & EV_READ) {
bufev->wm_read.low = lowmark;
bufev->wm_read.high = highmark;
}
if (events & EV_WRITE) {
bufev->wm_write.low = lowmark;
bufev->wm_write.high = highmark;
}
/* If the watermarks changed then see if we should call read again */
bufferevent_read_pressure_cb(bufev->input,
0, EVBUFFER_LENGTH(bufev->input), bufev);
}
int
bufferevent_base_set(struct event_base *base, struct bufferevent *bufev)
{
int res;
bufev->ev_base = base;
res = event_base_set(base, &bufev->ev_read);
if (res == -1)
return (res);
res = event_base_set(base, &bufev->ev_write);
return (res);
}

322
libevent/evdns.3 Normal file
View File

@ -0,0 +1,322 @@
.\"
.\" Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd October 7, 2006
.Dt EVDNS 3
.Os
.Sh NAME
.Nm evdns_init
.Nm evdns_shutdown
.Nm evdns_err_to_string
.Nm evdns_nameserver_add
.Nm evdns_count_nameservers
.Nm evdns_clear_nameservers_and_suspend
.Nm evdns_resume
.Nm evdns_nameserver_ip_add
.Nm evdns_resolve_ipv4
.Nm evdns_resolve_reverse
.Nm evdns_resolv_conf_parse
.Nm evdns_config_windows_nameservers
.Nm evdns_search_clear
.Nm evdns_search_add
.Nm evdns_search_ndots_set
.Nm evdns_set_log_fn
.Nd asynchronous functions for DNS resolution.
.Sh SYNOPSIS
.Fd #include <sys/time.h>
.Fd #include <event.h>
.Fd #include <evdns.h>
.Ft int
.Fn evdns_init
.Ft void
.Fn evdns_shutdown "int fail_requests"
.Ft "const char *"
.Fn evdns_err_to_string "int err"
.Ft int
.Fn evdns_nameserver_add "unsigned long int address"
.Ft int
.Fn evdns_count_nameservers
.Ft int
.Fn evdns_clear_nameservers_and_suspend
.Ft int
.Fn evdns_resume
.Ft int
.Fn evdns_nameserver_ip_add(const char *ip_as_string);
.Ft int
.Fn evdns_resolve_ipv4 "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
.Ft int
.Fn evdns_resolve_reverse "struct in_addr *in" "int flags" "evdns_callback_type callback" "void *ptr"
.Ft int
.Fn evdns_resolv_conf_parse "int flags" "const char *"
.Ft void
.Fn evdns_search_clear
.Ft void
.Fn evdns_search_add "const char *domain"
.Ft void
.Fn evdns_search_ndots_set "const int ndots"
.Ft void
.Fn evdns_set_log_fn "evdns_debug_log_fn_type fn"
.Ft int
.Fn evdns_config_windows_nameservers
.Sh DESCRIPTION
Welcome, gentle reader
.Pp
Async DNS lookups are really a whole lot harder than they should be,
mostly stemming from the fact that the libc resolver has never been
very good at them. Before you use this library you should see if libc
can do the job for you with the modern async call getaddrinfo_a
(see http://www.imperialviolet.org/page25.html#e498). Otherwise,
please continue.
.Pp
This code is based on libevent and you must call event_init before
any of the APIs in this file. You must also seed the OpenSSL random
source if you are using OpenSSL for ids (see below).
.Pp
This library is designed to be included and shipped with your source
code. You statically link with it. You should also test for the
existence of strtok_r and define HAVE_STRTOK_R if you have it.
.Pp
The DNS protocol requires a good source of id numbers and these
numbers should be unpredictable for spoofing reasons. There are
three methods for generating them here and you must define exactly
one of them. In increasing order of preference:
.Pp
.Bl -tag -width "DNS_USE_GETTIMEOFDAY_FOR_ID" -compact -offset indent
.It DNS_USE_GETTIMEOFDAY_FOR_ID
Using the bottom 16 bits of the usec result from gettimeofday. This
is a pretty poor solution but should work anywhere.
.It DNS_USE_CPU_CLOCK_FOR_ID
Using the bottom 16 bits of the nsec result from the CPU's time
counter. This is better, but may not work everywhere. Requires
POSIX realtime support and you'll need to link against -lrt on
glibc systems at least.
.It DNS_USE_OPENSSL_FOR_ID
Uses the OpenSSL RAND_bytes call to generate the data. You must
have seeded the pool before making any calls to this library.
.El
.Pp
The library keeps track of the state of nameservers and will avoid
them when they go down. Otherwise it will round robin between them.
.Pp
Quick start guide:
#include "evdns.h"
void callback(int result, char type, int count, int ttl,
void *addresses, void *arg);
evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
evdns_resolve("www.hostname.com", 0, callback, NULL);
.Pp
When the lookup is complete the callback function is called. The
first argument will be one of the DNS_ERR_* defines in evdns.h.
Hopefully it will be DNS_ERR_NONE, in which case type will be
DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
which the data can be cached for (in seconds), addresses will point
to an array of uint32_t's and arg will be whatever you passed to
evdns_resolve.
.Pp
Searching:
.Pp
In order for this library to be a good replacement for glibc's resolver it
supports searching. This involves setting a list of default domains, in
which names will be queried for. The number of dots in the query name
determines the order in which this list is used.
.Pp
Searching appears to be a single lookup from the point of view of the API,
although many DNS queries may be generated from a single call to
evdns_resolve. Searching can also drastically slow down the resolution
of names.
.Pp
To disable searching:
.Bl -enum -compact -offset indent
.It
Never set it up. If you never call
.Fn evdns_resolv_conf_parse,
.Fn evdns_init,
or
.Fn evdns_search_add
then no searching will occur.
.It
If you do call
.Fn evdns_resolv_conf_parse
then don't pass
.Va DNS_OPTION_SEARCH
(or
.Va DNS_OPTIONS_ALL,
which implies it).
.It
When calling
.Fn evdns_resolve,
pass the
.Va DNS_QUERY_NO_SEARCH
flag.
.El
.Pp
The order of searches depends on the number of dots in the name. If the
number is greater than the ndots setting then the names is first tried
globally. Otherwise each search domain is appended in turn.
.Pp
The ndots setting can either be set from a resolv.conf, or by calling
evdns_search_ndots_set.
.Pp
For example, with ndots set to 1 (the default) and a search domain list of
["myhome.net"]:
Query: www
Order: www.myhome.net, www.
.Pp
Query: www.abc
Order: www.abc., www.abc.myhome.net
.Pp
.Sh API reference
.Pp
.Bl -tag -width 0123456
.It Ft int Fn evdns_init
Initializes support for non-blocking name resolution by calling
.Fn evdns_resolv_conf_parse
on UNIX and
.Fn evdns_config_windows_nameservers
on Windows.
.It Ft int Fn evdns_nameserver_add "unsigned long int address"
Add a nameserver. The address should be an IP address in
network byte order. The type of address is chosen so that
it matches in_addr.s_addr.
Returns non-zero on error.
.It Ft int Fn evdns_nameserver_ip_add "const char *ip_as_string"
This wraps the above function by parsing a string as an IP
address and adds it as a nameserver.
Returns non-zero on error
.It Ft int Fn evdns_resolve "const char *name" "int flags" "evdns_callback_type callback" "void *ptr"
Resolve a name. The name parameter should be a DNS name.
The flags parameter should be 0, or DNS_QUERY_NO_SEARCH
which disables searching for this query. (see defn of
searching above).
.Pp
The callback argument is a function which is called when
this query completes and ptr is an argument which is passed
to that callback function.
.Pp
Returns non-zero on error
.It Ft void Fn evdns_search_clear
Clears the list of search domains
.It Ft void Fn evdns_search_add "const char *domain"
Add a domain to the list of search domains
.It Ft void Fn evdns_search_ndots_set "int ndots"
Set the number of dots which, when found in a name, causes
the first query to be without any search domain.
.It Ft int Fn evdns_count_nameservers "void"
Return the number of configured nameservers (not necessarily the
number of running nameservers). This is useful for double-checking
whether our calls to the various nameserver configuration functions
have been successful.
.It Ft int Fn evdns_clear_nameservers_and_suspend "void"
Remove all currently configured nameservers, and suspend all pending
resolves. Resolves will not necessarily be re-attempted until
evdns_resume() is called.
.It Ft int Fn evdns_resume "void"
Re-attempt resolves left in limbo after an earlier call to
evdns_clear_nameservers_and_suspend().
.It Ft int Fn evdns_config_windows_nameservers "void"
Attempt to configure a set of nameservers based on platform settings on
a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
looks in the registry. Returns 0 on success, nonzero on failure.
.It Ft int Fn evdns_resolv_conf_parse "int flags" "const char *filename"
Parse a resolv.conf like file from the given filename.
.Pp
See the man page for resolv.conf for the format of this file.
The flags argument determines what information is parsed from
this file:
.Bl -tag -width "DNS_OPTION_NAMESERVERS" -offset indent -compact -nested
.It DNS_OPTION_SEARCH
domain, search and ndots options
.It DNS_OPTION_NAMESERVERS
nameserver lines
.It DNS_OPTION_MISC
timeout and attempts options
.It DNS_OPTIONS_ALL
all of the above
.El
.Pp
The following directives are not parsed from the file:
sortlist, rotate, no-check-names, inet6, debug
.Pp
Returns non-zero on error:
.Bl -tag -width "0" -offset indent -compact -nested
.It 0
no errors
.It 1
failed to open file
.It 2
failed to stat file
.It 3
file too large
.It 4
out of memory
.It 5
short read from file
.El
.El
.Sh Internals:
Requests are kept in two queues. The first is the inflight queue. In
this queue requests have an allocated transaction id and nameserver.
They will soon be transmitted if they haven't already been.
.Pp
The second is the waiting queue. The size of the inflight ring is
limited and all other requests wait in waiting queue for space. This
bounds the number of concurrent requests so that we don't flood the
nameserver. Several algorithms require a full walk of the inflight
queue and so bounding its size keeps thing going nicely under huge
(many thousands of requests) loads.
.Pp
If a nameserver loses too many requests it is considered down and we
try not to use it. After a while we send a probe to that nameserver
(a lookup for google.com) and, if it replies, we consider it working
again. If the nameserver fails a probe we wait longer to try again
with the next probe.
.Sh SEE ALSO
.Xr event 3 ,
.Xr gethostbyname 3 ,
.Xr resolv.conf 5
.Sh HISTORY
The
.Nm evdns
API was developed by Adam Langley on top of the
.Nm libevent
API.
The code was integrate into
.Nm Tor
by Nick Mathewson and finally put into
.Nm libevent
itself by Niels Provos.
.Sh AUTHORS
The
.Nm evdns
API and code was written by Adam Langley with significant
contributions by Nick Mathewson.
.Sh BUGS
This documentation is neither complete nor authoritative.
If you are in doubt about the usage of this API then
check the source code to find out how it works, write
up the missing piece of documentation and send it to
me for inclusion in this man page.

3200
libevent/evdns.c Normal file

File diff suppressed because it is too large Load Diff

528
libevent/evdns.h Normal file
View File

@ -0,0 +1,528 @@
/*
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The original DNS code is due to Adam Langley with heavy
* modifications by Nick Mathewson. Adam put his DNS software in the
* public domain. You can find his original copyright below. Please,
* aware that the code as part of libevent is governed by the 3-clause
* BSD license above.
*
* This software is Public Domain. To view a copy of the public domain dedication,
* visit http://creativecommons.org/licenses/publicdomain/ or send a letter to
* Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
*
* I ask and expect, but do not require, that all derivative works contain an
* attribution similar to:
* Parts developed by Adam Langley <agl@imperialviolet.org>
*
* You may wish to replace the word "Parts" with something else depending on
* the amount of original code.
*
* (Derivative works does not include programs which link against, run or include
* the source verbatim in their source distributions)
*/
/** @file evdns.h
*
* Welcome, gentle reader
*
* Async DNS lookups are really a whole lot harder than they should be,
* mostly stemming from the fact that the libc resolver has never been
* very good at them. Before you use this library you should see if libc
* can do the job for you with the modern async call getaddrinfo_a
* (see http://www.imperialviolet.org/page25.html#e498). Otherwise,
* please continue.
*
* This code is based on libevent and you must call event_init before
* any of the APIs in this file. You must also seed the OpenSSL random
* source if you are using OpenSSL for ids (see below).
*
* This library is designed to be included and shipped with your source
* code. You statically link with it. You should also test for the
* existence of strtok_r and define HAVE_STRTOK_R if you have it.
*
* The DNS protocol requires a good source of id numbers and these
* numbers should be unpredictable for spoofing reasons. There are
* three methods for generating them here and you must define exactly
* one of them. In increasing order of preference:
*
* DNS_USE_GETTIMEOFDAY_FOR_ID:
* Using the bottom 16 bits of the usec result from gettimeofday. This
* is a pretty poor solution but should work anywhere.
* DNS_USE_CPU_CLOCK_FOR_ID:
* Using the bottom 16 bits of the nsec result from the CPU's time
* counter. This is better, but may not work everywhere. Requires
* POSIX realtime support and you'll need to link against -lrt on
* glibc systems at least.
* DNS_USE_OPENSSL_FOR_ID:
* Uses the OpenSSL RAND_bytes call to generate the data. You must
* have seeded the pool before making any calls to this library.
*
* The library keeps track of the state of nameservers and will avoid
* them when they go down. Otherwise it will round robin between them.
*
* Quick start guide:
* #include "evdns.h"
* void callback(int result, char type, int count, int ttl,
* void *addresses, void *arg);
* evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf");
* evdns_resolve("www.hostname.com", 0, callback, NULL);
*
* When the lookup is complete the callback function is called. The
* first argument will be one of the DNS_ERR_* defines in evdns.h.
* Hopefully it will be DNS_ERR_NONE, in which case type will be
* DNS_IPv4_A, count will be the number of IP addresses, ttl is the time
* which the data can be cached for (in seconds), addresses will point
* to an array of uint32_t's and arg will be whatever you passed to
* evdns_resolve.
*
* Searching:
*
* In order for this library to be a good replacement for glibc's resolver it
* supports searching. This involves setting a list of default domains, in
* which names will be queried for. The number of dots in the query name
* determines the order in which this list is used.
*
* Searching appears to be a single lookup from the point of view of the API,
* although many DNS queries may be generated from a single call to
* evdns_resolve. Searching can also drastically slow down the resolution
* of names.
*
* To disable searching:
* 1. Never set it up. If you never call evdns_resolv_conf_parse or
* evdns_search_add then no searching will occur.
*
* 2. If you do call evdns_resolv_conf_parse then don't pass
* DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it).
*
* 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag.
*
* The order of searches depends on the number of dots in the name. If the
* number is greater than the ndots setting then the names is first tried
* globally. Otherwise each search domain is appended in turn.
*
* The ndots setting can either be set from a resolv.conf, or by calling
* evdns_search_ndots_set.
*
* For example, with ndots set to 1 (the default) and a search domain list of
* ["myhome.net"]:
* Query: www
* Order: www.myhome.net, www.
*
* Query: www.abc
* Order: www.abc., www.abc.myhome.net
*
* Internals:
*
* Requests are kept in two queues. The first is the inflight queue. In
* this queue requests have an allocated transaction id and nameserver.
* They will soon be transmitted if they haven't already been.
*
* The second is the waiting queue. The size of the inflight ring is
* limited and all other requests wait in waiting queue for space. This
* bounds the number of concurrent requests so that we don't flood the
* nameserver. Several algorithms require a full walk of the inflight
* queue and so bounding its size keeps thing going nicely under huge
* (many thousands of requests) loads.
*
* If a nameserver loses too many requests it is considered down and we
* try not to use it. After a while we send a probe to that nameserver
* (a lookup for google.com) and, if it replies, we consider it working
* again. If the nameserver fails a probe we wait longer to try again
* with the next probe.
*/
#ifndef EVENTDNS_H
#define EVENTDNS_H
#ifdef __cplusplus
extern "C" {
#endif
/* For integer types. */
#include <evutil.h>
/** Error codes 0-5 are as described in RFC 1035. */
#define DNS_ERR_NONE 0
/** The name server was unable to interpret the query */
#define DNS_ERR_FORMAT 1
/** The name server was unable to process this query due to a problem with the
* name server */
#define DNS_ERR_SERVERFAILED 2
/** The domain name does not exist */
#define DNS_ERR_NOTEXIST 3
/** The name server does not support the requested kind of query */
#define DNS_ERR_NOTIMPL 4
/** The name server refuses to reform the specified operation for policy
* reasons */
#define DNS_ERR_REFUSED 5
/** The reply was truncated or ill-formated */
#define DNS_ERR_TRUNCATED 65
/** An unknown error occurred */
#define DNS_ERR_UNKNOWN 66
/** Communication with the server timed out */
#define DNS_ERR_TIMEOUT 67
/** The request was canceled because the DNS subsystem was shut down. */
#define DNS_ERR_SHUTDOWN 68
#define DNS_IPv4_A 1
#define DNS_PTR 2
#define DNS_IPv6_AAAA 3
#define DNS_QUERY_NO_SEARCH 1
#define DNS_OPTION_SEARCH 1
#define DNS_OPTION_NAMESERVERS 2
#define DNS_OPTION_MISC 4
#define DNS_OPTIONS_ALL 7
/**
* The callback that contains the results from a lookup.
* - type is either DNS_IPv4_A or DNS_PTR or DNS_IPv6_AAAA
* - count contains the number of addresses of form type
* - ttl is the number of seconds the resolution may be cached for.
* - addresses needs to be cast according to type
*/
typedef void (*evdns_callback_type) (int result, char type, int count, int ttl, void *addresses, void *arg);
/**
Initialize the asynchronous DNS library.
This function initializes support for non-blocking name resolution by
calling evdns_resolv_conf_parse() on UNIX and
evdns_config_windows_nameservers() on Windows.
@return 0 if successful, or -1 if an error occurred
@see evdns_shutdown()
*/
int evdns_init(void);
/**
Shut down the asynchronous DNS resolver and terminate all active requests.
If the 'fail_requests' option is enabled, all active requests will return
an empty result with the error flag set to DNS_ERR_SHUTDOWN. Otherwise,
the requests will be silently discarded.
@param fail_requests if zero, active requests will be aborted; if non-zero,
active requests will return DNS_ERR_SHUTDOWN.
@see evdns_init()
*/
void evdns_shutdown(int fail_requests);
/**
Convert a DNS error code to a string.
@param err the DNS error code
@return a string containing an explanation of the error code
*/
const char *evdns_err_to_string(int err);
/**
Add a nameserver.
The address should be an IPv4 address in network byte order.
The type of address is chosen so that it matches in_addr.s_addr.
@param address an IP address in network byte order
@return 0 if successful, or -1 if an error occurred
@see evdns_nameserver_ip_add()
*/
int evdns_nameserver_add(unsigned long int address);
/**
Get the number of configured nameservers.
This returns the number of configured nameservers (not necessarily the
number of running nameservers). This is useful for double-checking
whether our calls to the various nameserver configuration functions
have been successful.
@return the number of configured nameservers
@see evdns_nameserver_add()
*/
int evdns_count_nameservers(void);
/**
Remove all configured nameservers, and suspend all pending resolves.
Resolves will not necessarily be re-attempted until evdns_resume() is called.
@return 0 if successful, or -1 if an error occurred
@see evdns_resume()
*/
int evdns_clear_nameservers_and_suspend(void);
/**
Resume normal operation and continue any suspended resolve requests.
Re-attempt resolves left in limbo after an earlier call to
evdns_clear_nameservers_and_suspend().
@return 0 if successful, or -1 if an error occurred
@see evdns_clear_nameservers_and_suspend()
*/
int evdns_resume(void);
/**
Add a nameserver.
This wraps the evdns_nameserver_add() function by parsing a string as an IP
address and adds it as a nameserver.
@return 0 if successful, or -1 if an error occurred
@see evdns_nameserver_add()
*/
int evdns_nameserver_ip_add(const char *ip_as_string);
/**
Lookup an A record for a given name.
@param name a DNS hostname
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
@param callback a callback function to invoke when the request is completed
@param ptr an argument to pass to the callback function
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
*/
int evdns_resolve_ipv4(const char *name, int flags, evdns_callback_type callback, void *ptr);
/**
Lookup an AAAA record for a given name.
@param name a DNS hostname
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
@param callback a callback function to invoke when the request is completed
@param ptr an argument to pass to the callback function
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6()
*/
int evdns_resolve_ipv6(const char *name, int flags, evdns_callback_type callback, void *ptr);
struct in_addr;
struct in6_addr;
/**
Lookup a PTR record for a given IP address.
@param in an IPv4 address
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
@param callback a callback function to invoke when the request is completed
@param ptr an argument to pass to the callback function
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_reverse_ipv6()
*/
int evdns_resolve_reverse(const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
/**
Lookup a PTR record for a given IPv6 address.
@param in an IPv6 address
@param flags either 0, or DNS_QUERY_NO_SEARCH to disable searching for this query.
@param callback a callback function to invoke when the request is completed
@param ptr an argument to pass to the callback function
@return 0 if successful, or -1 if an error occurred
@see evdns_resolve_reverse_ipv6()
*/
int evdns_resolve_reverse_ipv6(const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
/**
Set the value of a configuration option.
The currently available configuration options are:
ndots, timeout, max-timeouts, max-inflight, and attempts
@param option the name of the configuration option to be modified
@param val the value to be set
@param flags either 0 | DNS_OPTION_SEARCH | DNS_OPTION_MISC
@return 0 if successful, or -1 if an error occurred
*/
int evdns_set_option(const char *option, const char *val, int flags);
/**
Parse a resolv.conf file.
The 'flags' parameter determines what information is parsed from the
resolv.conf file. See the man page for resolv.conf for the format of this
file.
The following directives are not parsed from the file: sortlist, rotate,
no-check-names, inet6, debug.
If this function encounters an error, the possible return values are: 1 =
failed to open file, 2 = failed to stat file, 3 = file too large, 4 = out of
memory, 5 = short read from file, 6 = no nameservers listed in the file
@param flags any of DNS_OPTION_NAMESERVERS|DNS_OPTION_SEARCH|DNS_OPTION_MISC|
DNS_OPTIONS_ALL
@param filename the path to the resolv.conf file
@return 0 if successful, or various positive error codes if an error
occurred (see above)
@see resolv.conf(3), evdns_config_windows_nameservers()
*/
int evdns_resolv_conf_parse(int flags, const char *const filename);
/**
Obtain nameserver information using the Windows API.
Attempt to configure a set of nameservers based on platform settings on
a win32 host. Preferentially tries to use GetNetworkParams; if that fails,
looks in the registry.
@return 0 if successful, or -1 if an error occurred
@see evdns_resolv_conf_parse()
*/
#ifdef WIN32
int evdns_config_windows_nameservers(void);
#endif
/**
Clear the list of search domains.
*/
void evdns_search_clear(void);
/**
Add a domain to the list of search domains
@param domain the domain to be added to the search list
*/
void evdns_search_add(const char *domain);
/**
Set the 'ndots' parameter for searches.
Sets the number of dots which, when found in a name, causes
the first query to be without any search domain.
@param ndots the new ndots parameter
*/
void evdns_search_ndots_set(const int ndots);
/**
A callback that is invoked when a log message is generated
@param is_warning indicates if the log message is a 'warning'
@param msg the content of the log message
*/
typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg);
/**
Set the callback function to handle log messages.
@param fn the callback to be invoked when a log message is generated
*/
void evdns_set_log_fn(evdns_debug_log_fn_type fn);
/**
Set a callback that will be invoked to generate transaction IDs. By
default, we pick transaction IDs based on the current clock time.
@param fn the new callback, or NULL to use the default.
*/
void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
#define DNS_NO_SEARCH 1
/*
* Structures and functions used to implement a DNS server.
*/
struct evdns_server_request {
int flags;
int nquestions;
struct evdns_server_question **questions;
};
struct evdns_server_question {
int type;
#ifdef __cplusplus
int dns_question_class;
#else
/* You should refer to this field as "dns_question_class". The
* name "class" works in C for backward compatibility, and will be
* removed in a future version. (1.5 or later). */
int class;
#define dns_question_class class
#endif
char name[1];
};
typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, void *);
#define EVDNS_ANSWER_SECTION 0
#define EVDNS_AUTHORITY_SECTION 1
#define EVDNS_ADDITIONAL_SECTION 2
#define EVDNS_TYPE_A 1
#define EVDNS_TYPE_NS 2
#define EVDNS_TYPE_CNAME 5
#define EVDNS_TYPE_SOA 6
#define EVDNS_TYPE_PTR 12
#define EVDNS_TYPE_MX 15
#define EVDNS_TYPE_TXT 16
#define EVDNS_TYPE_AAAA 28
#define EVDNS_QTYPE_AXFR 252
#define EVDNS_QTYPE_ALL 255
#define EVDNS_CLASS_INET 1
struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data);
void evdns_close_server_port(struct evdns_server_port *port);
int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data);
int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, void *addrs, int ttl);
int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl);
int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl);
int evdns_server_request_respond(struct evdns_server_request *req, int err);
int evdns_server_request_drop(struct evdns_server_request *req);
struct sockaddr;
int evdns_server_request_get_requesting_addr(struct evdns_server_request *_req, struct sockaddr *sa, int addr_len);
#ifdef __cplusplus
}
#endif
#endif /* !EVENTDNS_H */

102
libevent/event-internal.h Normal file
View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EVENT_INTERNAL_H_
#define _EVENT_INTERNAL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "config.h"
#include "min_heap.h"
#include "evsignal.h"
struct eventop {
const char *name;
void *(*init)(struct event_base *);
int (*add)(void *, struct event *);
int (*del)(void *, struct event *);
int (*dispatch)(struct event_base *, void *, struct timeval *);
void (*dealloc)(struct event_base *, void *);
/* set if we need to reinitialize the event base */
int need_reinit;
};
struct event_base {
const struct eventop *evsel;
void *evbase;
int event_count; /* counts number of total events */
int event_count_active; /* counts number of active events */
int event_gotterm; /* Set to terminate loop */
int event_break; /* Set to terminate loop immediately */
/* active event management */
struct event_list **activequeues;
int nactivequeues;
/* signal handling info */
struct evsignal_info sig;
struct event_list eventqueue;
struct timeval event_tv;
struct min_heap timeheap;
struct timeval tv_cache;
};
/* Internal use only: Functions that might be missing from <sys/queue.h> */
#ifndef HAVE_TAILQFOREACH
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#endif /* TAILQ_FOREACH */
int _evsignal_set_handler(struct event_base *base, int evsignal,
void (*fn)(int));
int _evsignal_restore_handler(struct event_base *base, int evsignal);
#ifdef __cplusplus
}
#endif
#endif /* _EVENT_INTERNAL_H_ */

624
libevent/event.3 Normal file
View File

@ -0,0 +1,624 @@
.\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $
.\"
.\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 8, 2000
.Dt EVENT 3
.Os
.Sh NAME
.Nm event_init ,
.Nm event_dispatch ,
.Nm event_loop ,
.Nm event_loopexit ,
.Nm event_loopbreak ,
.Nm event_set ,
.Nm event_base_dispatch ,
.Nm event_base_loop ,
.Nm event_base_loopexit ,
.Nm event_base_loopbreak ,
.Nm event_base_set ,
.Nm event_base_free ,
.Nm event_add ,
.Nm event_del ,
.Nm event_once ,
.Nm event_base_once ,
.Nm event_pending ,
.Nm event_initialized ,
.Nm event_priority_init ,
.Nm event_priority_set ,
.Nm evtimer_set ,
.Nm evtimer_add ,
.Nm evtimer_del ,
.Nm evtimer_pending ,
.Nm evtimer_initialized ,
.Nm signal_set ,
.Nm signal_add ,
.Nm signal_del ,
.Nm signal_pending ,
.Nm signal_initialized ,
.Nm bufferevent_new ,
.Nm bufferevent_free ,
.Nm bufferevent_write ,
.Nm bufferevent_write_buffer ,
.Nm bufferevent_read ,
.Nm bufferevent_enable ,
.Nm bufferevent_disable ,
.Nm bufferevent_settimeout ,
.Nm bufferevent_base_set ,
.Nm evbuffer_new ,
.Nm evbuffer_free ,
.Nm evbuffer_add ,
.Nm evbuffer_add_buffer ,
.Nm evbuffer_add_printf ,
.Nm evbuffer_add_vprintf ,
.Nm evbuffer_drain ,
.Nm evbuffer_write ,
.Nm evbuffer_read ,
.Nm evbuffer_find ,
.Nm evbuffer_readline ,
.Nm evhttp_new ,
.Nm evhttp_bind_socket ,
.Nm evhttp_free
.Nd execute a function when a specific event occurs
.Sh SYNOPSIS
.Fd #include <sys/time.h>
.Fd #include <event.h>
.Ft "struct event_base *"
.Fn "event_init" "void"
.Ft int
.Fn "event_dispatch" "void"
.Ft int
.Fn "event_loop" "int flags"
.Ft int
.Fn "event_loopexit" "struct timeval *tv"
.Ft int
.Fn "event_loopbreak" "void"
.Ft void
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
.Ft int
.Fn "event_base_dispatch" "struct event_base *base"
.Ft int
.Fn "event_base_loop" "struct event_base *base" "int flags"
.Ft int
.Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv"
.Ft int
.Fn "event_base_loopbreak" "struct event_base *base"
.Ft int
.Fn "event_base_set" "struct event_base *base" "struct event *"
.Ft void
.Fn "event_base_free" "struct event_base *base"
.Ft int
.Fn "event_add" "struct event *ev" "struct timeval *tv"
.Ft int
.Fn "event_del" "struct event *ev"
.Ft int
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
.Ft int
.Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
.Ft int
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
.Ft int
.Fn "event_initialized" "struct event *ev"
.Ft int
.Fn "event_priority_init" "int npriorities"
.Ft int
.Fn "event_priority_set" "struct event *ev" "int priority"
.Ft void
.Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg"
.Ft void
.Fn "evtimer_add" "struct event *ev" "struct timeval *"
.Ft void
.Fn "evtimer_del" "struct event *ev"
.Ft int
.Fn "evtimer_pending" "struct event *ev" "struct timeval *tv"
.Ft int
.Fn "evtimer_initialized" "struct event *ev"
.Ft void
.Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg"
.Ft void
.Fn "signal_add" "struct event *ev" "struct timeval *"
.Ft void
.Fn "signal_del" "struct event *ev"
.Ft int
.Fn "signal_pending" "struct event *ev" "struct timeval *tv"
.Ft int
.Fn "signal_initialized" "struct event *ev"
.Ft "struct bufferevent *"
.Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg"
.Ft void
.Fn "bufferevent_free" "struct bufferevent *bufev"
.Ft int
.Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size"
.Ft int
.Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf"
.Ft size_t
.Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size"
.Ft int
.Fn "bufferevent_enable" "struct bufferevent *bufev" "short event"
.Ft int
.Fn "bufferevent_disable" "struct bufferevent *bufev" "short event"
.Ft void
.Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write"
.Ft int
.Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev"
.Ft "struct evbuffer *"
.Fn "evbuffer_new" "void"
.Ft void
.Fn "evbuffer_free" "struct evbuffer *buf"
.Ft int
.Fn "evbuffer_add" "struct evbuffer *buf" "const void *data" "size_t size"
.Ft int
.Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src"
.Ft int
.Fn "evbuffer_add_printf" "struct evbuffer *buf" "const char *fmt" "..."
.Ft int
.Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap"
.Ft void
.Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size"
.Ft int
.Fn "evbuffer_write" "struct evbuffer *buf" "int fd"
.Ft int
.Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size"
.Ft "u_char *"
.Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size"
.Ft "char *"
.Fn "evbuffer_readline" "struct evbuffer *buf"
.Ft "struct evhttp *"
.Fn "evhttp_new" "struct event_base *base"
.Ft int
.Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port"
.Ft "void"
.Fn "evhttp_free" "struct evhttp *http"
.Ft int
.Fa (*event_sigcb)(void) ;
.Ft volatile sig_atomic_t
.Fa event_gotsig ;
.Sh DESCRIPTION
The
.Nm event
API provides a mechanism to execute a function when a specific event
on a file descriptor occurs or after a given time has passed.
.Pp
The
.Nm event
API needs to be initialized with
.Fn event_init
before it can be used.
.Pp
In order to process events, an application needs to call
.Fn event_dispatch .
This function only returns on error, and should replace the event core
of the application program.
.Pp
The function
.Fn event_set
prepares the event structure
.Fa ev
to be used in future calls to
.Fn event_add
and
.Fn event_del .
The event will be prepared to call the function specified by the
.Fa fn
argument with an
.Fa int
argument indicating the file descriptor, a
.Fa short
argument indicating the type of event, and a
.Fa void *
argument given in the
.Fa arg
argument.
The
.Fa fd
indicates the file descriptor that should be monitored for events.
The events can be either
.Va EV_READ ,
.Va EV_WRITE ,
or both,
indicating that an application can read or write from the file descriptor
respectively without blocking.
.Pp
The function
.Fa fn
will be called with the file descriptor that triggered the event and
the type of event which will be either
.Va EV_TIMEOUT ,
.Va EV_SIGNAL ,
.Va EV_READ ,
or
.Va EV_WRITE .
Additionally, an event which has registered interest in more than one of the
preceeding events, via bitwise-OR to
.Fn event_set ,
can provide its callback function with a bitwise-OR of more than one triggered
event.
The additional flag
.Va EV_PERSIST
makes an
.Fn event_add
persistent until
.Fn event_del
has been called.
.Pp
Once initialized, the
.Fa ev
structure can be used repeatedly with
.Fn event_add
and
.Fn event_del
and does not need to be reinitialized unless the function called and/or
the argument to it are to be changed.
However, when an
.Fa ev
structure has been added to libevent using
.Fn event_add
the structure must persist until the event occurs (assuming
.Fa EV_PERSIST
is not set) or is removed
using
.Fn event_del .
You may not reuse the same
.Fa ev
structure for multiple monitored descriptors; each descriptor
needs its own
.Fa ev .
.Pp
The function
.Fn event_add
schedules the execution of the
.Fa ev
event when the event specified in
.Fn event_set
occurs or in at least the time specified in the
.Fa tv .
If
.Fa tv
is
.Dv NULL ,
no timeout occurs and the function will only be called
if a matching event occurs on the file descriptor.
The event in the
.Fa ev
argument must be already initialized by
.Fn event_set
and may not be used in calls to
.Fn event_set
until it has timed out or been removed with
.Fn event_del .
If the event in the
.Fa ev
argument already has a scheduled timeout, the old timeout will be
replaced by the new one.
.Pp
The function
.Fn event_del
will cancel the event in the argument
.Fa ev .
If the event has already executed or has never been added
the call will have no effect.
.Pp
The functions
.Fn evtimer_set ,
.Fn evtimer_add ,
.Fn evtimer_del ,
.Fn evtimer_initialized ,
and
.Fn evtimer_pending
are abbreviations for common situations where only a timeout is required.
The file descriptor passed will be \-1, and the event type will be
.Va EV_TIMEOUT .
.Pp
The functions
.Fn signal_set ,
.Fn signal_add ,
.Fn signal_del ,
.Fn signal_initialized ,
and
.Fn signal_pending
are abbreviations.
The event type will be a persistent
.Va EV_SIGNAL .
That means
.Fn signal_set
adds
.Va EV_PERSIST .
.Pp
In order to avoid races in signal handlers, the
.Nm event
API provides two variables:
.Va event_sigcb
and
.Va event_gotsig .
A signal handler
sets
.Va event_gotsig
to indicate that a signal has been received.
The application sets
.Va event_sigcb
to a callback function.
After the signal handler sets
.Va event_gotsig ,
.Nm event_dispatch
will execute the callback function to process received signals.
The callback returns 1 when no events are registered any more.
It can return \-1 to indicate an error to the
.Nm event
library, causing
.Fn event_dispatch
to terminate with
.Va errno
set to
.Er EINTR .
.Pp
The function
.Fn event_once
is similar to
.Fn event_set .
However, it schedules a callback to be called exactly once and does not
require the caller to prepare an
.Fa event
structure.
This function supports
.Fa EV_TIMEOUT ,
.Fa EV_READ ,
and
.Fa EV_WRITE .
.Pp
The
.Fn event_pending
function can be used to check if the event specified by
.Fa event
is pending to run.
If
.Va EV_TIMEOUT
was specified and
.Fa tv
is not
.Dv NULL ,
the expiration time of the event will be returned in
.Fa tv .
.Pp
The
.Fn event_initialized
macro can be used to check if an event has been initialized.
.Pp
The
.Nm event_loop
function provides an interface for single pass execution of pending
events.
The flags
.Va EVLOOP_ONCE
and
.Va EVLOOP_NONBLOCK
are recognized.
The
.Nm event_loopexit
function exits from the event loop. The next
.Fn event_loop
iteration after the
given timer expires will complete normally (handling all queued events) then
exit without blocking for events again. Subsequent invocations of
.Fn event_loop
will proceed normally.
The
.Nm event_loopbreak
function exits from the event loop immediately.
.Fn event_loop
will abort after the next event is completed;
.Fn event_loopbreak
is typically invoked from this event's callback. This behavior is analogous
to the "break;" statement. Subsequent invocations of
.Fn event_loop
will proceed normally.
.Pp
It is the responsibility of the caller to provide these functions with
pre-allocated event structures.
.Pp
.Sh EVENT PRIORITIES
By default
.Nm libevent
schedules all active events with the same priority.
However, sometimes it is desirable to process some events with a higher
priority than others.
For that reason,
.Nm libevent
supports strict priority queues.
Active events with a lower priority are always processed before events
with a higher priority.
.Pp
The number of different priorities can be set initially with the
.Fn event_priority_init
function.
This function should be called before the first call to
.Fn event_dispatch .
The
.Fn event_priority_set
function can be used to assign a priority to an event.
By default,
.Nm libevent
assigns the middle priority to all events unless their priority
is explicitly set.
.Sh THREAD SAFE EVENTS
.Nm Libevent
has experimental support for thread-safe events.
When initializing the library via
.Fn event_init ,
an event base is returned.
This event base can be used in conjunction with calls to
.Fn event_base_set ,
.Fn event_base_dispatch ,
.Fn event_base_loop ,
.Fn event_base_loopexit ,
.Fn bufferevent_base_set
and
.Fn event_base_free .
.Fn event_base_set
should be called after preparing an event with
.Fn event_set ,
as
.Fn event_set
assigns the provided event to the most recently created event base.
.Fn bufferevent_base_set
should be called after preparing a bufferevent with
.Fn bufferevent_new .
.Fn event_base_free
should be used to free memory associated with the event base
when it is no longer needed.
.Sh BUFFERED EVENTS
.Nm libevent
provides an abstraction on top of the regular event callbacks.
This abstraction is called a
.Va "buffered event" .
A buffered event provides input and output buffers that get filled
and drained automatically.
The user of a buffered event no longer deals directly with the IO,
but instead is reading from input and writing to output buffers.
.Pp
A new bufferevent is created by
.Fn bufferevent_new .
The parameter
.Fa fd
specifies the file descriptor from which data is read and written to.
This file descriptor is not allowed to be a
.Xr pipe 2 .
The next three parameters are callbacks.
The read and write callback have the following form:
.Ft void
.Fn "(*cb)" "struct bufferevent *bufev" "void *arg" .
The error callback has the following form:
.Ft void
.Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" .
The argument is specified by the fourth parameter
.Fa "cbarg" .
A
.Fa bufferevent struct
pointer is returned on success, NULL on error.
Both the read and the write callback may be NULL.
The error callback has to be always provided.
.Pp
Once initialized, the bufferevent structure can be used repeatedly with
bufferevent_enable() and bufferevent_disable().
The flags parameter can be a combination of
.Va EV_READ
and
.Va EV_WRITE .
When read enabled the bufferevent will try to read from the file
descriptor and call the read callback.
The write callback is executed
whenever the output buffer is drained below the write low watermark,
which is
.Va 0
by default.
.Pp
The
.Fn bufferevent_write
function can be used to write data to the file descriptor.
The data is appended to the output buffer and written to the descriptor
automatically as it becomes available for writing.
.Fn bufferevent_write
returns 0 on success or \-1 on failure.
The
.Fn bufferevent_read
function is used to read data from the input buffer,
returning the amount of data read.
.Pp
If multiple bases are in use, bufferevent_base_set() must be called before
enabling the bufferevent for the first time.
.Sh NON-BLOCKING HTTP SUPPORT
.Nm libevent
provides a very thin HTTP layer that can be used both to host an HTTP
server and also to make HTTP requests.
An HTTP server can be created by calling
.Fn evhttp_new .
It can be bound to any port and address with the
.Fn evhttp_bind_socket
function.
When the HTTP server is no longer used, it can be freed via
.Fn evhttp_free .
.Pp
To be notified of HTTP requests, a user needs to register callbacks with the
HTTP server.
This can be done by calling
.Fn evhttp_set_cb .
The second argument is the URI for which a callback is being registered.
The corresponding callback will receive an
.Va struct evhttp_request
object that contains all information about the request.
.Pp
This section does not document all the possible function calls; please
check
.Va event.h
for the public interfaces.
.Sh ADDITIONAL NOTES
It is possible to disable support for
.Va epoll , kqueue , devpoll , poll
or
.Va select
by setting the environment variable
.Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL
or
.Va EVENT_NOSELECT ,
respectively.
By setting the environment variable
.Va EVENT_SHOW_METHOD ,
.Nm libevent
displays the kernel notification method that it uses.
.Sh RETURN VALUES
Upon successful completion
.Fn event_add
and
.Fn event_del
return 0.
Otherwise, \-1 is returned and the global variable errno is
set to indicate the error.
.Sh SEE ALSO
.Xr kqueue 2 ,
.Xr poll 2 ,
.Xr select 2 ,
.Xr evdns 3 ,
.Xr timeout 9
.Sh HISTORY
The
.Nm event
API manpage is based on the
.Xr timeout 9
manpage by Artur Grabowski.
The port of
.Nm libevent
to Windows is due to Michael A. Davis.
Support for real-time signals is due to Taral.
.Sh AUTHORS
The
.Nm event
library was written by Niels Provos.
.Sh BUGS
This documentation is neither complete nor authoritative.
If you are in doubt about the usage of this API then
check the source code to find out how it works, write
up the missing piece of documentation and send it to
me for inclusion in this man page.

1025
libevent/event.c Normal file

File diff suppressed because it is too large Load Diff

1175
libevent/event.h Normal file

File diff suppressed because it is too large Load Diff

1417
libevent/event_rpcgen.py Normal file

File diff suppressed because it is too large Load Diff

443
libevent/event_tagging.c Normal file
View File

@ -0,0 +1,443 @@
/*
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#else
#include <sys/ioctl.h>
#endif
#include <sys/queue.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <syslog.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "event.h"
#include "evutil.h"
#include "log.h"
int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
static struct evbuffer *_buf; /* not thread safe */
void
evtag_init(void)
{
if (_buf != NULL)
return;
if ((_buf = evbuffer_new()) == NULL)
event_err(1, "%s: malloc", __func__);
}
/*
* We encode integer's by nibbles; the first nibble contains the number
* of significant nibbles - 1; this allows us to encode up to 64-bit
* integers. This function is byte-order independent.
*/
void
encode_int(struct evbuffer *evbuf, ev_uint32_t number)
{
int off = 1, nibbles = 0;
ev_uint8_t data[5];
memset(data, 0, sizeof(ev_uint32_t)+1);
while (number) {
if (off & 0x1)
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
else
data[off/2] = (data[off/2] & 0x0f) |
((number & 0x0f) << 4);
number >>= 4;
off++;
}
if (off > 2)
nibbles = off - 2;
/* Off - 1 is the number of encoded nibbles */
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
evbuffer_add(evbuf, data, (off + 1) / 2);
}
/*
* Support variable length encoding of tags; we use the high bit in each
* octet as a continuation signal.
*/
int
evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
{
int bytes = 0;
ev_uint8_t data[5];
memset(data, 0, sizeof(data));
do {
ev_uint8_t lower = tag & 0x7f;
tag >>= 7;
if (tag)
lower |= 0x80;
data[bytes++] = lower;
} while (tag);
if (evbuf != NULL)
evbuffer_add(evbuf, data, bytes);
return (bytes);
}
static int
decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
{
ev_uint32_t number = 0;
ev_uint8_t *data = EVBUFFER_DATA(evbuf);
int len = EVBUFFER_LENGTH(evbuf);
int count = 0, shift = 0, done = 0;
while (count++ < len) {
ev_uint8_t lower = *data++;
number |= (lower & 0x7f) << shift;
shift += 7;
if (!(lower & 0x80)) {
done = 1;
break;
}
}
if (!done)
return (-1);
if (dodrain)
evbuffer_drain(evbuf, count);
if (ptag != NULL)
*ptag = number;
return (count);
}
int
evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
{
return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
}
/*
* Marshal a data type, the general format is as follows:
*
* tag number: one byte; length: var bytes; payload: var bytes
*/
void
evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
const void *data, ev_uint32_t len)
{
evtag_encode_tag(evbuf, tag);
encode_int(evbuf, len);
evbuffer_add(evbuf, (void *)data, len);
}
/* Marshaling for integers */
void
evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
encode_int(_buf, integer);
evtag_encode_tag(evbuf, tag);
encode_int(evbuf, EVBUFFER_LENGTH(_buf));
evbuffer_add_buffer(evbuf, _buf);
}
void
evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
{
evtag_marshal(buf, tag, string, strlen(string));
}
void
evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
encode_int(_buf, tv->tv_sec);
encode_int(_buf, tv->tv_usec);
evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
EVBUFFER_LENGTH(_buf));
}
static int
decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
{
ev_uint32_t number = 0;
ev_uint8_t *data = EVBUFFER_DATA(evbuf);
int len = EVBUFFER_LENGTH(evbuf);
int nibbles = 0;
if (!len)
return (-1);
nibbles = ((data[0] & 0xf0) >> 4) + 1;
if (nibbles > 8 || (nibbles >> 1) + 1 > len)
return (-1);
len = (nibbles >> 1) + 1;
while (nibbles > 0) {
number <<= 4;
if (nibbles & 0x1)
number |= data[nibbles >> 1] & 0x0f;
else
number |= (data[nibbles >> 1] & 0xf0) >> 4;
nibbles--;
}
if (dodrain)
evbuffer_drain(evbuf, len);
*pnumber = number;
return (len);
}
int
evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
{
return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
}
int
evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
{
return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
}
int
evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
{
struct evbuffer tmp;
int res, len;
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
if (len == -1)
return (-1);
tmp = *evbuf;
tmp.buffer += len;
tmp.off -= len;
res = decode_int_internal(plength, &tmp, 0);
if (res == -1)
return (-1);
*plength += res + len;
return (0);
}
int
evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
{
struct evbuffer tmp;
int res, len;
len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
if (len == -1)
return (-1);
tmp = *evbuf;
tmp.buffer += len;
tmp.off -= len;
res = decode_int_internal(plength, &tmp, 0);
if (res == -1)
return (-1);
return (0);
}
int
evtag_consume(struct evbuffer *evbuf)
{
ev_uint32_t len;
if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1)
return (-1);
if (evtag_decode_int(&len, evbuf) == -1)
return (-1);
evbuffer_drain(evbuf, len);
return (0);
}
/* Reads the data type from an event buffer */
int
evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
{
ev_uint32_t len;
ev_uint32_t integer;
if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1)
return (-1);
if (evtag_decode_int(&integer, src) == -1)
return (-1);
len = integer;
if (EVBUFFER_LENGTH(src) < len)
return (-1);
if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1)
return (-1);
evbuffer_drain(src, len);
return (len);
}
/* Marshaling for integers */
int
evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
ev_uint32_t *pinteger)
{
ev_uint32_t tag;
ev_uint32_t len;
ev_uint32_t integer;
if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
return (-1);
if (need_tag != tag)
return (-1);
if (evtag_decode_int(&integer, evbuf) == -1)
return (-1);
len = integer;
if (EVBUFFER_LENGTH(evbuf) < len)
return (-1);
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1)
return (-1);
evbuffer_drain(evbuf, len);
return (evtag_decode_int(pinteger, _buf));
}
/* Unmarshal a fixed length tag */
int
evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
size_t len)
{
ev_uint32_t tag;
/* Initialize this event buffer so that we can read into it */
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
/* Now unmarshal a tag and check that it matches the tag we want */
if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag)
return (-1);
if (EVBUFFER_LENGTH(_buf) != len)
return (-1);
memcpy(data, EVBUFFER_DATA(_buf), len);
return (0);
}
int
evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
char **pstring)
{
ev_uint32_t tag;
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
return (-1);
*pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1);
if (*pstring == NULL)
event_err(1, "%s: calloc", __func__);
evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf));
return (0);
}
int
evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
struct timeval *ptv)
{
ev_uint32_t tag;
ev_uint32_t integer;
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
return (-1);
if (evtag_decode_int(&integer, _buf) == -1)
return (-1);
ptv->tv_sec = integer;
if (evtag_decode_int(&integer, _buf) == -1)
return (-1);
ptv->tv_usec = integer;
return (0);
}

371
libevent/evhttp.h Normal file
View File

@ -0,0 +1,371 @@
/*
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EVHTTP_H_
#define _EVHTTP_H_
#include <event.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#endif
/** @file evhttp.h
*
* Basic support for HTTP serving.
*
* As libevent is a library for dealing with event notification and most
* interesting applications are networked today, I have often found the
* need to write HTTP code. The following prototypes and definitions provide
* an application with a minimal interface for making HTTP requests and for
* creating a very simple HTTP server.
*/
/* Response codes */
#define HTTP_OK 200
#define HTTP_NOCONTENT 204
#define HTTP_MOVEPERM 301
#define HTTP_MOVETEMP 302
#define HTTP_NOTMODIFIED 304
#define HTTP_BADREQUEST 400
#define HTTP_NOTFOUND 404
#define HTTP_SERVUNAVAIL 503
struct evhttp;
struct evhttp_request;
struct evkeyvalq;
/** Create a new HTTP server
*
* @param base (optional) the event base to receive the HTTP events
* @return a pointer to a newly initialized evhttp server structure
*/
struct evhttp *evhttp_new(struct event_base *base);
/**
* Binds an HTTP server on the specified address and port.
*
* Can be called multiple times to bind the same http server
* to multiple different ports.
*
* @param http a pointer to an evhttp object
* @param address a string containing the IP address to listen(2) on
* @param port the port number to listen on
* @return a newly allocated evhttp struct
* @see evhttp_free()
*/
int evhttp_bind_socket(struct evhttp *http, const char *address, u_short port);
/**
* Makes an HTTP server accept connections on the specified socket
*
* This may be useful to create a socket and then fork multiple instances
* of an http server, or when a socket has been communicated via file
* descriptor passing in situations where an http servers does not have
* permissions to bind to a low-numbered port.
*
* Can be called multiple times to have the http server listen to
* multiple different sockets.
*
* @param http a pointer to an evhttp object
* @param fd a socket fd that is ready for accepting connections
* @return 0 on success, -1 on failure.
* @see evhttp_free(), evhttp_bind_socket()
*/
int evhttp_accept_socket(struct evhttp *http, int fd);
/**
* Free the previously created HTTP server.
*
* Works only if no requests are currently being served.
*
* @param http the evhttp server object to be freed
* @see evhttp_start()
*/
void evhttp_free(struct evhttp* http);
/** Set a callback for a specified URI */
void evhttp_set_cb(struct evhttp *, const char *,
void (*)(struct evhttp_request *, void *), void *);
/** Removes the callback for a specified URI */
int evhttp_del_cb(struct evhttp *, const char *);
/** Set a callback for all requests that are not caught by specific callbacks
*/
void evhttp_set_gencb(struct evhttp *,
void (*)(struct evhttp_request *, void *), void *);
/**
* Set the timeout for an HTTP request.
*
* @param http an evhttp object
* @param timeout_in_secs the timeout, in seconds
*/
void evhttp_set_timeout(struct evhttp *, int timeout_in_secs);
/* Request/Response functionality */
/**
* Send an HTML error message to the client.
*
* @param req a request object
* @param error the HTTP error code
* @param reason a brief explanation of the error
*/
void evhttp_send_error(struct evhttp_request *req, int error,
const char *reason);
/**
* Send an HTML reply to the client.
*
* @param req a request object
* @param code the HTTP response code to send
* @param reason a brief message to send with the response code
* @param databuf the body of the response
*/
void evhttp_send_reply(struct evhttp_request *req, int code,
const char *reason, struct evbuffer *databuf);
/* Low-level response interface, for streaming/chunked replies */
void evhttp_send_reply_start(struct evhttp_request *, int, const char *);
void evhttp_send_reply_chunk(struct evhttp_request *, struct evbuffer *);
void evhttp_send_reply_end(struct evhttp_request *);
/**
* Start an HTTP server on the specified address and port
*
* DEPRECATED: it does not allow an event base to be specified
*
* @param address the address to which the HTTP server should be bound
* @param port the port number on which the HTTP server should listen
* @return an struct evhttp object
*/
struct evhttp *evhttp_start(const char *address, u_short port);
/*
* Interfaces for making requests
*/
enum evhttp_cmd_type { EVHTTP_REQ_GET, EVHTTP_REQ_POST, EVHTTP_REQ_HEAD };
enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
/**
* the request structure that a server receives.
* WARNING: expect this structure to change. I will try to provide
* reasonable accessors.
*/
struct evhttp_request {
#if defined(TAILQ_ENTRY)
TAILQ_ENTRY(evhttp_request) next;
#else
struct {
struct evhttp_request *tqe_next;
struct evhttp_request **tqe_prev;
} next;
#endif
/* the connection object that this request belongs to */
struct evhttp_connection *evcon;
int flags;
#define EVHTTP_REQ_OWN_CONNECTION 0x0001
#define EVHTTP_PROXY_REQUEST 0x0002
struct evkeyvalq *input_headers;
struct evkeyvalq *output_headers;
/* address of the remote host and the port connection came from */
char *remote_host;
u_short remote_port;
enum evhttp_request_kind kind;
enum evhttp_cmd_type type;
char *uri; /* uri after HTTP request was parsed */
char major; /* HTTP Major number */
char minor; /* HTTP Minor number */
int response_code; /* HTTP Response code */
char *response_code_line; /* Readable response */
struct evbuffer *input_buffer; /* read data */
ev_int64_t ntoread;
int chunked;
struct evbuffer *output_buffer; /* outgoing post or data */
/* Callback */
void (*cb)(struct evhttp_request *, void *);
void *cb_arg;
/*
* Chunked data callback - call for each completed chunk if
* specified. If not specified, all the data is delivered via
* the regular callback.
*/
void (*chunk_cb)(struct evhttp_request *, void *);
};
/**
* Creates a new request object that needs to be filled in with the request
* parameters. The callback is executed when the request completed or an
* error occurred.
*/
struct evhttp_request *evhttp_request_new(
void (*cb)(struct evhttp_request *, void *), void *arg);
/** enable delivery of chunks to requestor */
void evhttp_request_set_chunked_cb(struct evhttp_request *,
void (*cb)(struct evhttp_request *, void *));
/** Frees the request object and removes associated events. */
void evhttp_request_free(struct evhttp_request *req);
/**
* A connection object that can be used to for making HTTP requests. The
* connection object tries to establish the connection when it is given an
* http request object.
*/
struct evhttp_connection *evhttp_connection_new(
const char *address, unsigned short port);
/** Frees an http connection */
void evhttp_connection_free(struct evhttp_connection *evcon);
/** sets the ip address from which http connections are made */
void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
const char *address);
/** sets the local port from which http connections are made */
void evhttp_connection_set_local_port(struct evhttp_connection *evcon,
unsigned short port);
/** Sets the timeout for events related to this connection */
void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
int timeout_in_secs);
/** Sets the retry limit for this connection - -1 repeats indefnitely */
void evhttp_connection_set_retries(struct evhttp_connection *evcon,
int retry_max);
/** Set a callback for connection close. */
void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
void (*)(struct evhttp_connection *, void *), void *);
/**
* Associates an event base with the connection - can only be called
* on a freshly created connection object that has not been used yet.
*/
void evhttp_connection_set_base(struct evhttp_connection *evcon,
struct event_base *base);
/** Get the remote address and port associated with this connection. */
void evhttp_connection_get_peer(struct evhttp_connection *evcon,
char **address, u_short *port);
/** The connection gets ownership of the request */
int evhttp_make_request(struct evhttp_connection *evcon,
struct evhttp_request *req,
enum evhttp_cmd_type type, const char *uri);
const char *evhttp_request_uri(struct evhttp_request *req);
/* Interfaces for dealing with HTTP headers */
const char *evhttp_find_header(const struct evkeyvalq *, const char *);
int evhttp_remove_header(struct evkeyvalq *, const char *);
int evhttp_add_header(struct evkeyvalq *, const char *, const char *);
void evhttp_clear_headers(struct evkeyvalq *);
/* Miscellaneous utility functions */
/**
Helper function to encode a URI.
The returned string must be freed by the caller.
@param uri an unencoded URI
@return a newly allocated URI-encoded string
*/
char *evhttp_encode_uri(const char *uri);
/**
Helper function to decode a URI.
The returned string must be freed by the caller.
@param uri an encoded URI
@return a newly allocated unencoded URI
*/
char *evhttp_decode_uri(const char *uri);
/**
* Helper function to parse out arguments in a query.
*
* Parsing a uri like
*
* http://foo.com/?q=test&s=some+thing
*
* will result in two entries in the key value queue.
* The first entry is: key="q", value="test"
* The second entry is: key="s", value="some thing"
*
* @param uri the request URI
* @param headers the head of the evkeyval queue
*/
void evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
/**
* Escape HTML character entities in a string.
*
* Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
* &#039; and &amp; correspondingly.
*
* The returned string needs to be freed by the caller.
*
* @param html an unescaped HTML string
* @return an escaped HTML string
*/
char *evhttp_htmlescape(const char *html);
#ifdef __cplusplus
}
#endif
#endif /* _EVHTTP_H_ */

513
libevent/evport.c Normal file
View File

@ -0,0 +1,513 @@
/*
* Submitted by David Pacheco (dp.spambait@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2007 Sun Microsystems. All rights reserved.
* Use is subject to license terms.
*/
/*
* evport.c: event backend using Solaris 10 event ports. See port_create(3C).
* This implementation is loosely modeled after the one used for select(2) (in
* select.c).
*
* The outstanding events are tracked in a data structure called evport_data.
* Each entry in the ed_fds array corresponds to a file descriptor, and contains
* pointers to the read and write events that correspond to that fd. (That is,
* when the file is readable, the "read" event should handle it, etc.)
*
* evport_add and evport_del update this data structure. evport_dispatch uses it
* to determine where to callback when an event occurs (which it gets from
* port_getn).
*
* Helper functions are used: grow() grows the file descriptor array as
* necessary when large fd's come in. reassociate() takes care of maintaining
* the proper file-descriptor/event-port associations.
*
* As in the select(2) implementation, signals are handled by evsignal.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/time.h>
#include <assert.h>
#include <sys/queue.h>
#include <errno.h>
#include <poll.h>
#include <port.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef CHECK_INVARIANTS
#include <assert.h>
#endif
#include "event.h"
#include "event-internal.h"
#include "log.h"
#include "evsignal.h"
/*
* Default value for ed_nevents, which is the maximum file descriptor number we
* can handle. If an event comes in for a file descriptor F > nevents, we will
* grow the array of file descriptors, doubling its size.
*/
#define DEFAULT_NFDS 16
/*
* EVENTS_PER_GETN is the maximum number of events to retrieve from port_getn on
* any particular call. You can speed things up by increasing this, but it will
* (obviously) require more memory.
*/
#define EVENTS_PER_GETN 8
/*
* Per-file-descriptor information about what events we're subscribed to. These
* fields are NULL if no event is subscribed to either of them.
*/
struct fd_info {
struct event* fdi_revt; /* the event responsible for the "read" */
struct event* fdi_wevt; /* the event responsible for the "write" */
};
#define FDI_HAS_READ(fdi) ((fdi)->fdi_revt != NULL)
#define FDI_HAS_WRITE(fdi) ((fdi)->fdi_wevt != NULL)
#define FDI_HAS_EVENTS(fdi) (FDI_HAS_READ(fdi) || FDI_HAS_WRITE(fdi))
#define FDI_TO_SYSEVENTS(fdi) (FDI_HAS_READ(fdi) ? POLLIN : 0) | \
(FDI_HAS_WRITE(fdi) ? POLLOUT : 0)
struct evport_data {
int ed_port; /* event port for system events */
int ed_nevents; /* number of allocated fdi's */
struct fd_info *ed_fds; /* allocated fdi table */
/* fdi's that we need to reassoc */
int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
};
static void* evport_init (struct event_base *);
static int evport_add (void *, struct event *);
static int evport_del (void *, struct event *);
static int evport_dispatch (struct event_base *, void *, struct timeval *);
static void evport_dealloc (struct event_base *, void *);
const struct eventop evportops = {
"evport",
evport_init,
evport_add,
evport_del,
evport_dispatch,
evport_dealloc,
1 /* need reinit */
};
/*
* Initialize the event port implementation.
*/
static void*
evport_init(struct event_base *base)
{
struct evport_data *evpd;
int i;
/*
* Disable event ports when this environment variable is set
*/
if (getenv("EVENT_NOEVPORT"))
return (NULL);
if (!(evpd = calloc(1, sizeof(struct evport_data))))
return (NULL);
if ((evpd->ed_port = port_create()) == -1) {
free(evpd);
return (NULL);
}
/*
* Initialize file descriptor structure
*/
evpd->ed_fds = calloc(DEFAULT_NFDS, sizeof(struct fd_info));
if (evpd->ed_fds == NULL) {
close(evpd->ed_port);
free(evpd);
return (NULL);
}
evpd->ed_nevents = DEFAULT_NFDS;
for (i = 0; i < EVENTS_PER_GETN; i++)
evpd->ed_pending[i] = -1;
evsignal_init(base);
return (evpd);
}
#ifdef CHECK_INVARIANTS
/*
* Checks some basic properties about the evport_data structure. Because it
* checks all file descriptors, this function can be expensive when the maximum
* file descriptor ever used is rather large.
*/
static void
check_evportop(struct evport_data *evpd)
{
assert(evpd);
assert(evpd->ed_nevents > 0);
assert(evpd->ed_port > 0);
assert(evpd->ed_fds > 0);
/*
* Verify the integrity of the fd_info struct as well as the events to
* which it points (at least, that they're valid references and correct
* for their position in the structure).
*/
int i;
for (i = 0; i < evpd->ed_nevents; ++i) {
struct event *ev;
struct fd_info *fdi;
fdi = &evpd->ed_fds[i];
if ((ev = fdi->fdi_revt) != NULL) {
assert(ev->ev_fd == i);
}
if ((ev = fdi->fdi_wevt) != NULL) {
assert(ev->ev_fd == i);
}
}
}
/*
* Verifies very basic integrity of a given port_event.
*/
static void
check_event(port_event_t* pevt)
{
/*
* We've only registered for PORT_SOURCE_FD events. The only
* other thing we can legitimately receive is PORT_SOURCE_ALERT,
* but since we're not using port_alert either, we can assume
* PORT_SOURCE_FD.
*/
assert(pevt->portev_source == PORT_SOURCE_FD);
assert(pevt->portev_user == NULL);
}
#else
#define check_evportop(epop)
#define check_event(pevt)
#endif /* CHECK_INVARIANTS */
/*
* Doubles the size of the allocated file descriptor array.
*/
static int
grow(struct evport_data *epdp, int factor)
{
struct fd_info *tmp;
int oldsize = epdp->ed_nevents;
int newsize = factor * oldsize;
assert(factor > 1);
check_evportop(epdp);
tmp = realloc(epdp->ed_fds, sizeof(struct fd_info) * newsize);
if (NULL == tmp)
return -1;
epdp->ed_fds = tmp;
memset((char*) (epdp->ed_fds + oldsize), 0,
(newsize - oldsize)*sizeof(struct fd_info));
epdp->ed_nevents = newsize;
check_evportop(epdp);
return 0;
}
/*
* (Re)associates the given file descriptor with the event port. The OS events
* are specified (implicitly) from the fd_info struct.
*/
static int
reassociate(struct evport_data *epdp, struct fd_info *fdip, int fd)
{
int sysevents = FDI_TO_SYSEVENTS(fdip);
if (sysevents != 0) {
if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
fd, sysevents, NULL) == -1) {
event_warn("port_associate");
return (-1);
}
}
check_evportop(epdp);
return (0);
}
/*
* Main event loop - polls port_getn for some number of events, and processes
* them.
*/
static int
evport_dispatch(struct event_base *base, void *arg, struct timeval *tv)
{
int i, res;
struct evport_data *epdp = arg;
port_event_t pevtlist[EVENTS_PER_GETN];
/*
* port_getn will block until it has at least nevents events. It will
* also return how many it's given us (which may be more than we asked
* for, as long as it's less than our maximum (EVENTS_PER_GETN)) in
* nevents.
*/
int nevents = 1;
/*
* We have to convert a struct timeval to a struct timespec
* (only difference is nanoseconds vs. microseconds). If no time-based
* events are active, we should wait for I/O (and tv == NULL).
*/
struct timespec ts;
struct timespec *ts_p = NULL;
if (tv != NULL) {
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
ts_p = &ts;
}
/*
* Before doing anything else, we need to reassociate the events we hit
* last time which need reassociation. See comment at the end of the
* loop below.
*/
for (i = 0; i < EVENTS_PER_GETN; ++i) {
struct fd_info *fdi = NULL;
if (epdp->ed_pending[i] != -1) {
fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
}
if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd :
fdi->fdi_wevt->ev_fd;
reassociate(epdp, fdi, fd);
epdp->ed_pending[i] = -1;
}
}
if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN,
(unsigned int *) &nevents, ts_p)) == -1) {
if (errno == EINTR || errno == EAGAIN) {
evsignal_process(base);
return (0);
} else if (errno == ETIME) {
if (nevents == 0)
return (0);
} else {
event_warn("port_getn");
return (-1);
}
} else if (base->sig.evsignal_caught) {
evsignal_process(base);
}
event_debug(("%s: port_getn reports %d events", __func__, nevents));
for (i = 0; i < nevents; ++i) {
struct event *ev;
struct fd_info *fdi;
port_event_t *pevt = &pevtlist[i];
int fd = (int) pevt->portev_object;
check_evportop(epdp);
check_event(pevt);
epdp->ed_pending[i] = fd;
/*
* Figure out what kind of event it was
* (because we have to pass this to the callback)
*/
res = 0;
if (pevt->portev_events & POLLIN)
res |= EV_READ;
if (pevt->portev_events & POLLOUT)
res |= EV_WRITE;
assert(epdp->ed_nevents > fd);
fdi = &(epdp->ed_fds[fd]);
/*
* We now check for each of the possible events (READ
* or WRITE). Then, we activate the event (which will
* cause its callback to be executed).
*/
if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) {
event_active(ev, res, 1);
}
if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) {
event_active(ev, res, 1);
}
} /* end of all events gotten */
check_evportop(epdp);
return (0);
}
/*
* Adds the given event (so that you will be notified when it happens via
* the callback function).
*/
static int
evport_add(void *arg, struct event *ev)
{
struct evport_data *evpd = arg;
struct fd_info *fdi;
int factor;
check_evportop(evpd);
/*
* Delegate, if it's not ours to handle.
*/
if (ev->ev_events & EV_SIGNAL)
return (evsignal_add(ev));
/*
* If necessary, grow the file descriptor info table
*/
factor = 1;
while (ev->ev_fd >= factor * evpd->ed_nevents)
factor *= 2;
if (factor > 1) {
if (-1 == grow(evpd, factor)) {
return (-1);
}
}
fdi = &evpd->ed_fds[ev->ev_fd];
if (ev->ev_events & EV_READ)
fdi->fdi_revt = ev;
if (ev->ev_events & EV_WRITE)
fdi->fdi_wevt = ev;
return reassociate(evpd, fdi, ev->ev_fd);
}
/*
* Removes the given event from the list of events to wait for.
*/
static int
evport_del(void *arg, struct event *ev)
{
struct evport_data *evpd = arg;
struct fd_info *fdi;
int i;
int associated = 1;
check_evportop(evpd);
/*
* Delegate, if it's not ours to handle
*/
if (ev->ev_events & EV_SIGNAL) {
return (evsignal_del(ev));
}
if (evpd->ed_nevents < ev->ev_fd) {
return (-1);
}
for (i = 0; i < EVENTS_PER_GETN; ++i) {
if (evpd->ed_pending[i] == ev->ev_fd) {
associated = 0;
break;
}
}
fdi = &evpd->ed_fds[ev->ev_fd];
if (ev->ev_events & EV_READ)
fdi->fdi_revt = NULL;
if (ev->ev_events & EV_WRITE)
fdi->fdi_wevt = NULL;
if (associated) {
if (!FDI_HAS_EVENTS(fdi) &&
port_dissociate(evpd->ed_port, PORT_SOURCE_FD,
ev->ev_fd) == -1) {
/*
* Ignre EBADFD error the fd could have been closed
* before event_del() was called.
*/
if (errno != EBADFD) {
event_warn("port_dissociate");
return (-1);
}
} else {
if (FDI_HAS_EVENTS(fdi)) {
return (reassociate(evpd, fdi, ev->ev_fd));
}
}
} else {
if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) {
evpd->ed_pending[i] = -1;
}
}
return 0;
}
static void
evport_dealloc(struct event_base *base, void *arg)
{
struct evport_data *evpd = arg;
evsignal_dealloc(base);
close(evpd->ed_port);
if (evpd->ed_fds)
free(evpd->ed_fds);
free(evpd);
}

87
libevent/evrpc-internal.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2006 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EVRPC_INTERNAL_H_
#define _EVRPC_INTERNAL_H_
#include "http-internal.h"
struct evrpc;
#define EVRPC_URI_PREFIX "/.rpc."
struct evrpc_hook {
TAILQ_ENTRY(evrpc_hook) (next);
/* returns -1; if the rpc should be aborted, is allowed to rewrite */
int (*process)(struct evhttp_request *, struct evbuffer *, void *);
void *process_arg;
};
TAILQ_HEAD(evrpc_hook_list, evrpc_hook);
/*
* this is shared between the base and the pool, so that we can reuse
* the hook adding functions; we alias both evrpc_pool and evrpc_base
* to this common structure.
*/
struct _evrpc_hooks {
/* hooks for processing outbound and inbound rpcs */
struct evrpc_hook_list in_hooks;
struct evrpc_hook_list out_hooks;
};
#define input_hooks common.in_hooks
#define output_hooks common.out_hooks
struct evrpc_base {
struct _evrpc_hooks common;
/* the HTTP server under which we register our RPC calls */
struct evhttp* http_server;
/* a list of all RPCs registered with us */
TAILQ_HEAD(evrpc_list, evrpc) registered_rpcs;
};
struct evrpc_req_generic;
void evrpc_reqstate_free(struct evrpc_req_generic* rpc_state);
/* A pool for holding evhttp_connection objects */
struct evrpc_pool {
struct _evrpc_hooks common;
struct event_base *base;
struct evconq connections;
int timeout;
TAILQ_HEAD(evrpc_requestq, evrpc_request_wrapper) requests;
};
#endif /* _EVRPC_INTERNAL_H_ */

Some files were not shown because too many files have changed in this diff Show More