diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe3f3a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +CMakeCache.txt +CMakeFiles/ +CPackConfig.cmake +CPackSourceConfig.cmake +Makefile +cmake_install.cmake +pgagent +pgagent--3.4.sql +pgagent.control +*.log diff --git a/CMakeLists.txt b/CMakeLists.txt index 29755b4..5968b25 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,205 +1,213 @@ -####################################################################### -# -# pgAgent - PostgreSQL tools -# Copyright (C) 2002 - 2016, The pgAdmin Development Team -# This software is released under the PostgreSQL Licence -# -# CMakeLists.txt - CMake build configuration -# -####################################################################### - -################################################################################ -# Initial setup -################################################################################ -IF(APPLE) - CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) -ELSE() - CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -ENDIF(APPLE) - -IF(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) - -SET(CMAKE_FIND_LIBRARY_PREFIXES "") -SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") - -SET(STATIC_BUILD YES CACHE BOOL "Statically link the executable?") -################################################################################ -# Apple stuff -################################################################################ -IF(APPLE) - # Setup default values - IF(NOT HAVE_CACHED_VALUES) - - IF(EXISTS ${CMAKE_OSX_SYSROOT}) - SET(CMAKE_OSX_SYSROOT ${CMAKE_OSX_SYSROOT} CACHE FILEPATH "isysroot used for universal binary support" FORCE) - ENDIF(EXISTS ${CMAKE_OSX_SYSROOT}) - - IF(NOT ${CMAKE_OSX_ARCHITECTURES} STREQUAL "") - SET(CMAKE_OSX_ARCHITECTURES ${CMAKE_OSX_ARCHITECTURES} CACHE STRING "Build architectures for OSX" FORCE) - ELSE() - SET(CMAKE_OSX_ARCHITECTURES "ppc;i386" CACHE STRING "Build architectures for OSX" FORCE) - ENDIF(NOT ${CMAKE_OSX_ARCHITECTURES} STREQUAL "") - - ENDIF(NOT HAVE_CACHED_VALUES) - - # Target Tiger - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4") -ENDIF(APPLE) - -################################################################################ -# Project config -################################################################################ -PROJECT(pgagent) - -# If changing the version number, remember to change here and under the CPack -# settings in this file, as well as the definition for pgagent_schema_version() -# in pgagent.sql and upgrade_pgagent.sql if the major version number is -# changed. The full version number also needs to be included in pgAgent.rc and -# pgaevent/pgamsgevent.rc at present. -SET(VERSION "3.4.1") - -# CPack stuff -SET(CPACK_PACKAGE_VERSION_MAJOR 3) -SET(CPACK_PACKAGE_VERSION_MINOR 4) -SET(CPACK_PACKAGE_VERSION_PATCH 1) -SET(CPACK_PACKAGE_NAME "pgAgent") -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "pgAgent is a job scheduling engine for PostgreSQL") -SET(CPACK_PACKAGE_VENDOR "the pgAdmin Development Team") -IF(WIN32) - SET(CPACK_GENERATOR ZIP) -ELSE(WIN32) - SET(CPACK_GENERATOR TGZ) -ENDIF(WIN32) -SET(CPACK_SOURCE_GENERATOR TGZ) -SET(CPACK_SOURCE_IGNORE_FILES "\\\\.DS_Store;/CVS/;/\\\\.svn/;\\\\.swp$;\\\\.#;/#;.*~;cscope.*") - -ADD_DEFINITIONS(-DPGAGENT_VERSION_MAJOR=${CPACK_PACKAGE_VERSION_MAJOR}) -ADD_DEFINITIONS(-DPGAGENT_VERSION="${VERSION}") - -# This must come after we set the CPACK variables!! -INCLUDE(CPack) - -################################################################################ -# Find wxWidgets -################################################################################ -SET(WX_DEBUG NO CACHE BOOL "Use the debug build of wxWidgets?") -SET(WX_STATIC ${STATIC_BUILD}) -SET(WX_VERSION "2.8") -SET(WX_UNICODE YES) -SET(WX_MODULES "base") - -FIND_PACKAGE(WX REQUIRED) - -INCLUDE_DIRECTORIES(${WX_INCLUDE_DIRS}) -ADD_DEFINITIONS(${WX_DEFINITIONS}) -LINK_DIRECTORIES(${WX_LIBRARY_DIRS}) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WX_CXX_FLAGS}") - -################################################################################ -# Find PostgreSQL -################################################################################ -SET(PG_STATIC ${WX_STATIC}) - -FIND_PACKAGE(PG REQUIRED) - -INCLUDE_DIRECTORIES(${PG_INCLUDE_DIRS}) -LINK_DIRECTORIES(${PG_LIBRARY_DIRS}) - -################################################################################ -# Let's rock! -################################################################################ -INCLUDE_DIRECTORIES(${pgagent_SOURCE_DIR} - ${pgagent_SOURCE_DIR}/include) - -FILE(GLOB _cpp_files *.cpp) -FILE(GLOB _h_files include/*.h) - -SET(_srcs ${_cpp_files} ${_h_files}) - -IF(WIN32) - SET(_srcs ${_srcs} pgagent.rc) -ENDIF(WIN32) - -ADD_EXECUTABLE(pgagent ${_srcs}) -TARGET_LINK_LIBRARIES(pgagent ${PG_LIBRARIES} ${WX_LIBRARIES}) - -# Installation -IF (WIN32) - INSTALL(TARGETS pgagent DESTINATION .) - INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent.sql DESTINATION .) - INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent_upgrade.sql DESTINATION .) -ELSE(WIN32) - INSTALL(TARGETS pgagent DESTINATION bin) - INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent.sql DESTINATION share) - INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent_upgrade.sql DESTINATION share) -ENDIF(WIN32) - -INSTALL(FILES ${pgagent_SOURCE_DIR}/README DESTINATION .) -INSTALL(FILES ${pgagent_SOURCE_DIR}/LICENSE DESTINATION .) - -# Extension -IF(PG_EXTENSION) - ADD_CUSTOM_COMMAND( - OUTPUT pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql pgagent.control - COMMAND ${CMAKE_COMMAND} -D MAJOR_VERSION=${CPACK_PACKAGE_VERSION_MAJOR} -D MINOR_VERSION=${CPACK_PACKAGE_VERSION_MINOR} -P cmake/MakeExt.cmake - MAIN_DEPENDENCY sql/pgagent.sql - ) - ADD_CUSTOM_TARGET(run ALL DEPENDS pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql pgagent.control) - INSTALL(FILES pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql DESTINATION ${PG_SHARE_DIR}/extension) - FILE(GLOB SQL "${CMAKE_CURRENT_SOURCE_DIR}/sql/*--*.sql") - FILE(GLOB CONTROL "${CMAKE_CURRENT_SOURCE_DIR}/*.control") - INSTALL(FILES pgagent.control ${CONTROL} ${SQL} DESTINATION ${PG_SHARE_DIR}/extension) -ENDIF(PG_EXTENSION) - - -################################################################################ -# pgaevent -################################################################################ -IF(WIN32) - ADD_SUBDIRECTORY(pgaevent) -ENDIF(WIN32) - -################################################################################ -# Build summary -################################################################################ -MESSAGE(STATUS " ") - -MESSAGE(STATUS "================================================================================") -MESSAGE(STATUS "Configuration summary:") -MESSAGE(STATUS " ") -MESSAGE(STATUS " Project : ${PROJECT_NAME}") -MESSAGE(STATUS " Description : ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") -MESSAGE(STATUS " Version : ${VERSION}") -MESSAGE(STATUS " ") -MESSAGE(STATUS " PostgreSQL version string : ${PG_VERSION_STRING}") -IF(${PG_MAJOR_VERSION} GREATER 9) - MESSAGE(STATUS " PostgreSQL version parts : ${PG_MAJOR_VERSION}") -ELSE() - MESSAGE(STATUS " PostgreSQL version parts : ${PG_MAJOR_VERSION}.${PG_MINOR_VERSION}") -ENDIF(${PG_MAJOR_VERSION} GREATER 10) -MESSAGE(STATUS " PostgreSQL path : ${PG_ROOT_DIR}") -MESSAGE(STATUS " PostgreSQL config binary : ${PG_CONFIG_PATH}") -MESSAGE(STATUS " PostgreSQL include path : ${PG_INCLUDE_DIRS}") -MESSAGE(STATUS " PostgreSQL library path : ${PG_LIBRARY_DIRS}") -MESSAGE(STATUS " PostgreSQL share path : ${PG_SHARE_DIR}") -MESSAGE(STATUS " ") -MESSAGE(STATUS " wxWidgets version : ${WX_VERSION_STRING}") -MESSAGE(STATUS " wxWidgets path : ${WX_ROOT_DIR}") -MESSAGE(STATUS " wxWidgets config binary : ${WX_CONFIG_PATH}") -MESSAGE(STATUS " wxWidgets Static linking : ${WX_STATIC}") -MESSAGE(STATUS " wxWidgets Debug? : ${WX_DEBUG}") -MESSAGE(STATUS "================================================================================") -MESSAGE(STATUS " ") - -################################################################################ -# Give ourselves a hint that we have cached values - must be last! -################################################################################ -IF(NOT HAVE_CACHED_VALUES) - SET(HAVE_CACHED_VALUES 1 CACHE INTERNAL "Flag to indicate that we have cached values") -ENDIF(NOT HAVE_CACHED_VALUES) - - +####################################################################### +# +# pgAgent - PostgreSQL tools +# Copyright (C) 2002 - 2016, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +# CMakeLists.txt - CMake build configuration +# +####################################################################### + +################################################################################ +# Initial setup +################################################################################ +IF(APPLE) + CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) +ELSE() + CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +ENDIF(APPLE) + +IF(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) + +SET(CMAKE_FIND_LIBRARY_PREFIXES "") +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") + +SET(STATIC_BUILD NO CACHE BOOL "Statically link the executable?") +SET(BOOST_MULTITHREADED_BUILD YES CACHE BOOL "Build multithreaded executable?") +SET(BOOST_STATIC_BUILD NO CACHE BOOL "Statically link the executable?") +################################################################################ +# Apple stuff +################################################################################ +IF(APPLE) + # Setup default values + IF(NOT HAVE_CACHED_VALUES) + + IF(EXISTS ${CMAKE_OSX_SYSROOT}) + SET(CMAKE_OSX_SYSROOT ${CMAKE_OSX_SYSROOT} CACHE FILEPATH "isysroot used for universal binary support" FORCE) + ENDIF(EXISTS ${CMAKE_OSX_SYSROOT}) + + IF(NOT ${CMAKE_OSX_ARCHITECTURES} STREQUAL "") + SET(CMAKE_OSX_ARCHITECTURES ${CMAKE_OSX_ARCHITECTURES} CACHE STRING "Build architectures for OSX" FORCE) + ELSE() + SET(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Build architectures for OSX" FORCE) + ENDIF(NOT ${CMAKE_OSX_ARCHITECTURES} STREQUAL "") + + ENDIF(NOT HAVE_CACHED_VALUES) + + # Target Tiger + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.9") +ENDIF(APPLE) + +################################################################################ +# Project config +################################################################################ +PROJECT(pgagent) + +# If changing the version number, remember to change here and under the CPack +# settings in this file, as well as the definition for pgagent_schema_version() +# in pgagent.sql and upgrade_pgagent.sql if the major version number is +# changed. The full version number also needs to be included in pgAgent.rc and +# pgaevent/pgamsgevent.rc at present. +SET(VERSION "3.4.1") + +# CPack stuff +SET(CPACK_PACKAGE_VERSION_MAJOR 3) +SET(CPACK_PACKAGE_VERSION_MINOR 4) +SET(CPACK_PACKAGE_VERSION_PATCH 1) +SET(CPACK_PACKAGE_NAME "pgAgent") +SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "pgAgent is a job scheduling engine for PostgreSQL") +SET(CPACK_PACKAGE_VENDOR "the pgAdmin Development Team") +IF(WIN32) + SET(CPACK_GENERATOR ZIP) +ELSE(WIN32) + SET(CPACK_GENERATOR TGZ) +ENDIF(WIN32) +SET(CPACK_SOURCE_GENERATOR TGZ) +SET(CPACK_SOURCE_IGNORE_FILES "\\\\.DS_Store;/CVS/;/\\\\.svn/;\\\\.swp$;\\\\.#;/#;.*~;cscope.*") + +ADD_DEFINITIONS(-DPGAGENT_VERSION_MAJOR=${CPACK_PACKAGE_VERSION_MAJOR}) +ADD_DEFINITIONS(-DPGAGENT_VERSION="${VERSION}") + +IF(WIN32) + SET(BOOST_WIN_VERSION 0x0501) + ADD_DEFINITIONS(-D_WIN32_WINNT=${BOOST_WIN_VERSION} -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS) +ENDIF(WIN32) + +# This must come after we set the CPACK variables!! +INCLUDE(CPack) + +################################################################################ +# Find PostgreSQL +################################################################################ +SET(PG_STATIC ${STATIC_BUILD}) + +FIND_PACKAGE(PG REQUIRED) + +INCLUDE_DIRECTORIES(${PG_INCLUDE_DIRS}) +LINK_DIRECTORIES(${PG_LIBRARY_DIRS}) + +################################################################################ +# Find Boost Libraries +################################################################################ +SET (Boost_FIND_REQUIRED TRUE) +SET (Boost_FIND_QUIETLY FALSE) +SET (Boost_DEBUG FALSE) +SET (Boost_USE_MULTITHREADED ${BOOST_MULTITHREADED_BUILD}) +SET (Boost_USE_STATIC_LIBS ${BOOST_STATIC_BUILD}) + +FIND_PACKAGE(Boost COMPONENTS filesystem regex date_time thread system) + +if(Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}) +ELSE() + MESSAGE(FATAL_ERROR "Boost library not found.") +endif() + +################################################################################ +# Let's rock! +################################################################################ +INCLUDE_DIRECTORIES(${pgagent_SOURCE_DIR} + ${pgagent_SOURCE_DIR}/include) + +FILE(GLOB _cpp_files *.cpp) +FILE(GLOB _h_files include/*.h) + +SET(_srcs ${_cpp_files} ${_h_files}) + +IF(WIN32) + SET(_srcs ${_srcs} pgagent.rc) +ENDIF(WIN32) + +ADD_EXECUTABLE(pgagent ${_srcs}) +TARGET_LINK_LIBRARIES( + pgagent ${PG_LIBRARIES} ${Boost_LIBRARIES} +) + +# Installation +IF (WIN32) + INSTALL(TARGETS pgagent DESTINATION .) + INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent.sql DESTINATION .) + INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent_upgrade.sql DESTINATION .) +ELSE(WIN32) + INSTALL(TARGETS pgagent DESTINATION bin) + INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent.sql DESTINATION share) + INSTALL(FILES ${pgagent_SOURCE_DIR}/sql/pgagent_upgrade.sql DESTINATION share) +ENDIF(WIN32) + +INSTALL(FILES ${pgagent_SOURCE_DIR}/README DESTINATION .) +INSTALL(FILES ${pgagent_SOURCE_DIR}/LICENSE DESTINATION .) + +# Extension +IF(PG_EXTENSION) + ADD_CUSTOM_COMMAND( + OUTPUT ${CMAKE_BINARY_DIR}/pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql pgagent.control + COMMAND ${CMAKE_COMMAND} -D MAJOR_VERSION=${CPACK_PACKAGE_VERSION_MAJOR} -D MINOR_VERSION=${CPACK_PACKAGE_VERSION_MINOR} -DPGAGENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/MakeExt.cmake + MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/sql/pgagent.sql + ) + ADD_CUSTOM_TARGET(run ALL DEPENDS ${CMAKE_BINARY_DIR}/pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql ${CMAKE_BINARY_DIR}/pgagent.control) + INSTALL(FILES ${CMAKE_BINARY_DIR}/pgagent--${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.sql DESTINATION ${PG_SHARE_DIR}/extension) + FILE(GLOB SQL "${CMAKE_CURRENT_SOURCE_DIR}/sql/*--*.sql") + FILE(GLOB CONTROL "${CMAKE_CURRENT_SOURCE_DIR}/*.control") + INSTALL(FILES ${CMAKE_BINARY_DIR}/pgagent.control ${CONTROL} ${SQL} DESTINATION ${PG_SHARE_DIR}/extension) +ENDIF(PG_EXTENSION) + +################################################################################ +# pgaevent +################################################################################ +IF(WIN32) + ADD_SUBDIRECTORY(pgaevent) +ENDIF(WIN32) + +################################################################################ +# Build summary +################################################################################ +MESSAGE(STATUS " ") + +MESSAGE(STATUS "================================================================================") +MESSAGE(STATUS "Configuration summary:") +MESSAGE(STATUS " ") +MESSAGE(STATUS " Project : ${PROJECT_NAME}") +MESSAGE(STATUS " Description : ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") +MESSAGE(STATUS " Version : ${VERSION}") +MESSAGE(STATUS " ") +MESSAGE(STATUS " PostgreSQL version string : ${PG_VERSION_STRING}") +IF(${PG_MAJOR_VERSION} GREATER 9) + MESSAGE(STATUS " PostgreSQL version parts : ${PG_MAJOR_VERSION}") +ELSE() + MESSAGE(STATUS " PostgreSQL version parts : ${PG_MAJOR_VERSION}.${PG_MINOR_VERSION}") +ENDIF(${PG_MAJOR_VERSION} GREATER 9) +MESSAGE(STATUS " PostgreSQL path : ${PG_ROOT_DIR}") +MESSAGE(STATUS " PostgreSQL config binary : ${PG_CONFIG_PATH}") +MESSAGE(STATUS " PostgreSQL include path : ${PG_INCLUDE_DIRS}") +MESSAGE(STATUS " PostgreSQL library path : ${PG_LIBRARY_DIRS}") +MESSAGE(STATUS " PostgreSQL share path : ${PG_SHARE_DIR}") +MESSAGE(STATUS " ") +MESSAGE(STATUS " Boost version : ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") +MESSAGE(STATUS " Boost path : ${Boost_INCLUDE_DIRS}") +MESSAGE(STATUS " Boost include directory : ${Boost_INCLUDE_DIRS}") +MESSAGE(STATUS " Boost library directory : ${Boost_LIBRARY_DIRS}") +MESSAGE(STATUS " Boost Static linking : ${Boost_USE_STATIC_LIBS}") +MESSAGE(STATUS "================================================================================") +MESSAGE(STATUS " ") + +################################################################################ +# Give ourselves a hint that we have cached values - must be last! +################################################################################ +IF(NOT HAVE_CACHED_VALUES) + SET(HAVE_CACHED_VALUES 1 CACHE INTERNAL "Flag to indicate that we have cached values") +ENDIF(NOT HAVE_CACHED_VALUES) diff --git a/README b/README index d10bee9..610f4ba 100644 --- a/README +++ b/README @@ -1,51 +1,48 @@ -pgAgent -======= - -This document describes the compilation of pgAgent, a job scheduler for -PostgreSQL. - -pgAgent is managed using pgAdmin (http://www.pgadmin.org). The pgAdmin -documentation contains details of the setup and use of pgAgent with your -PostgreSQL system. The latest build of the documentation can be found at -http://www.pgadmin.org/docs/dev/pgagent.html. - -Building pgAgent ----------------- - -You will need: - -- A C/C++ compiler, such as GCC or Microsoft Visual C++ on Windows. -- CMake 2.6 (from www.cmake.org) -- A wxWidgets 2.8.x installation, configured per the requirements for - pgAdmin: - http://git.postgresql.org/gitweb/?p=pgadmin3.git;a=blob_plain;f=INSTALL;hb=HEAD -- A PostgreSQL 8.3 or higher installation - -1) Unpack the pgAgent source code -2) Create a build directory in which the code will be built. -3) Run ccmake from the build directory (on Windows, use the CMake graphical - interface). By default, ccmake will generate Unix Makefiles - consult the - documentation if you wish to generate other types of output: - -$ ccmake /path/to/pgagent - -4) If required, press 'c' to generate a default configuration: - -CMAKE_BUILD_TYPE Release -CMAKE_INSTALL_PREFIX /usr/local -CMAKE_OSX_ARCHITECTURES ppc;i386 -CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk -PostgreSQL_CONFIG_EXECUTABLE /usr/local/pgsql/bin/pg_config -wxWidgets_CONFIG_EXECUTABLE /usr/local/bin/wx-config -wxWidgets_USE_DEBUG OFF -wxWidgets_USE_STATIC ON -wxWidgets_USE_UNICODE ON -wxWidgets_wxrc_EXECUTABLE /usr/bin/wxrc - -5) Use the ccmake interface to adjust any settings as required. When configured - as required, press 'c' to re-configure (if required) and 'g' to generate the - build files and exit. - -6) Run 'make' to build pgAgent on Mac or Unix, or open the generated project - files in VC++ on Windows and build the solution in the desired configuration. - +pgAgent +======= + +This document describes the compilation of pgAgent, a job scheduler for +PostgreSQL. + +pgAgent is managed using pgAdmin (http://www.pgadmin.org). The pgAdmin +documentation contains details of the setup and use of pgAgent with your +PostgreSQL system. The latest build of the documentation can be found at +http://www.pgadmin.org/docs/dev/pgagent.html. + +Building pgAgent +---------------- + +You will need: + +- A C/C++ compiler, such as GCC or Microsoft Visual C++ on Windows. +- CMake 2.6 (from www.cmake.org) +- A Boost library 1.41 or higher installation +- A PostgreSQL 8.3 or higher installation + +1) Unpack the pgAgent source code +2) Create a build directory in which the code will be built. +3) Run ccmake from the build directory (on Windows, use the CMake graphical + interface). By default, ccmake will generate Unix Makefiles - consult the + documentation if you wish to generate other types of output: + +$ ccmake /path/to/pgagent + +4) If required, press 'c' to generate a default configuration: + +CMAKE_BUILD_TYPE Release +CMAKE_INSTALL_PREFIX /usr/local +CMAKE_OSX_ARCHITECTURES x86_64 +CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.10.sdk +PostgreSQL_CONFIG_EXECUTABLE /usr/local/pgsql/bin/pg_config +Boost_FIND_REQUIRED ON +Boost_FIND_QUIETLY OFF +Boost_DEBUG OFF +Boost_USE_MULTITHREADED ON +Boost_USE_STATIC_LIBS OFF + +5) Use the ccmake interface to adjust any settings as required. When configured + as required, press 'c' to re-configure (if required) and 'g' to generate the + build files and exit. + +6) Run 'make' to build pgAgent on Mac or Unix, or open the generated project + files in VC++ on Windows and build the solution in the desired configuration. diff --git a/cmake/FindBoost.cmake b/cmake/FindBoost.cmake new file mode 100644 index 0000000..bb853bb --- /dev/null +++ b/cmake/FindBoost.cmake @@ -0,0 +1,1214 @@ +# FindBoost +# --------- +# +# Find Boost include dirs and libraries +# +# Use this module by invoking find_package with the form:: +# +# find_package(Boost +# [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0 +# [REQUIRED] # Fail with error if Boost is not found +# [COMPONENTS ...] # Boost libraries by their canonical name +# ) # e.g. "date_time" for "libboost_date_time" +# +# This module finds headers and requested component libraries OR a CMake +# package configuration file provided by a "Boost CMake" build. For the +# latter case skip to the "Boost CMake" section below. For the former +# case results are reported in variables:: +# +# Boost_FOUND - True if headers and requested libraries were found +# Boost_INCLUDE_DIRS - Boost include directories +# Boost_LIBRARY_DIRS - Link directories for Boost libraries +# Boost_LIBRARIES - Boost component libraries to be linked +# Boost__FOUND - True if component was found ( is upper-case) +# Boost__LIBRARY - Libraries to link for component (may include +# target_link_libraries debug/optimized keywords) +# Boost_VERSION - BOOST_VERSION value from boost/version.hpp +# Boost_LIB_VERSION - Version string appended to library filenames +# Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) +# Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) +# Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) +# Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) +# - Pass to add_definitions() to have diagnostic +# information about Boost's automatic linking +# displayed during compilation +# +# This module reads hints about search locations from variables:: +# +# BOOST_ROOT - Preferred installation prefix +# (or BOOSTROOT) +# BOOST_INCLUDEDIR - Preferred include directory e.g. /include +# BOOST_LIBRARYDIR - Preferred library directory e.g. /lib +# Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not +# specified by these hint variables. Default is OFF. +# Boost_ADDITIONAL_VERSIONS +# - List of Boost versions not known to this module +# (Boost install locations may contain the version) +# +# and saves search results persistently in CMake cache entries:: +# +# Boost_INCLUDE_DIR - Directory containing Boost headers +# Boost_LIBRARY_DIR - Directory containing Boost libraries +# Boost__LIBRARY_DEBUG - Component library debug variant +# Boost__LIBRARY_RELEASE - Component library release variant +# +# Users may set these hints or results as cache entries. Projects +# should not read these entries directly but instead use the above +# result variables. Note that some hint names start in upper-case +# "BOOST". One may specify these as environment variables if they are +# not specified as CMake variables or cache entries. +# +# This module first searches for the Boost header files using the above +# hint variables (excluding BOOST_LIBRARYDIR) and saves the result in +# Boost_INCLUDE_DIR. Then it searches for requested component libraries +# using the above hints (excluding BOOST_INCLUDEDIR and +# Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, +# and the library name configuration settings below. It saves the +# library directory in Boost_LIBRARY_DIR and individual library +# locations in Boost__LIBRARY_DEBUG and Boost__LIBRARY_RELEASE. +# When one changes settings used by previous searches in the same build +# tree (excluding environment variables) this module discards previous +# search results affected by the changes and searches again. +# +# Boost libraries come in many variants encoded in their file name. +# Users or projects may tell this module which variant to find by +# setting variables:: +# +# Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded +# libraries ('mt' tag). Default is ON. +# Boost_USE_STATIC_LIBS - Set to ON to force the use of the static +# libraries. Default is OFF. +# Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use +# libraries linked statically to the C++ runtime +# ('s' tag). Default is platform dependent. +# Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use +# libraries linked to the MS debug C++ runtime +# ('g' tag). Default is ON. +# Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a +# debug Python build ('y' tag). Default is OFF. +# Boost_USE_STLPORT - Set to ON to use libraries compiled with +# STLPort ('p' tag). Default is OFF. +# Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS +# - Set to ON to use libraries compiled with +# STLPort deprecated "native iostreams" +# ('n' tag). Default is OFF. +# Boost_COMPILER - Set to the compiler-specific library suffix +# (e.g. "-gcc43"). Default is auto-computed +# for the C++ compiler in use. +# Boost_THREADAPI - Suffix for "thread" component library name, +# such as "pthread" or "win32". Names with +# and without this suffix will both be tried. +# Boost_NAMESPACE - Alternate namespace used to build boost with +# e.g. if set to "myboost", will search for +# myboost_thread instead of boost_thread. +# +# Other variables one may set to control this module are:: +# +# Boost_DEBUG - Set to ON to enable debug output from FindBoost. +# Please enable this before filing any bug report. +# Boost_DETAILED_FAILURE_MSG +# - Set to ON to add detailed information to the +# failure message even when the REQUIRED option +# is not given to the find_package call. +# Boost_REALPATH - Set to ON to resolve symlinks for discovered +# libraries to assist with packaging. For example, +# the "system" component library may be resolved to +# "/usr/lib/libboost_system.so.1.42.0" instead of +# "/usr/lib/libboost_system.so". This does not +# affect linking and should not be enabled unless +# the user needs this information. +# +# On Visual Studio and Borland compilers Boost headers request automatic +# linking to corresponding libraries. This requires matching libraries +# to be linked explicitly or available in the link library search path. +# In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve +# dynamic linking. Boost automatic linking typically requests static +# libraries with a few exceptions (such as Boost.Python). Use:: +# +# add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) +# +# to ask Boost to report information about automatic linking requests. +# +# Example to find Boost headers only:: +# +# find_package(Boost 1.36.0) +# if(Boost_FOUND) +# include_directories(${Boost_INCLUDE_DIRS}) +# add_executable(foo foo.cc) +# endif() +# +# Example to find Boost headers and some *static* libraries:: +# +# set(Boost_USE_STATIC_LIBS ON) # only find static libs +# set(Boost_USE_MULTITHREADED ON) +# set(Boost_USE_STATIC_RUNTIME OFF) +# find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...) +# if(Boost_FOUND) +# include_directories(${Boost_INCLUDE_DIRS}) +# add_executable(foo foo.cc) +# target_link_libraries(foo ${Boost_LIBRARIES}) +# endif() +# +# Boost CMake +# ^^^^^^^^^^^ +# +# If Boost was built using the boost-cmake project it provides a package +# configuration file for use with find_package's Config mode. This +# module looks for the package configuration file called +# BoostConfig.cmake or boost-config.cmake and stores the result in cache +# entry "Boost_DIR". If found, the package configuration file is loaded +# and this module returns with no further action. See documentation of +# the Boost CMake package configuration for details on what it provides. +# +# Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. + +#------------------------------------------------------------------------------- +# Before we go searching, check whether boost-cmake is available, unless the +# user specifically asked NOT to search for boost-cmake. +# +# If Boost_DIR is set, this behaves as any find_package call would. If not, +# it looks at BOOST_ROOT and BOOSTROOT to find Boost. +# + +if (NOT Boost_NO_BOOST_CMAKE) + # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, + # since these are more conventional for Boost. + if ("$ENV{Boost_DIR}" STREQUAL "") + if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") + set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) + elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") + set(ENV{Boost_DIR} $ENV{BOOSTROOT}) + endif() + endif() + + # Do the same find_package call but look specifically for the CMake version. + # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no + # need to delegate them to this find_package call. + find_package(Boost QUIET NO_MODULE) + mark_as_advanced(Boost_DIR) + + # If we found boost-cmake, then we're done. Print out what we found. + # Otherwise let the rest of the module try to find it. + if (Boost_FOUND) + message("Boost ${Boost_FIND_VERSION} found.") + if (Boost_FIND_COMPONENTS) + message("Found Boost components:") + message(" ${Boost_FIND_COMPONENTS}") + endif() + return() + endif() +endif() + + +#------------------------------------------------------------------------------- +# FindBoost functions & macros +# + +############################################ +# +# Check the existence of the libraries. +# +############################################ +# This macro was taken directly from the FindQt4.cmake file that is included +# with the CMake distribution. This is NOT my work. All work was done by the +# original authors of the FindQt4.cmake file. Only minor modifications were +# made to remove references to Qt and make this file more generally applicable +# And ELSE/ENDIF pairs were removed for readability. +######################################################################### + +macro(_Boost_ADJUST_LIB_VARS basename) + if(Boost_INCLUDE_DIR ) + if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) + # if the generator supports configuration types then set + # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value + if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) + else() + # if there are no configuration types and CMAKE_BUILD_TYPE has no value + # then just use the release libraries + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) + endif() + # FIXME: This probably should be set for both cases + set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) + endif() + + # if only the release version was found, set the debug variable also to the release version + if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) + set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) + endif() + + # if only the debug version was found, set the release variable also to the debug version + if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) + set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) + endif() + + # If the debug & release library ends up being the same, omit the keywords + if(${Boost_${basename}_LIBRARY_RELEASE} STREQUAL ${Boost_${basename}_LIBRARY_DEBUG}) + set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) + set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) + endif() + + if(Boost_${basename}_LIBRARY) + set(Boost_${basename}_FOUND ON) + endif() + + endif() + # Make variables changeable to the advanced user + mark_as_advanced( + Boost_${basename}_LIBRARY_RELEASE + Boost_${basename}_LIBRARY_DEBUG + ) +endmacro() + +macro(_Boost_CHANGE_DETECT changed_var) + set(${changed_var} 0) + foreach(v ${ARGN}) + if(DEFINED _Boost_COMPONENTS_SEARCHED) + if(${v}) + if(_${v}_LAST) + string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) + else() + set(_${v}_CHANGED 1) + endif() + elseif(_${v}_LAST) + set(_${v}_CHANGED 1) + endif() + if(_${v}_CHANGED) + set(${changed_var} 1) + endif() + else() + set(_${v}_CHANGED 0) + endif() + endforeach() +endmacro() + +macro(_Boost_FIND_LIBRARY var) + find_library(${var} ${ARGN}) + + if(${var}) + # If this is the first library found then save Boost_LIBRARY_DIR. + if(NOT Boost_LIBRARY_DIR) + get_filename_component(_dir "${${var}}" PATH) + set(Boost_LIBRARY_DIR "${_dir}" CACHE PATH "Boost library directory" FORCE) + endif() + elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) + # Try component-specific hints but do not save Boost_LIBRARY_DIR. + find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) + endif() + + # If Boost_LIBRARY_DIR is known then search only there. + if(Boost_LIBRARY_DIR) + set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) + endif() +endmacro() + +#------------------------------------------------------------------------------- + +# +# Runs compiler with "-dumpversion" and parses major/minor +# version with a regex. +# +function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) + + exec_program(${CMAKE_CXX_COMPILER} + ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion + OUTPUT_VARIABLE _boost_COMPILER_VERSION + ) + string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2" + _boost_COMPILER_VERSION ${_boost_COMPILER_VERSION}) + + set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) +endfunction() + +# +# Take a list of libraries with "thread" in it +# and prepend duplicates with "thread_${Boost_THREADAPI}" +# at the front of the list +# +function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) + set(_orig_libnames ${ARGN}) + string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") + set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) +endfunction() + +# +# If a library is found, replace its cache entry with its REALPATH +# +function(_Boost_SWAP_WITH_REALPATH _library _docstring) + if(${_library}) + get_filename_component(_boost_filepathreal ${${_library}} REALPATH) + unset(${_library} CACHE) + set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") + endif() +endfunction() + +function(_Boost_CHECK_SPELLING _var) + if(${_var}) + string(TOUPPER ${_var} _var_UC) + message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") + endif() +endfunction() + +# Guesses Boost's compiler prefix used in built library names +# Returns the guess by setting the variable pointed to by _ret +function(_Boost_GUESS_COMPILER_PREFIX _ret) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel" + OR CMAKE_CXX_COMPILER MATCHES "icl" + OR CMAKE_CXX_COMPILER MATCHES "icpc") + if(WIN32) + set (_boost_COMPILER "-iw") + else() + set (_boost_COMPILER "-il") + endif() + elseif (MSVC14) + set(_boost_COMPILER "-vc140") + elseif (MSVC12) + set(_boost_COMPILER "-vc120") + elseif (MSVC11) + set(_boost_COMPILER "-vc110") + elseif (MSVC10) + set(_boost_COMPILER "-vc100") + elseif (MSVC90) + set(_boost_COMPILER "-vc90") + elseif (MSVC80) + set(_boost_COMPILER "-vc80") + elseif (MSVC71) + set(_boost_COMPILER "-vc71") + elseif (MSVC70) # Good luck! + set(_boost_COMPILER "-vc7") # yes, this is correct + elseif (MSVC60) # Good luck! + set(_boost_COMPILER "-vc6") # yes, this is correct + elseif (BORLAND) + set(_boost_COMPILER "-bcb") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") + set(_boost_COMPILER "-sw") + elseif (MINGW) + if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) + set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 + else() + _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) + set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") + endif() + elseif (UNIX) + if (CMAKE_COMPILER_IS_GNUCXX) + if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) + set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 + else() + _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) + # Determine which version of GCC we have. + if(APPLE) + if(Boost_MINOR_VERSION) + if(${Boost_MINOR_VERSION} GREATER 35) + # In Boost 1.36.0 and newer, the mangled compiler name used + # on Mac OS X/Darwin is "xgcc". + set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") + else() + # In Boost <= 1.35.0, there is no mangled compiler name for + # the Mac OS X/Darwin version of GCC. + set(_boost_COMPILER "") + endif() + else() + # We don't know the Boost version, so assume it's + # pre-1.36.0. + set(_boost_COMPILER "") + endif() + else() + set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") + endif() + endif() + endif () + else() + # TODO at least Boost_DEBUG here? + set(_boost_COMPILER "") + endif() + set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) +endfunction() + +# +# End functions/macros +# +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# main. +#------------------------------------------------------------------------------- + +if(NOT DEFINED Boost_USE_MULTITHREADED) + set(Boost_USE_MULTITHREADED TRUE) +endif() +if(NOT DEFINED Boost_USE_DEBUG_RUNTIME) + set(Boost_USE_DEBUG_RUNTIME TRUE) +endif() + +# Check the version of Boost against the requested version. +if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) + message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") +endif() + +if(Boost_FIND_VERSION_EXACT) + # The version may appear in a directory with or without the patch + # level, even when the patch level is non-zero. + set(_boost_TEST_VERSIONS + "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" + "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") +else() + # The user has not requested an exact version. Among known + # versions, find those that are acceptable to the user request. + set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} + "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" + "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" + "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" + "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" + "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" + "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" + "1.34" "1.33.1" "1.33.0" "1.33") + set(_boost_TEST_VERSIONS) + if(Boost_FIND_VERSION) + set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") + # Select acceptable versions. + foreach(version ${_Boost_KNOWN_VERSIONS}) + if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") + # This version is high enough. + list(APPEND _boost_TEST_VERSIONS "${version}") + elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") + # This version is a short-form for the requested version with + # the patch level dropped. + list(APPEND _boost_TEST_VERSIONS "${version}") + endif() + endforeach() + else() + # Any version is acceptable. + set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") + endif() +endif() + +# The reason that we failed to find Boost. This will be set to a +# user-friendly message when we fail to find some necessary piece of +# Boost. +set(Boost_ERROR_REASON) + +if(Boost_DEBUG) + # Output some of their choices + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") +endif() + +if(WIN32) + # In windows, automatic linking is performed, so you do not have + # to specify the libraries. If you are linking to a dynamic + # runtime, then you can choose to link to either a static or a + # dynamic Boost library, the default is to do a static link. You + # can alter this for a specific library "whatever" by defining + # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be + # linked dynamically. Alternatively you can force all Boost + # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. + + # This feature can be disabled for Boost library "whatever" by + # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining + # BOOST_ALL_NO_LIB. + + # If you want to observe which libraries are being linked against + # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking + # code to emit a #pragma message each time a library is selected + # for linking. + set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") +endif() + +_Boost_CHECK_SPELLING(Boost_ROOT) +_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) +_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) + +# Collect environment variable inputs as hints. Do not consider changes. +foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) + set(_env $ENV{${v}}) + if(_env) + file(TO_CMAKE_PATH "${_env}" _ENV_${v}) + else() + set(_ENV_${v} "") + endif() +endforeach() +if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) + set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") +endif() + +# Collect inputs and cached results. Detect changes since the last run. +if(NOT BOOST_ROOT AND BOOSTROOT) + set(BOOST_ROOT "${BOOSTROOT}") +endif() +set(_Boost_VARS_DIR + BOOST_ROOT + Boost_NO_SYSTEM_PATHS + ) + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Declared as CMake or Environmental Variables:") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_ROOT = ${BOOST_ROOT}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") +endif() + +# ------------------------------------------------------------------------ +# Search for Boost include DIR +# ------------------------------------------------------------------------ + +set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) +_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) +# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the +# location did. We will find a new one based on the new inputs. +if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) + unset(Boost_INCLUDE_DIR CACHE) +endif() + +if(NOT Boost_INCLUDE_DIR) + set(_boost_INCLUDE_SEARCH_DIRS "") + if(BOOST_INCLUDEDIR) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) + elseif(_ENV_BOOST_INCLUDEDIR) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) + endif() + + if( BOOST_ROOT ) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) + elseif( _ENV_BOOST_ROOT ) + list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) + endif() + + if( Boost_NO_SYSTEM_PATHS) + list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) + else() + list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS + C:/boost/include + C:/boost + /sw/local/include + ) + endif() + + # Try to find Boost by stepping backwards through the Boost versions + # we know about. + # Build a list of path suffixes for each version. + set(_boost_PATH_SUFFIXES) + foreach(_boost_VER ${_boost_TEST_VERSIONS}) + # Add in a path suffix, based on the required version, ideally + # we could read this from version.hpp, but for that to work we'd + # need to know the include dir already + set(_boost_BOOSTIFIED_VERSION) + + # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 + if(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") + set(_boost_BOOSTIFIED_VERSION + "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}_${CMAKE_MATCH_3}") + elseif(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)") + set(_boost_BOOSTIFIED_VERSION + "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") + endif() + + list(APPEND _boost_PATH_SUFFIXES + "boost-${_boost_BOOSTIFIED_VERSION}" + "boost_${_boost_BOOSTIFIED_VERSION}" + "boost/boost-${_boost_BOOSTIFIED_VERSION}" + "boost/boost_${_boost_BOOSTIFIED_VERSION}" + ) + + endforeach() + + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Include debugging info:") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") + endif() + + # Look for a standard boost header file. + find_path(Boost_INCLUDE_DIR + NAMES boost/config.hpp + HINTS ${_boost_INCLUDE_SEARCH_DIRS} + PATH_SUFFIXES ${_boost_PATH_SUFFIXES} + ) +endif() + +# ------------------------------------------------------------------------ +# Extract version information from version.hpp +# ------------------------------------------------------------------------ + +# Set Boost_FOUND based only on header location and version. +# It will be updated below for component libraries. +if(Boost_INCLUDE_DIR) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") + endif() + + # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp + set(Boost_VERSION 0) + set(Boost_LIB_VERSION "") + file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") + set(_Boost_VERSION_REGEX "([0-9]+)") + set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") + foreach(v VERSION LIB_VERSION) + if("${_boost_VERSION_HPP_CONTENTS}" MATCHES "#define BOOST_${v} ${_Boost_${v}_REGEX}") + set(Boost_${v} "${CMAKE_MATCH_1}") + endif() + endforeach() + unset(_boost_VERSION_HPP_CONTENTS) + + math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") + math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") + math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") + + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "version.hpp reveals boost " + "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + endif() + + if(Boost_FIND_VERSION) + # Set Boost_FOUND based on requested version. + set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") + set(Boost_FOUND 0) + set(_Boost_VERSION_AGE "old") + elseif(Boost_FIND_VERSION_EXACT AND + NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") + set(Boost_FOUND 0) + set(_Boost_VERSION_AGE "new") + else() + set(Boost_FOUND 1) + endif() + if(NOT Boost_FOUND) + # State that we found a version of Boost that is too new or too old. + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") + if (Boost_FIND_VERSION_PATCH) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}.${Boost_FIND_VERSION_PATCH}") + endif () + if (NOT Boost_FIND_VERSION_EXACT) + set(Boost_ERROR_REASON "${Boost_ERROR_REASON} (or newer)") + endif () + set(Boost_ERROR_REASON "${Boost_ERROR_REASON}.") + endif () + else() + # Caller will accept any Boost version. + set(Boost_FOUND 1) + endif() +else() + set(Boost_FOUND 0) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") +endif() + +# ------------------------------------------------------------------------ +# Prefix initialization +# ------------------------------------------------------------------------ + +set(Boost_LIB_PREFIX "") +if ( WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) + set(Boost_LIB_PREFIX "lib") +endif() + +if ( NOT Boost_NAMESPACE ) + set(Boost_NAMESPACE "boost") +endif() + +# ------------------------------------------------------------------------ +# Suffix initialization and compiler suffix detection. +# ------------------------------------------------------------------------ + +set(_Boost_VARS_NAME + Boost_NAMESPACE + Boost_COMPILER + Boost_THREADAPI + Boost_USE_DEBUG_PYTHON + Boost_USE_MULTITHREADED + Boost_USE_STATIC_LIBS + Boost_USE_STATIC_RUNTIME + Boost_USE_STLPORT + Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS + ) +_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) + +# Setting some more suffixes for the library +if (Boost_COMPILER) + set(_boost_COMPILER ${Boost_COMPILER}) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "using user-specified Boost_COMPILER = ${_boost_COMPILER}") + endif() +else() + # Attempt to guess the compiler suffix + # NOTE: this is not perfect yet, if you experience any issues + # please report them and use the Boost_COMPILER variable + # to work around the problems. + _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "guessed _boost_COMPILER = ${_boost_COMPILER}") + endif() +endif() + +set (_boost_MULTITHREADED "-mt") +if( NOT Boost_USE_MULTITHREADED ) + set (_boost_MULTITHREADED "") +endif() +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") +endif() + +#====================== +# Systematically build up the Boost ABI tag +# http://boost.org/doc/libs/1_41_0/more/getting_started/windows.html#library-naming +set( _boost_RELEASE_ABI_TAG "-") +set( _boost_DEBUG_ABI_TAG "-") +# Key Use this library when: +# s linking statically to the C++ standard library and +# compiler runtime support libraries. +if(Boost_USE_STATIC_RUNTIME) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") +endif() +# g using debug versions of the standard and runtime +# support libraries +if(WIN32 AND Boost_USE_DEBUG_RUNTIME) + if(MSVC OR "${CMAKE_CXX_COMPILER}" MATCHES "icl" + OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc") + set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}g") + endif() +endif() +# y using special debug build of python +if(Boost_USE_DEBUG_PYTHON) + set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}y") +endif() +# d using a debug version of your code +set(_boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}d") +# p using the STLport standard library rather than the +# default one supplied with your compiler +if(Boost_USE_STLPORT) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}p") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}p") +endif() +# n using the STLport deprecated "native iostreams" feature +if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) + set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}n") + set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}n") +endif() + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") +endif() + +# ------------------------------------------------------------------------ +# Begin finding boost libraries +# ------------------------------------------------------------------------ +set(_Boost_VARS_LIB BOOST_LIBRARYDIR Boost_LIBRARY_DIR) +_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR ${_Boost_VARS_DIR} ${_Boost_VARS_LIB} Boost_INCLUDE_DIR) +# Clear Boost_LIBRARY_DIR if it did not change but other input affecting the +# location did. We will find a new one based on the new inputs. +if(_Boost_CHANGE_LIBDIR AND NOT _Boost_LIBRARY_DIR_CHANGED) + unset(Boost_LIBRARY_DIR CACHE) +endif() + +if(Boost_LIBRARY_DIR) + set(_boost_LIBRARY_SEARCH_DIRS ${Boost_LIBRARY_DIR} NO_DEFAULT_PATH) +else() + set(_boost_LIBRARY_SEARCH_DIRS "") + if(BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_LIBRARYDIR}) + elseif(_ENV_BOOST_LIBRARYDIR) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_LIBRARYDIR}) + endif() + + if(BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) + elseif(_ENV_BOOST_ROOT) + list(APPEND _boost_LIBRARY_SEARCH_DIRS ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) + endif() + + list(APPEND _boost_LIBRARY_SEARCH_DIRS + ${Boost_INCLUDE_DIR}/lib + ${Boost_INCLUDE_DIR}/../lib + ${Boost_INCLUDE_DIR}/stage/lib + ) + if( Boost_NO_SYSTEM_PATHS ) + list(APPEND _boost_LIBRARY_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH) + else() + list(APPEND _boost_LIBRARY_SEARCH_DIRS PATHS + C:/boost/lib + C:/boost + /sw/local/lib + ) + endif() +endif() + +if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_boost_LIBRARY_SEARCH_DIRS = ${_boost_LIBRARY_SEARCH_DIRS}") +endif() + +# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES +if( Boost_USE_STATIC_LIBS ) + set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES .a ) + endif() +endif() + +# We want to use the tag inline below without risking double dashes +if(_boost_RELEASE_ABI_TAG) + if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") + set(_boost_RELEASE_ABI_TAG "") + endif() +endif() +if(_boost_DEBUG_ABI_TAG) + if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") + set(_boost_DEBUG_ABI_TAG "") + endif() +endif() + +# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled +# on WIN32 was to: +# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) +# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) +# We maintain this behavior since changing it could break people's builds. +# To disable the ambiguous behavior, the user need only +# set Boost_USE_STATIC_RUNTIME either ON or OFF. +set(_boost_STATIC_RUNTIME_WORKAROUND false) +if(WIN32 AND Boost_USE_STATIC_LIBS) + if(NOT DEFINED Boost_USE_STATIC_RUNTIME) + set(_boost_STATIC_RUNTIME_WORKAROUND true) + endif() +endif() + +# On versions < 1.35, remove the System library from the considered list +# since it wasn't added until 1.35. +if(Boost_VERSION AND Boost_FIND_COMPONENTS) + if(Boost_VERSION LESS 103500) + list(REMOVE_ITEM Boost_FIND_COMPONENTS system) + endif() +endif() + +# If the user changed any of our control inputs flush previous results. +if(_Boost_CHANGE_LIBDIR OR _Boost_CHANGE_LIBNAME) + foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + foreach(c DEBUG RELEASE) + set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) + unset(${_var} CACHE) + set(${_var} "${_var}-NOTFOUND") + endforeach() + endforeach() + set(_Boost_COMPONENTS_SEARCHED "") +endif() + +foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + + set( _boost_docstring_release "Boost ${COMPONENT} library (release)") + set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") + + # Compute component-specific hints. + set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "") + if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR + ${COMPONENT} STREQUAL "graph_parallel") + foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}) + if(IS_ABSOLUTE "${lib}") + get_filename_component(libdir "${lib}" PATH) + string(REPLACE "\\" "/" libdir "${libdir}") + list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir}) + endif() + endforeach() + endif() + + # Consolidate and report component-specific hints. + if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) + list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Component-specific library search paths for ${COMPONENT}: " + "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT}") + endif() + endif() + + # + # Find RELEASE libraries + # + set(_boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) + if(_boost_STATIC_RUNTIME_WORKAROUND) + set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") + list(APPEND _boost_RELEASE_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) + endif() + if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") + _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) + endif() + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") + endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE + NAMES ${_boost_RELEASE_NAMES} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} + NAMES_PER_DIR + DOC "${_boost_docstring_release}" + ) + + # + # Find DEBUG libraries + # + set(_boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) + if(_boost_STATIC_RUNTIME_WORKAROUND) + set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") + list(APPEND _boost_DEBUG_NAMES + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_COMPILER}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}-${Boost_LIB_VERSION} + ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) + endif() + if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") + _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) + endif() + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") + endif() + + # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. + string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS}") + + _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG + NAMES ${_boost_DEBUG_NAMES} + HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} + NAMES_PER_DIR + DOC "${_boost_docstring_debug}" + ) + + if(Boost_REALPATH) + _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") + _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) + endif() + + _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) + +endforeach() + +# Restore the original find library ordering +if( Boost_USE_STATIC_LIBS ) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) +endif() + +# ------------------------------------------------------------------------ +# End finding boost libraries +# ------------------------------------------------------------------------ + +set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) +set(Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR}) + +# The above setting of Boost_FOUND was based only on the header files. +# Update it for the requested component libraries. +if(Boost_FOUND) + # The headers were found. Check for requested component libs. + set(_boost_CHECKED_COMPONENT FALSE) + set(_Boost_MISSING_COMPONENTS "") + foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} COMPONENT) + set(_boost_CHECKED_COMPONENT TRUE) + if(NOT Boost_${COMPONENT}_FOUND) + string(TOLOWER ${COMPONENT} COMPONENT) + list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) + endif() + endforeach() + + if(Boost_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") + endif() + + if (_Boost_MISSING_COMPONENTS) + set(Boost_FOUND 0) + # We were unable to find some libraries, so generate a sensible + # error message that lists the libraries we were unable to find. + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}\nCould not find the following") + if(Boost_USE_STATIC_LIBS) + set(Boost_ERROR_REASON "${Boost_ERROR_REASON} static") + endif() + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON} Boost libraries:\n") + foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON} ${Boost_NAMESPACE}_${COMPONENT}\n") + endforeach() + + list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) + list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) + if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + else () + set(Boost_ERROR_REASON + "${Boost_ERROR_REASON}Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") + endif () + endif () + + if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) + # Compatibility Code for backwards compatibility with CMake + # 2.4's FindBoost module. + + # Look for the boost library path. + # Note that the user may not have installed any libraries + # so it is quite possible the Boost_LIBRARY_DIRS may not exist. + set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) + + if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") + get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) + endif() + + if("${_boost_LIB_DIR}" MATCHES "/include$") + # Strip off the trailing "/include" in the path. + get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) + endif() + + if(EXISTS "${_boost_LIB_DIR}/lib") + set(_boost_LIB_DIR ${_boost_LIB_DIR}/lib) + else() + if(EXISTS "${_boost_LIB_DIR}/stage/lib") + set(_boost_LIB_DIR ${_boost_LIB_DIR}/stage/lib) + else() + set(_boost_LIB_DIR "") + endif() + endif() + + if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") + set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) + endif() + + endif() +else() + # Boost headers were not found so no components were found. + foreach(COMPONENT ${Boost_FIND_COMPONENTS}) + string(TOUPPER ${COMPONENT} UPPERCOMPONENT) + set(Boost_${UPPERCOMPONENT}_FOUND 0) + endforeach() +endif() + +# ------------------------------------------------------------------------ +# Notification to end user about what was found +# ------------------------------------------------------------------------ + +set(Boost_LIBRARIES "") +if(Boost_FOUND) + if(NOT Boost_FIND_QUIETLY) + message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") + if(Boost_FIND_COMPONENTS) + message(STATUS "Found the following Boost libraries:") + endif() + endif() + foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) + string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) + if( Boost_${UPPERCOMPONENT}_FOUND ) + if(NOT Boost_FIND_QUIETLY) + message (STATUS " ${COMPONENT}") + endif() + list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) + endif() + endforeach() +else() + if(Boost_FIND_REQUIRED) + message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") + else() + if(NOT Boost_FIND_QUIETLY) + # we opt not to automatically output Boost_ERROR_REASON here as + # it could be quite lengthy and somewhat imposing in its requests + # Since Boost is not always a required dependency we'll leave this + # up to the end-user. + if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) + message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") + else() + message(STATUS "Could NOT find Boost") + endif() + endif() + endif() +endif() + +# Configure display of cache entries in GUI. +foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) + get_property(_type CACHE ${v} PROPERTY TYPE) + if(_type) + set_property(CACHE ${v} PROPERTY ADVANCED 1) + if("x${_type}" STREQUAL "xUNINITIALIZED") + if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") + set_property(CACHE ${v} PROPERTY TYPE STRING) + else() + set_property(CACHE ${v} PROPERTY TYPE PATH) + endif() + endif() + endif() +endforeach() + +# Record last used values of input variables so we can +# detect on the next run if the user changed them. +foreach(v + ${_Boost_VARS_INC} ${_Boost_VARS_LIB} + ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} + ) + if(DEFINED ${v}) + set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") + else() + unset(_${v}_LAST CACHE) + endif() +endforeach() + +# Maintain a persistent list of components requested anywhere since +# the last flush. +set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") +list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) +list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) +list(SORT _Boost_COMPONENTS_SEARCHED) +set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" + CACHE INTERNAL "Components requested for this build tree.") diff --git a/cmake/FindWX.cmake b/cmake/FindWX.cmake deleted file mode 100644 index b818293..0000000 --- a/cmake/FindWX.cmake +++ /dev/null @@ -1,323 +0,0 @@ -####################################################################### -# -# FindPg.cmake - A CMake module for locating wxWidgets -# -# Dave Page, EnterpriseDB UK Ltd. -# This code is released under the PostgreSQL Licence -# -####################################################################### - -# To use this module, simply include it in your CMake project. -# If set, wxWidgets will be assumed to be in the location specified -# by the WXWIN environment variable. Otherwise, it will be searched -# for in a number of standard locations. -# -# The following CMake variables can be set to control the build type. -# If not set, the default values shown will be used. Booleans must -# be either YES or NO: -# -# WX_VERSION = "2.8" -# WX_DEBUG = NO -# WX_STATIC = NO -# WX_UNICODE = YES -# WX_MODULES = "base" (a list). -# -# The following CMake variable will be set: -# -# WX_FOUND - Set to TRUE if wxWidgets is located -# WX_ROOT_DIR - The base install directory for wxWidgets -# WX_VERSION_STRING - The wxWidgets version number. -# -# Unix only: -# WX_CONFIG_PATH - The wx-config executable path -# -# Unix & Win32: -# WX_INCLUDE_DIRS - The wxWidgets header directories. -# WX_DEFINITIONS - The wxWidgets preprocessor definitions -# WX_LIBRARIES - The wxWidgets libraries -# WX_LIBRARY_DIRS - The wxWidgets library directories. - - -############################################################################### -# Macros -############################################################################### - -# Check for a library on Windows -MACRO(WIN32_CHECK_LIB M_LIB_NAME M_LIB_REL_FILENAME M_LIB_DBG_FILENAME M_LIB_PATH) - - LIST(FIND WX_MODULES ${M_LIB_NAME} _pos) - IF(NOT _pos EQUAL -1) - - SET(_tmp CACHE INTERNAL "_tmp-NOTFOUND") - FIND_FILE(_tmp NAMES ${M_LIB_REL_FILENAME} PATHS ${M_LIB_PATH} NO_DEFAULT_PATH) - IF(_tmp STREQUAL "_tmp-NOTFOUND") - SET(_error TRUE) - ELSE(_tmp STREQUAL "_tmp-NOTFOUND") - LIST(APPEND WX_LIBRARIES "optimized;${M_LIB_REL_FILENAME}") - ENDIF(_tmp STREQUAL "_tmp-NOTFOUND") - - SET(_tmp CACHE INTERNAL "_tmp-NOTFOUND") - FIND_FILE(_tmp NAMES ${M_LIB_DBG_FILENAME} PATHS ${M_LIB_PATH} NO_DEFAULT_PATH) - IF(_tmp STREQUAL "_tmp-NOTFOUND") - SET(_error TRUE) - ELSE(_tmp STREQUAL "_tmp-NOTFOUND") - LIST(APPEND WX_LIBRARIES "debug;${M_LIB_DBG_FILENAME}") - ENDIF(_tmp STREQUAL "_tmp-NOTFOUND") - - ENDIF(NOT _pos EQUAL -1) - -ENDMACRO(WIN32_CHECK_LIB) - -############################################################################### -# Arguments -############################################################################### - -IF(NOT WX_VERSION OR WX_VERSION STREQUAL "") - SET(_version "2.8") -ELSE(NOT WX_VERSION OR WX_VERSION STREQUAL "") - SET(_version ${WX_VERSION}) -ENDIF(NOT WX_VERSION OR WX_VERSION STREQUAL "") - -IF(NOT WX_DEBUG OR WX_DEBUG STREQUAL "") - SET(_debug "no") -ELSE(NOT WX_DEBUG OR WX_DEBUG STREQUAL "") - IF(WX_DEBUG) - SET(_debug "yes") - ELSE(WX_DEBUG) - SET(_debug "no") - ENDIF(WX_DEBUG) -ENDIF(NOT WX_DEBUG OR WX_DEBUG STREQUAL "") - -IF(NOT WX_STATIC OR WX_STATIC STREQUAL "") - SET(_static "no") -ELSE(NOT WX_STATIC OR WX_STATIC STREQUAL "") - IF(WX_STATIC) - SET(_static "yes") - ELSE(WX_STATIC) - SET(_static "no") - ENDIF(WX_STATIC) -ENDIF(NOT WX_STATIC OR WX_STATIC STREQUAL "") - -IF(NOT WX_UNICODE OR WX_UNICODE STREQUAL "") - SET(_unicode "yes") -ELSE(NOT WX_UNICODE OR WX_UNICODE STREQUAL "") - IF(WX_UNICODE) - SET(_unicode "yes") - ELSE(WX_UNICODE) - SET(_unicode "no") - ENDIF(WX_UNICODE) -ENDIF(NOT WX_UNICODE OR WX_UNICODE STREQUAL "") - -IF(NOT WX_MODULES OR WX_MODULES STREQUAL "") - SET(_modules "base") -ELSE(NOT WX_MODULES OR WX_MODULES STREQUAL "") - SET(_modules ${WX_MODULES}) -ENDIF(NOT WX_MODULES OR WX_MODULES STREQUAL "") - -SET(_build_desc "version: ${_version}, debug: ${_debug}, static: ${_static}, unicode: ${_unicode}, modules: ${_modules}") - -############################################################################### -# Here we go... -############################################################################### - -# MSVC++ -IF(WIN32 AND NOT CYGWIN AND NOT MSYS) - # The VC++ libraries are found in an entirely different way than - # the *nix libraries because we don't have a wx-config file. - - # Figure out the build suffix - SET(_suffix "") # Possibly-unicode libraries - - IF(_unicode) - SET(_suffix "${_suffix}u") - ENDIF(_unicode) - - # Figure out the build prefix directory - IF(_static) - SET(_prefix "vc_lib") - ELSE(_static) - SET(_prefix "vc_dll") - ENDIF(_static) - - # Find the Unix configure script. We'll attempt to extract a version number from it. - IF(NOT $ENV{WXWIN} STREQUAL "") - FIND_PATH(WX_ROOT_DIR NAMES configure - PATHS $ENV{WXWIN} - DOC "Path to the wxWidgets installation" - NO_DEFAULT_PATH) - ELSE(NOT $ENV{WXWIN} STREQUAL "") - FIND_PATH(WX_ROOT_DIR NAMES configure - PATHS $ENV{ProgramFiles}/wxWidgets-* - $ENV{SystemDrive}/wxWidgets-* - DOC "Path to the wxWidgets installation") - ENDIF(NOT $ENV{WXWIN} STREQUAL "") - - # Attempt to read the version number from the configure script - FILE(STRINGS ${WX_ROOT_DIR}/configure _line REGEX "PACKAGE_VERSION=") - STRING(REGEX REPLACE "PACKAGE_VERSION='([0-9]+\\.[0-9]+\\.[0-9]+)'" "\\1" WX_VERSION_STRING "${_line}") - - IF(NOT ${WX_VERSION_STRING} STREQUAL "") - - SET(WX_FOUND TRUE) - - LIST(APPEND WX_INCLUDE_DIRS "${WX_ROOT_DIR}/include" "${WX_ROOT_DIR}/contrib/include") - LIST(APPEND WX_LIBRARY_DIRS "${WX_ROOT_DIR}/lib/${_prefix}") - - # Got through the modules list and add libraries for those requested. - # If any of them don't seem to exist, throw an error, or got to not found mode - STRING(REGEX REPLACE "^([0-9])+\\.([0-9])+\\.[0-9]+" "\\1\\2" _shortver "${WX_VERSION_STRING}") - - SET(_error FALSE) - - SET(_libpath ${WX_ROOT_DIR}/lib/${_prefix}) - - WIN32_CHECK_LIB("adv" wxmsw${_shortver}${_suffix}_adv.lib wxmsw${_shortver}${_suffix}d_adv.lib ${_libpath}) - WIN32_CHECK_LIB("aui" wxmsw${_shortver}${_suffix}_aui.lib wxmsw${_shortver}${_suffix}d_aui.lib ${_libpath}) - WIN32_CHECK_LIB("base" wxbase${_shortver}${_suffix}.lib wxbase${_shortver}${_suffix}d.lib ${_libpath}) - WIN32_CHECK_LIB("core" wxmsw${_shortver}${_suffix}_core.lib wxmsw${_shortver}${_suffix}d_core.lib ${_libpath}) - WIN32_CHECK_LIB("dbgrid" wxmsw${_shortver}${_suffix}_dbgrid.lib wxmsw${_shortver}${_suffix}d_dbgrid.lib ${_libpath}) - WIN32_CHECK_LIB("gl" wxmsw${_shortver}${_suffix}_gl.lib wxmsw${_shortver}${_suffix}d_gl.lib ${_libpath}) - WIN32_CHECK_LIB("html" wxmsw${_shortver}${_suffix}_html.lib wxmsw${_shortver}${_suffix}d_html.lib ${_libpath}) - WIN32_CHECK_LIB("media" wxmsw${_shortver}${_suffix}_media.lib wxmsw${_shortver}${_suffix}d_media.lib ${_libpath}) - WIN32_CHECK_LIB("net" wxbase${_shortver}${_suffix}_net.lib wxbase${_shortver}${_suffix}d_net.lib ${_libpath}) - WIN32_CHECK_LIB("odbc" wxbase${_shortver}${_suffix}_odbc.lib wxbase${_shortver}${_suffix}d_odbc.lib ${_libpath}) - WIN32_CHECK_LIB("qa" wxmsw${_shortver}${_suffix}_qa.lib wxmsw${_shortver}${_suffix}d_qa.lib ${_libpath}) - WIN32_CHECK_LIB("richtext" wxmsw${_shortver}${_suffix}_richtext.lib wxmsw${_shortver}${_suffix}d_richtext.lib ${_libpath}) - WIN32_CHECK_LIB("xml" wxbase${_shortver}${_suffix}_xml.lib wxbase${_shortver}${_suffix}d_xml.lib ${_libpath}) - WIN32_CHECK_LIB("xrc" wxmsw${_shortver}${_suffix}_xrc.lib wxmsw${_shortver}${_suffix}d_xrc.lib ${_libpath}) - - # Contribs - WIN32_CHECK_LIB("fl" wxmsw${_shortver}${_suffix}_fl.lib wxmsw${_shortver}${_suffix}d_fl.lib ${_libpath}) - WIN32_CHECK_LIB("foldbar" wxmsw${_shortver}${_suffix}_foldbar.lib wxmsw${_shortver}${_suffix}d_foldbar.lib ${_libpath}) - WIN32_CHECK_LIB("gizmos" wxmsw${_shortver}${_suffix}_gizmos.lib wxmsw${_shortver}${_suffix}d_gizmos.lib ${_libpath}) - WIN32_CHECK_LIB("gizmos_xrc" wxmsw${_shortver}${_suffix}_gizmos_xrc.lib wxmsw${_shortver}${_suffix}d_gizmos_xrc.lib ${_libpath}) - WIN32_CHECK_LIB("mmedia" wxmsw${_shortver}${_suffix}_mmedia.lib wxmsw${_shortver}${_suffix}d_mmedia.lib ${_libpath}) - WIN32_CHECK_LIB("netutils" wxmsw${_shortver}${_suffix}_netutils.lib wxmsw${_shortver}${_suffix}d_netutils.lib ${_libpath}) - WIN32_CHECK_LIB("ogl" wxmsw${_shortver}${_suffix}_ogl.lib wxmsw${_shortver}${_suffix}d_ogl.lib ${_libpath}) - WIN32_CHECK_LIB("plot" wxmsw${_shortver}${_suffix}_plot.lib wxmsw${_shortver}${_suffix}d_plot.lib ${_libpath}) - WIN32_CHECK_LIB("stc" wxmsw${_shortver}${_suffix}_stc.lib wxmsw${_shortver}${_suffix}d_stc.lib ${_libpath}) - WIN32_CHECK_LIB("svg" wxmsw${_shortver}${_suffix}_svg.lib wxmsw${_shortver}${_suffix}d_svg.lib ${_libpath}) - - # Add some default libraries we'll need - LIST(APPEND WX_LIBRARIES "debug;wxexpatd.lib" "optimized;wxexpat.lib" - "debug;wxjpegd.lib" "optimized;wxjpeg.lib" - "debug;wxpngd.lib" "optimized;wxpng.lib" - "debug;wxregex${_suffix}d.lib" "optimized;wxregex${_suffix}.lib" - "debug;wxtiffd.lib" "optimized;wxtiff.lib" - "debug;wxzlibd.lib" "optimized;wxzlib.lib") - LIST(APPEND WX_LIBRARIES winmm comctl32 rpcrt4 wsock32) - - # Preprocessor definitions - SET(${WX_DEFINITIONS} "-D__WXMSW__") - - IF(_unicode) - SET(WX_DEFINITIONS "${WX_DEFINITIONS};-DUNICODE") - ENDIF(_unicode) - - IF(NOT _static) - SET(WX_DEFINITIONS "${WX_DEFINITIONS};-DWXUSINGDLL") - ENDIF(NOT _static) - - # Bail out if there was an error - IF(_error) - SET(WX_FOUND FALSE) - SET(WX_ROOT_DIR WX_ROOT_DIR-NO_FOUND) - SET(WX_VERSION_STRING "") - SET(WX_INCLUDE_DIRS "") - SET(WX_DEFINITIONS "") - SET(WX_LIBRARIES "") - SET(WX_LIBRARY_DIRS "") - IF(WX_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "The selected wxWidgets configuration (${_build_desc}) is not available.") - ELSE(WX_FIND_REQUIRED) - MESSAGE(STATUS "The selected wxWidgets configuration (${_build_desc}) is not available.") - ENDIF(WX_FIND_REQUIRED) - ENDIF(_error) - - ELSE(NOT ${WX_VERSION_STRING} STREQUAL "") - SET(WX_FOUND FALSE) - SET(WX_ROOT_DIR WX_ROOT_DIR-NO_FOUND) - SET(WX_VERSION_STRING "") - IF(WX_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "No wxWidgets installation could be found.") - ELSE(WX_FIND_REQUIRED) - MESSAGE(STATUS "No wxWidgets installation could be found.") - ENDIF(WX_FIND_REQUIRED) - ENDIF(NOT ${WX_VERSION_STRING} STREQUAL "") - -# Unix-style -ELSE(WIN32 AND NOT CYGWIN AND NOT MSYS) - - # Set up the wx-config command line - SET(_args "--version=${_version} --debug=${_debug} --static=${_static} --unicode=${_unicode} ${_modules}") - - IF(NOT $ENV{WXWIN} STREQUAL "") - FIND_PROGRAM(WX_CONFIG_PATH wx-config - PATH $ENV{WXWIN}/bin - DOC "Path to the wx-config executable" - NO_DEFAULT_PATH) - ELSE(NOT $ENV{WXWIN} STREQUAL "") - FIND_PROGRAM(WX_CONFIG_PATH wx-config - DOC "Path to the wx-config executable") - ENDIF(NOT $ENV{WXWIN} STREQUAL "") - - EXEC_PROGRAM(${WX_CONFIG_PATH} ARGS ${_args} --version OUTPUT_VARIABLE WX_VERSION_STRING RETURN_VALUE _retval) - - IF(_retval EQUAL 1) - SET(WX_FOUND FALSE) - SET(WX_ROOT_DIR WX_ROOT_DIR-NO_FOUND) - SET(WX_VERSION_STRING "") - IF(WX_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "The selected wxWidgets configuration (${_build_desc}) is not available.") - ELSE(WX_FIND_REQUIRED) - MESSAGE(STATUS "The selected wxWidgets configuration (${_build_desc}) is not available.") - ENDIF(WX_FIND_REQUIRED) - ENDIF(_retval EQUAL 1) - - IF(NOT _retval) - - SET(WX_FOUND TRUE) - - # Strip the bin and pg_config from the path - GET_FILENAME_COMPONENT(WX_ROOT_DIR ${WX_CONFIG_PATH} PATH) - GET_FILENAME_COMPONENT(WX_ROOT_DIR ${WX_ROOT_DIR} PATH) - - EXEC_PROGRAM(${WX_CONFIG_PATH} ARGS ${_args} --cppflags OUTPUT_VARIABLE _cppflags) - EXEC_PROGRAM(${WX_CONFIG_PATH} ARGS ${_args} --libs OUTPUT_VARIABLE _ldflags) - - # Parse the compiler options - STRING(STRIP "${_cppflags}" WX_CPPFLAGS) - SEPARATE_ARGUMENTS(WX_CPPFLAGS) - - # Get the definitions, and drop them from the flags - STRING(REGEX MATCHALL "-D[^;]+" WX_DEFINITIONS "${WX_CPPFLAGS}") - STRING(REGEX REPLACE "-D[^;]+(;|$)" "" WX_CPPFLAGS "${WX_CPPFLAGS}") - - # Get the include dirs. - STRING(REGEX MATCHALL "-I[^;]+" WX_INCLUDE_DIRS "${WX_CPPFLAGS}") - STRING(REPLACE "-I" "" WX_INCLUDE_DIRS "${WX_INCLUDE_DIRS}") - STRING(REGEX REPLACE "-I[^;]+(;|$)" "" WX_CPPFLAGS "${WX_CPPFLAGS}") - - # Parse the libraries - STRING(STRIP "${_ldflags}" WX_LIBRARIES) - SEPARATE_ARGUMENTS(WX_LIBRARIES) - STRING(REPLACE "-framework;" "-framework " WX_LIBRARIES "${WX_LIBRARIES}") - STRING(REPLACE "-arch;" "-arch " WX_LIBRARIES "${WX_LIBRARIES}") - STRING(REPLACE "-isysroot;" "-isysroot " WX_LIBRARIES "${WX_LIBRARIES}") - - # extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES) - STRING(REGEX MATCHALL "-L[^;]+" WX_LIBRARY_DIRS "${WX_LIBRARIES}") - STRING(REPLACE "-L" "" WX_LIBRARY_DIRS "${WX_LIBRARY_DIRS}") - - ELSE(NOT _retval) - SET(WX_FOUND FALSE) - SET(WX_ROOT_DIR WX_ROOT_DIR-NO_FOUND) - SET(WX_VERSION_STRING "") - IF(WX_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "No wxWidgets installation could be found.") - ELSE(WX_FIND_REQUIRED) - MESSAGE(STATUS "No wxWidgets installation could be found.") - ENDIF(WX_FIND_REQUIRED) - ENDIF(NOT _retval) - -ENDIF(WIN32 AND NOT CYGWIN AND NOT MSYS) diff --git a/cmake/MakeExt.cmake b/cmake/MakeExt.cmake index 5526601..cbfb20e 100644 --- a/cmake/MakeExt.cmake +++ b/cmake/MakeExt.cmake @@ -1,18 +1,18 @@ -####################################################################### -# -# pgAgent - PostgreSQL tools -# Copyright (C) 2002 - 2016, The pgAdmin Development Team -# This software is released under the PostgreSQL Licence -# -# MakeExt,cmake - Create the PG Extension -# -####################################################################### - -FILE(READ sql/pgagent.sql PGAGENT_SQL) -STRING(REPLACE "BEGIN TRANSACTION;" "" PGAGENT_SQL "${PGAGENT_SQL}") -STRING(REPLACE "COMMIT TRANSACTION;" "" PGAGENT_SQL "${PGAGENT_SQL}") -STRING(REPLACE "CREATE SCHEMA pgagent;" "" PGAGENT_SQL "${PGAGENT_SQL}") -STRING(REPLACE "-- EXT SELECT" "SELECT" PGAGENT_SQL "${PGAGENT_SQL}") -FILE(WRITE "pgagent--${MAJOR_VERSION}.${MINOR_VERSION}.sql" "${PGAGENT_SQL}") - -CONFIGURE_FILE(pgagent.control.in pgagent.control) +####################################################################### +# +# pgAgent - PostgreSQL tools +# Copyright (C) 2002 - 2016, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +# MakeExt,cmake - Create the PG Extension +# +####################################################################### + +FILE(READ ${PGAGENT_SOURCE_DIR}/sql/pgagent.sql PGAGENT_SQL) +STRING(REPLACE "BEGIN TRANSACTION;" "" PGAGENT_SQL "${PGAGENT_SQL}") +STRING(REPLACE "COMMIT TRANSACTION;" "" PGAGENT_SQL "${PGAGENT_SQL}") +STRING(REPLACE "CREATE SCHEMA pgagent;" "" PGAGENT_SQL "${PGAGENT_SQL}") +STRING(REPLACE "-- EXT SELECT" "SELECT" PGAGENT_SQL "${PGAGENT_SQL}") +FILE(WRITE "${CMAKE_BINARY_DIR}/pgagent--${MAJOR_VERSION}.${MINOR_VERSION}.sql" "${PGAGENT_SQL}") + +CONFIGURE_FILE(${PGAGENT_SOURCE_DIR}/pgagent.control.in ${CMAKE_BINARY_DIR}/pgagent.control) diff --git a/connection.cpp b/connection.cpp index 2b96294..e390af7 100644 --- a/connection.cpp +++ b/connection.cpp @@ -10,16 +10,50 @@ ////////////////////////////////////////////////////////////////////////// #include "pgAgent.h" +#include -#include -#include +namespace ip = boost::asio::ip; -DBconn *DBconn::primaryConn = NULL; -wxString DBconn::basicConnectString; -static wxMutex s_PoolLock; +DBconn *DBconn::ms_primaryConn = NULL; +std::wstring DBconn::ms_basicConnectString; +static boost::mutex s_poolLock; +class MutexLocker +{ +public: + MutexLocker(boost::mutex *lock): m_lock(lock) + { + if (m_lock) + m_lock->lock(); + } + + ~MutexLocker() + { + if (m_lock) + m_lock->unlock(); + } + + // When the exit(code) is being called, static object is being released + // earlier. Hence - it is a good idea to set the current mutex object to + // NULL to avoid ASSERTION in debug mode (specifically on OSX). + MutexLocker& operator =(boost::mutex *lock) + { + if (m_lock) + m_lock->unlock(); + m_lock = lock; + + if (m_lock) + m_lock->lock(); -DBconn::DBconn(const wxString &connectString, const wxString &db) + return *this; + } + +private: + boost::mutex *m_lock; + bool is_locked; +}; + +DBconn::DBconn(const std::wstring &connectString, const std::wstring &db) { inUse = false; next = 0; @@ -29,11 +63,11 @@ DBconn::DBconn(const wxString &connectString, const wxString &db) dbname = db; connStr = connectString; - if (connectString.IsEmpty()) + if (connectString.empty()) { // This is a sql call to a local database. // No connection string found. Use basicConnectString. - Connect(basicConnectString + wxT(" dbname=") + dbname); + Connect(ms_basicConnectString + L" dbname=" + dbname); } else { @@ -42,17 +76,23 @@ DBconn::DBconn(const wxString &connectString, const wxString &db) } -bool DBconn::Connect(const wxString &connectString) +bool DBconn::Connect(const std::wstring &connectString) { - LogMessage(wxString::Format(_("Creating DB connection: %s"), connectString.c_str()), LOG_DEBUG); - wxCharBuffer cstrUTF = connectString.mb_str(wxConvUTF8); - conn = PQconnectdb(cstrUTF); - if (PQstatus(conn) != CONNECTION_OK) + LogMessage((L"Creating DB connection: " + connectString), LOG_DEBUG); + char *cstrUTF = WStringToChar(connectString); + if (cstrUTF != NULL) { - lastError = wxString::FromAscii(PQerrorMessage(conn)); - PQfinish(conn); - conn = 0; + conn = PQconnectdb(cstrUTF); + if (PQstatus(conn) != CONNECTION_OK) + { + lastError = CharToWString((const char *)PQerrorMessage(conn)); + PQfinish(conn); + conn = 0; + } + + delete [] cstrUTF; } + return IsValid(); } @@ -68,118 +108,139 @@ DBconn::~DBconn() } -wxString DBconn::qtDbString(const wxString &value) +std::wstring DBconn::qtDbString(const std::wstring &value) { - wxString result = value; + std::wstring result = value; - result.Replace(wxT("\\"), wxT("\\\\")); - result.Replace(wxT("'"), wxT("''")); - result.Append(wxT("'")); + boost::replace_all(result, L"\\", L"\\\\"); + boost::replace_all(result, L"'", L"''"); + result.append(L"'"); if (BackendMinimumVersion(8, 1)) { - if (result.Contains(wxT("\\"))) - result.Prepend(wxT("E'")); + if (result.find(L"\\") != std::wstring::npos) + result.replace(0, 0, L"E'"); else - result.Prepend(wxT("'")); + result.replace(0, 0, L"'"); } else - result.Prepend(wxT("'")); + result.replace(0, 0, L"'"); return result; } - bool DBconn::BackendMinimumVersion(int major, int minor) { + char *ver = NULL; if (!majorVersion) { - wxString version = ExecuteScalar(wxT("SELECT version();")) ; - sscanf(version.ToAscii(), "%*s %d.%d", &majorVersion, &minorVersion); + std::wstring version = ExecuteScalar(L"SELECT version();"); + ver = WStringToChar(version); + if (ver != NULL) + sscanf(ver, "%*s %d.%d", &majorVersion, &minorVersion); } + + if (ver != NULL) + delete []ver; + return majorVersion > major || (majorVersion == major && minorVersion >= minor); } -DBconn *DBconn::InitConnection(const wxString &connectString) +DBconn *DBconn::InitConnection(const std::wstring &connectString) { - wxMutexLocker lock(s_PoolLock); + MutexLocker locker(&s_poolLock); - basicConnectString = connectString; - wxString dbname; + ms_basicConnectString = connectString; + std::wstring dbname; connInfo cnInfo = connInfo::getConnectionInfo(connectString); if (cnInfo.isValid) { dbname = cnInfo.dbname; - basicConnectString = cnInfo.getConnectionString(); - primaryConn = new DBconn(cnInfo.getConnectionString(), dbname); + ms_basicConnectString = cnInfo.getConnectionString(); + ms_primaryConn = new DBconn(cnInfo.getConnectionString(), dbname); - if (!primaryConn) - LogMessage(_("Failed to create primary connection!"), LOG_ERROR); - primaryConn->dbname = dbname; - primaryConn->inUse = true; + if (!ms_primaryConn) + { + // Unlock the mutex before logging error. + locker = (boost::mutex *)NULL; + LogMessage(L"Failed to create primary connection!", LOG_ERROR); + } + if (!ms_primaryConn->IsValid()) + { + std::wstring error = ms_primaryConn->GetLastError(); + delete ms_primaryConn; + ms_primaryConn = NULL; + // Unlock the mutex before logging error. + locker = (boost::mutex *)NULL; + LogMessage( + L"Failed to create primary connection: " + error, LOG_ERROR + ); + } + ms_primaryConn->dbname = dbname; + ms_primaryConn->inUse = true; } else { - primaryConn = NULL; - LogMessage(wxT("Primary connection string is not valid!"), LOG_ERROR); + ms_primaryConn = NULL; + // Unlock the mutex before logging error. + locker = (boost::mutex *)NULL; + LogMessage(L"Primary connection string is not valid!", LOG_ERROR); } - return primaryConn; + return ms_primaryConn; } -DBconn *DBconn::Get(const wxString &connStr, const wxString &db) +DBconn *DBconn::Get(const std::wstring &connStr, const std::wstring &db) { - if (db.IsEmpty() && connStr.IsEmpty()) + if (db.empty() && connStr.empty()) { - LogMessage(_("Cannot allocate connection - no database or connection string specified!"), LOG_WARNING); + LogMessage(L"Cannot allocate connection - no database or connection string specified!", LOG_WARNING); return NULL; } + MutexLocker locker(&s_poolLock); - wxMutexLocker lock(s_PoolLock); - - DBconn *thisConn = primaryConn, *lastConn; + DBconn *thisConn = ms_primaryConn, *lastConn; // find an existing connection do { - if (thisConn && ((!db.IsEmpty() && db == thisConn->dbname && connStr.IsEmpty()) || (!connStr.IsEmpty() && connStr == thisConn->connStr)) && !thisConn->inUse) + if (thisConn && ((!db.empty() && db == thisConn->dbname && connStr.empty()) || (!connStr.empty() && connStr == thisConn->connStr)) && !thisConn->inUse) { - LogMessage(wxString::Format(_("Allocating existing connection to database %s"), thisConn->dbname.c_str()), LOG_DEBUG); + LogMessage((L"Allocating existing connection to database " + thisConn->dbname), LOG_DEBUG); thisConn->inUse = true; + return thisConn; } lastConn = thisConn; thisConn = thisConn->next; - } - while (thisConn != 0); + } while (thisConn != 0); // No suitable connection was found, so create a new one. DBconn *newConn = NULL; newConn = new DBconn(connStr, db); - if (newConn->conn) + if (newConn && newConn->conn) { - LogMessage(wxString::Format(_("Allocating new connection to database %s"), newConn->dbname.c_str()), LOG_DEBUG); + LogMessage((L"Allocating new connection to database " + newConn->dbname), LOG_DEBUG); newConn->inUse = true; newConn->prev = lastConn; lastConn->next = newConn; } else { - wxString warnMsg; - if (connStr.IsEmpty()) - warnMsg = wxString::Format(_("Failed to create new connection to database '%s':'%s'"), - db.c_str(), newConn->GetLastError().c_str()); + std::wstring warnMsg; + if (connStr.empty()) + warnMsg = (L"Failed to create new connection to database '" + db + L"':'" + newConn->GetLastError() + L"'"); else - warnMsg = wxString::Format(_("Failed to create new connection for connection string '%s':%s"), - connStr.c_str(), newConn->GetLastError().c_str()); + warnMsg = (L"Failed to create new connection for connection string '" + connStr + L"':'" + newConn->GetLastError() + L"'"); LogMessage(warnMsg, LOG_STARTUP); + return NULL; } @@ -189,27 +250,27 @@ DBconn *DBconn::Get(const wxString &connStr, const wxString &db) void DBconn::Return() { - wxMutexLocker lock(s_PoolLock); + MutexLocker locker(&s_poolLock); // Cleanup - this->ExecuteVoid(wxT("RESET ALL")); - this->lastError.Empty(); + this->ExecuteVoid(L"RESET ALL"); + this->lastError.empty(); - LogMessage(wxString::Format(_("Returning connection to database %s"), dbname.c_str()), LOG_DEBUG); + LogMessage((L"Returning connection to database " + dbname), LOG_DEBUG); inUse = false; } void DBconn::ClearConnections(bool all) { - wxMutexLocker lock(s_PoolLock); + MutexLocker locker(&s_poolLock); if (all) - LogMessage(_("Clearing all connections"), LOG_DEBUG); + LogMessage(L"Clearing all connections", LOG_DEBUG); else - LogMessage(_("Clearing inactive connections"), LOG_DEBUG); + LogMessage(L"Clearing inactive connections", LOG_DEBUG); - DBconn *thisConn = primaryConn, *deleteConn; + DBconn *thisConn = ms_primaryConn, *deleteConn; int total = 0, free = 0, deleted = 0; if (thisConn) @@ -254,21 +315,19 @@ void DBconn::ClearConnections(bool all) if (all) { delete thisConn; + ms_primaryConn = NULL; deleted++; } - wxString tmp; - tmp.Printf(_("Connection stats: total - %d, free - %d, deleted - %d"), total, free, deleted); - LogMessage(tmp, LOG_DEBUG); + LogMessage((boost::wformat(L"Connection stats: total - %d, free - %d, deleted - %d") % total % free % deleted).str(), LOG_DEBUG); } else - LogMessage(_("No connections found!"), LOG_DEBUG); - + LogMessage(L"No connections found!", LOG_DEBUG); } -DBresult *DBconn::Execute(const wxString &query) +DBresult *DBconn::Execute(const std::wstring &query) { DBresult *res = new DBresult(this, query); if (!res->IsValid()) @@ -282,66 +341,70 @@ DBresult *DBconn::Execute(const wxString &query) } -wxString DBconn::ExecuteScalar(const wxString &query) +std::wstring DBconn::ExecuteScalar(const std::wstring &query) { int rows = -1; - DBresult *res = Execute(query); - wxString data; + DBresultPtr res = Execute(query); + std::wstring data; if (res) { data = res->GetString(0); rows = res->RowsAffected(); - delete res; return data; } - return wxEmptyString; + return L""; } -int DBconn::ExecuteVoid(const wxString &query) +int DBconn::ExecuteVoid(const std::wstring &query) { int rows = -1; - DBresult *res = Execute(query); + DBresultPtr res = Execute(query); if (res) { rows = res->RowsAffected(); - delete res; } return rows; } -wxString DBconn::GetLastError() +std::wstring DBconn::GetLastError() { - return lastError.Trim(true); + boost::algorithm::trim(lastError); + return lastError; } ///////////////////////////////////////////////////////7 -DBresult::DBresult(DBconn *conn, const wxString &query) +DBresult::DBresult(DBconn *conn, const std::wstring &query) { - wxCharBuffer cstrUTF = query.mb_str(wxConvUTF8); - result = PQexec(conn->conn, cstrUTF); + char *cstrUTF = WStringToChar(query); currentRow = 0; maxRows = 0; - - if (result) + if (cstrUTF != NULL) { - int rc = PQresultStatus(result); - conn->SetLastResult(rc); - if (rc == PGRES_TUPLES_OK) - maxRows = PQntuples(result); - else if (rc != PGRES_COMMAND_OK) + result = PQexec(conn->conn, cstrUTF); + + if (result) { - conn->lastError = wxString::FromAscii(PQerrorMessage(conn->conn)); - LogMessage(wxT("Query error: ") + conn->lastError, LOG_WARNING); - PQclear(result); - result = 0; + int rc = PQresultStatus(result); + conn->SetLastResult(rc); + if (rc == PGRES_TUPLES_OK) + maxRows = PQntuples(result); + else if (rc != PGRES_COMMAND_OK) + { + const char *last_error = PQerrorMessage(conn->conn); + conn->lastError = CharToWString(last_error); + LogMessage((L"Query error: " + conn->lastError), LOG_WARNING); + PQclear(result); + result = 0; + } } - } - else - conn->lastError = wxString::FromAscii(PQerrorMessage(conn->conn)); + else + conn->lastError = CharToWString(PQerrorMessage(conn->conn)); + delete [] cstrUTF; + } } @@ -352,26 +415,31 @@ DBresult::~DBresult() } -wxString DBresult::GetString(int col) const +std::wstring DBresult::GetString(int col) const { - wxString str; + std::wstring str; if (result && currentRow < maxRows && col >= 0) { - str = wxString::FromAscii(PQgetvalue(result, currentRow, col)); + str = CharToWString((const char *)PQgetvalue(result, currentRow, col)); } return str; } -wxString DBresult::GetString(const wxString &colname) const +std::wstring DBresult::GetString(const std::wstring &colname) const { - wxCharBuffer cstrUTF = colname.mb_str(wxConvUTF8); + char *cstrUTF = WStringToChar(colname); + + // Below function will return -1 if string is NULL or does not match. int col = PQfnumber(result, cstrUTF); + if (cstrUTF != NULL) + delete [] cstrUTF; + if (col < 0) { // fatal: not found - return wxT(""); + return L""; } return GetString(col); } @@ -380,170 +448,138 @@ wxString DBresult::GetString(const wxString &colname) const bool connInfo::IsValidIP() { - if (host.IsEmpty()) + if (host.empty()) return false; - // check for IPv4 format - wxStringTokenizer tkip4(host, wxT(".")); - int count = 0; - - while (tkip4.HasMoreTokens()) + const std::string hostAddr(host.begin(), host.end()); + try { - long val = 0; - if (!tkip4.GetNextToken().ToLong(&val)) - break; - if (count == 0 || count == 3) - if (val > 0 && val < 255) - count++; - else - break; - else if (val >= 0 && val < 255) - count++; - else - break; + ip::address ip = ip::address::from_string(hostAddr); + if (ip.is_v4() || ip.is_v6()) + return true; } - - if (count == 4) - return true; - - // check for IPv6 format - wxStringTokenizer tkip6(host, wxT(":")); - count = 0; - - while (tkip6.HasMoreTokens()) + catch (const boost::system::system_error& e) { - unsigned long val = 0; - wxString strVal = tkip6.GetNextToken(); - if (strVal.Length() > 4 || !strVal.ToULong(&val, 16)) - return false; - count++; + LogMessage(CharToWString((const char *)e.what()), LOG_WARNING); + return false; } - if (count <= 8) - return true; - // TODO:: We're not supporting mix mode (x:x:x:x:x:x:d.d.d.d) - // i.e. ::ffff:12.34.56.78 return false; } - -wxString connInfo::getConnectionString() +std::wstring connInfo::getConnectionString() { - wxString connStr; + std::wstring connStr; // Check if it has valid connection info if (!isValid) return connStr; // User - connStr = wxT("user=") + user; + connStr = L"user=" + user; // Port if (port != 0) { - wxString portStr; - portStr.Printf(wxT("%ld"), port); - connStr += wxT(" port=") + portStr; + std::wstring portStr(boost::lexical_cast(port)); + connStr += L" port=" + portStr; } // host or hostaddr - if (!host.IsEmpty()) + if (!host.empty()) { if (IsValidIP()) - connStr += wxT(" hostaddr=") + host; + connStr += L" hostaddr=" + host; else - connStr += wxT(" host=") + host; + connStr += L" host=" + host; } // connection timeout if (connection_timeout != 0) { - wxString val; - val.Printf(wxT("%ld"), connection_timeout); - connStr += wxT(" connection_timeout=") + val; + std::wstring val(boost::lexical_cast(connection_timeout)); + connStr += L" connection_timeout=" + val; } // password - if (!password.IsEmpty()) - connStr += wxT(" password=") + password; + if (!password.empty()) + connStr += L" password=" + password; + + if (!dbname.empty()) + connStr += L" dbname=" + dbname; - if (!dbname.IsEmpty()) - connStr += wxT(" dbname=") + dbname; + LogMessage(L"Connection Information:", LOG_DEBUG); - LogMessage(wxString::Format(_("Connection Information:")), LOG_DEBUG); - LogMessage(wxString::Format(_(" user : %s"), user.c_str()), LOG_DEBUG); - LogMessage(wxString::Format(_(" port : %ld"), port), LOG_DEBUG); - LogMessage(wxString::Format(_(" host : %s"), host.c_str()), LOG_DEBUG); - LogMessage(wxString::Format(_(" dbname : %s"), dbname.c_str()), LOG_DEBUG); - LogMessage(wxString::Format(_(" password : %s"), password.c_str()), LOG_DEBUG); - LogMessage(wxString::Format(_(" conn timeout : %ld"), connection_timeout), LOG_DEBUG); + LogMessage((L" user : " + user), LOG_DEBUG); + LogMessage((boost::wformat(L" port : %d") % port).str(), LOG_DEBUG); + LogMessage((L" host : " + host), LOG_DEBUG); + LogMessage((L" dbname : " + dbname), LOG_DEBUG); + LogMessage((L" password : " + password), LOG_DEBUG); + LogMessage((boost::wformat(L" conn timeout : %d") % connection_timeout).str(), LOG_DEBUG); return connStr; } - -connInfo connInfo::getConnectionInfo(wxString connStr) +connInfo connInfo::getConnectionInfo(const std::wstring &conn_str) { connInfo cnInfo; - wxRegEx propertyExp; - - // Remove the white-space(s) to match the following format - // i.e. prop=value - bool res = propertyExp.Compile(wxT("(([ ]*[\t]*)+)=")); + std::string connStr(conn_str.begin(), conn_str.end()); - propertyExp.ReplaceAll(&connStr, wxT("=")); + const boost::regex propertyExp("(([ ]*[\t]*)+)="); + connStr = boost::regex_replace(connStr, propertyExp, std::string("=")); - res = propertyExp.Compile(wxT("=(([ ]*[\t]*)+)")); - propertyExp.ReplaceAll(&connStr, wxT("=")); + const boost::regex propertyExp_("=(([ ]*[\t]*)+)"); + connStr = boost::regex_replace(connStr, propertyExp_, std::string("=")); - // Seperate all the prop=value patterns - wxArrayString tokens = wxStringTokenize(connStr, wxT("\t \n\r")); + boost::char_separator sep("\t \n\r"); + boost::tokenizer > tok(connStr, sep); - unsigned int index = 0; - while (index < tokens.Count()) + for (boost::tokenizer< boost::char_separator >::iterator beg = tok.begin(); (beg != tok.end()); ++beg) { - wxString prop, value; + std::wstring prop, value; + int key_val_pair = 0; - wxArrayString pairs = wxStringTokenize(tokens[index++], wxT("=")); + boost::char_separator sep_("="); + boost::tokenizer > tok_(*beg, sep_); - if (pairs.GetCount() != 2) - return cnInfo; + for (boost::tokenizer< boost::char_separator >::iterator key_val = tok_.begin(); (key_val != tok_.end()); ++key_val) + { + std::string tk = *key_val; + if (key_val_pair) + value = std::wstring(tk.begin(), tk.end()); + else + prop = std::wstring(tk.begin(), tk.end()); + key_val_pair++; + } - prop = pairs[0]; - value = pairs[1]; + if (key_val_pair != 2) + return cnInfo; - if (prop.CmpNoCase(wxT("user")) == 0) + if (boost::iequals(prop, L"user")) cnInfo.user = value; - else if (prop.CmpNoCase(wxT("host")) == 0 || prop.CmpNoCase(wxT("hostAddr")) == 0) + else if (boost::iequals(prop, L"host") || boost::iequals(prop, L"hostAddr")) cnInfo.host = value; - else if (prop.CmpNoCase(wxT("port")) == 0) - { - if (!value.ToULong(&cnInfo.port)) - // port must be an unsigned integer - return cnInfo; - } - else if (prop.CmpNoCase(wxT("password")) == 0) + else if (boost::iequals(prop, L"port")) + cnInfo.port = boost::lexical_cast(value); + else if (boost::iequals(prop, L"password")) cnInfo.password = value; - else if (prop.CmpNoCase(wxT("connection_timeout")) == 0) - { - if (!value.ToULong(&cnInfo.connection_timeout)) - // connection timeout must be an unsigned interger - return cnInfo; - } - else if (prop.CmpNoCase(wxT("dbname")) == 0) + else if (boost::iequals(prop, L"connection_timeout")) + cnInfo.connection_timeout = boost::lexical_cast(value); + else if (boost::iequals(prop, L"dbname")) cnInfo.dbname = value; else + { // Not valid property found return cnInfo; + } } // If user, dbname & host all are blank than we will consider this an invalid connection string - if (cnInfo.user.IsEmpty() && cnInfo.dbname.IsEmpty() && cnInfo.host.IsEmpty()) + if (cnInfo.user.empty() && cnInfo.dbname.empty() && cnInfo.host.empty()) cnInfo.isValid = false; else cnInfo.isValid = true; return cnInfo; } - diff --git a/include/connection.h b/include/connection.h index b2693f7..5ba4362 100644 --- a/include/connection.h +++ b/include/connection.h @@ -21,29 +21,29 @@ class DBresult; class DBconn { protected: - DBconn(const wxString &, const wxString &); + DBconn(const std::wstring &, const std::wstring &); ~DBconn(); public: - wxString qtDbString(const wxString &value); + std::wstring qtDbString(const std::wstring &value); bool BackendMinimumVersion(int major, int minor); - static DBconn *Get(const wxString &connStr, const wxString &db); - static DBconn *InitConnection(const wxString &connectString); + static DBconn *Get(const std::wstring &connStr, const std::wstring &db); + static DBconn *InitConnection(const std::wstring &connectString); static void ClearConnections(bool allIncludingPrimary = false); - static void SetBasicConnectString(const wxString &bcs) + static void SetBasicConnectString(const std::wstring &bcs) { - basicConnectString = bcs; + ms_basicConnectString = bcs; } - static const wxString &GetBasicConnectString() + static const std::wstring &GetBasicConnectString() { - return basicConnectString; + return ms_basicConnectString; } - wxString GetLastError(); - wxString GetDBname() + std::wstring GetLastError(); + std::wstring GetDBname() { return dbname; } @@ -53,53 +53,53 @@ public: return conn != 0; } - bool LastCommandOk() - { - return IsCommandOk((ExecStatusType)lastResult); - } + bool LastCommandOk() + { + return IsCommandOk((ExecStatusType)lastResult); + } - bool IsCommandOk(ExecStatusType ret) - { - switch (ret) - { - case PGRES_COMMAND_OK: - case PGRES_TUPLES_OK: - case PGRES_COPY_OUT: - case PGRES_COPY_IN: + bool IsCommandOk(ExecStatusType ret) + { + switch (ret) + { + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + case PGRES_COPY_OUT: + case PGRES_COPY_IN: #if (PG_VERSION_NUM >= 90100) - case PGRES_COPY_BOTH: + case PGRES_COPY_BOTH: #endif - return true; - default: - return false; - }; - } - - void SetLastResult(int res) - { - lastResult = res; - } - - int GetLastResult() - { - return lastResult; - } - - DBresult *Execute(const wxString &query); - wxString ExecuteScalar(const wxString &query); - int ExecuteVoid(const wxString &query); + return true; + default: + return false; + }; + } + + void SetLastResult(int res) + { + lastResult = res; + } + + int GetLastResult() + { + return lastResult; + } + + DBresult *Execute(const std::wstring &query); + std::wstring ExecuteScalar(const std::wstring &query); + int ExecuteVoid(const std::wstring &query); void Return(); private: - bool Connect(const wxString &connectString); + bool Connect(const std::wstring &connectString); int minorVersion, majorVersion; protected: - static wxString basicConnectString; - static DBconn *primaryConn; + static std::wstring ms_basicConnectString; + static DBconn *ms_primaryConn; - wxString dbname, lastError, connStr; + std::wstring dbname, lastError, connStr; PGconn *conn; DBconn *next, *prev; bool inUse; @@ -112,13 +112,13 @@ protected: class DBresult { protected: - DBresult(DBconn *conn, const wxString &query); + DBresult(DBconn *conn, const std::wstring &query); public: ~DBresult(); - wxString GetString(int col) const; - wxString GetString(const wxString &colname) const; + std::wstring GetString(int col) const; + std::wstring GetString(const std::wstring &colname) const; bool IsValid() const { @@ -146,6 +146,54 @@ protected: }; +class DBresultPtr +{ +public: + DBresultPtr(DBresult* in_ptr) + : m_ptr(in_ptr) + {} + ~DBresultPtr() + { + if (m_ptr) { + delete m_ptr; + m_ptr = NULL; + } + } + DBresultPtr& operator=(DBresult *other) + { + if (m_ptr) { + delete m_ptr; + } + m_ptr = other; + return *this; + } + const DBresult& operator*() const + { + return (*(const DBresult *)m_ptr); + } + const DBresult* operator->() const + { + return (const DBresult*)(m_ptr); + } + DBresult& operator*() + { + return (*(DBresult *)m_ptr); + } + DBresult* operator->() + { + return (DBresult *)m_ptr; + } + operator void*() const + { + return (DBresult *)m_ptr; + } + operator bool() const { return (m_ptr != NULL); } + +protected: + DBresult* m_ptr; +}; + + class connInfo { public: @@ -157,16 +205,16 @@ public: } private: - wxString user; + std::wstring user; unsigned long port; - wxString host; - wxString dbname; + std::wstring host; + std::wstring dbname; unsigned long connection_timeout; - wxString password; + std::wstring password; bool isValid; - wxString getConnectionString(); - static connInfo getConnectionInfo(wxString connStr); + std::wstring getConnectionString(); + static connInfo getConnectionInfo(const std::wstring &connStr); protected: bool IsValidIP(); diff --git a/include/job.h b/include/job.h index 1e1beb7..eae32b3 100644 --- a/include/job.h +++ b/include/job.h @@ -13,44 +13,35 @@ #ifndef JOB_H #define JOB_H -#include - +#include class Job { public: - Job(DBconn *conn, const wxString &jid); + Job(DBconn *conn, const std::wstring &jid); ~Job(); int Execute(); bool Runnable() { - return status == wxT("r"); + return status == L"r"; } protected: DBconn *threadConn; - wxString jobid, logid; - wxString status; + std::wstring jobid, logid; + std::wstring status; }; - -class JobThread : public wxThread +class JobThread { public: - JobThread(const wxString &jid); + JobThread(const std::wstring &jid); ~JobThread(); - bool Runnable() - { - return runnable; - } - - virtual void *Entry(); + void operator()(); private: - wxString jobid; - bool runnable; - Job *job; + std::wstring m_jobid; }; #endif // JOB_H diff --git a/include/misc.h b/include/misc.h index cc849e5..83e5c80 100644 --- a/include/misc.h +++ b/include/misc.h @@ -15,10 +15,14 @@ void WaitAWhile(const bool waitLong = false); -void setOptions(int argc, char **argv, const wxString &executable); -wxString getArg(int &argc, char **&argv); -wxString NumToStr(const long l); +void setOptions(int argc, char **argv, const std::wstring &executable); +std::wstring getArg(int &argc, char **&argv); +std::wstring NumToStr(const long l); void printVersion(); +std::wstring CharToWString(const char* cstr); +char* WStringToChar(const std::wstring &wstr); +std::string generateRandomString(size_t length); +std::wstring getTemporaryDirectoryPath(); #endif // MISC_H diff --git a/include/pgAgent.h b/include/pgAgent.h index be29dcb..69e801e 100644 --- a/include/pgAgent.h +++ b/include/pgAgent.h @@ -13,10 +13,24 @@ #ifndef PGAGENT_H #define PGAGENT_H -// Disable all the GUI classes that might get pulled in through the headers -#define wxUSE_GUI 0 +#if BOOST_OS_WINDOWS +#include +#endif -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "misc.h" #include "connection.h" @@ -25,13 +39,13 @@ extern long longWait; extern long shortWait; extern long minLogLevel; -extern wxString connectString; -extern wxString serviceDBname; -extern wxString backendPid; +extern std::wstring connectString; +extern std::wstring serviceDBname; +extern std::wstring backendPid; -#ifndef __WXMSW__ +#if !BOOST_OS_WINDOWS extern bool runInForeground; -extern wxString logFile; +extern std::wstring logFile; #endif // Log levels @@ -48,13 +62,12 @@ enum }; // Prototypes -void LogMessage(wxString msg, int level); +void LogMessage(const std::wstring &msg, const int &level); void MainLoop(); -#ifdef __WIN32__ -#include +#if BOOST_OS_WINDOWS void CheckForInterrupt(); -HANDLE win32_popen_r(const TCHAR *command, HANDLE &handle); +HANDLE win32_popen_r(const WCHAR *command, HANDLE &handle); #endif #endif // PGAGENT_H diff --git a/job.cpp b/job.cpp index 0b7c146..c877310 100644 --- a/job.cpp +++ b/job.cpp @@ -11,47 +11,41 @@ #include "pgAgent.h" -#include -#include -#include -#include - #include -#ifndef __WIN32__ +#if !BOOST_OS_WINDOWS #include #include +#include #endif -Job::Job(DBconn *conn, const wxString &jid) +Job::Job(DBconn *conn, const std::wstring &jid) { threadConn = conn; jobid = jid; - status = wxT(""); + status = L""; - LogMessage(wxString::Format(_("Starting job: %s"), jobid.c_str()), LOG_DEBUG); + LogMessage((L"Starting job: " + jobid), LOG_DEBUG); int rc = threadConn->ExecuteVoid( - wxT("UPDATE pgagent.pga_job SET jobagentid=") + backendPid + wxT(", joblastrun=now() ") - wxT(" WHERE jobagentid IS NULL AND jobid=") + jobid); + L"UPDATE pgagent.pga_job SET jobagentid=" + backendPid + L", joblastrun=now() " + + L" WHERE jobagentid IS NULL AND jobid=" + jobid); if (rc == 1) { - DBresult *id = threadConn->Execute( - wxT("SELECT nextval('pgagent.pga_joblog_jlgid_seq') AS id")); + DBresultPtr id = threadConn->Execute( + L"SELECT nextval('pgagent.pga_joblog_jlgid_seq') AS id"); if (id) { - logid = id->GetString(wxT("id")); + logid = id->GetString(L"id"); - DBresult *res = threadConn->Execute( - wxT("INSERT INTO pgagent.pga_joblog(jlgid, jlgjobid, jlgstatus) ") - wxT("VALUES (") + logid + wxT(", ") + jobid + wxT(", 'r')")); + DBresultPtr res = threadConn->Execute( + L"INSERT INTO pgagent.pga_joblog(jlgid, jlgjobid, jlgstatus) " + L"VALUES (" + logid + L", " + jobid + L", 'r')"); if (res) { - status = wxT("r"); - delete res; + status = L"r"; } - delete id; } } } @@ -59,21 +53,21 @@ Job::Job(DBconn *conn, const wxString &jid) Job::~Job() { - if (status != wxT("")) + if (status != L"") { threadConn->ExecuteVoid( - wxT("UPDATE pgagent.pga_joblog ") - wxT(" SET jlgstatus='") + status + wxT("', jlgduration=now() - jlgstart ") - wxT(" WHERE jlgid=") + logid + wxT(";\n") - - wxT("UPDATE pgagent.pga_job ") - wxT(" SET jobagentid=NULL, jobnextrun=NULL ") - wxT(" WHERE jobid=") + jobid - ); + L"UPDATE pgagent.pga_joblog " + L" SET jlgstatus='" + status + L"', jlgduration=now() - jlgstart " + + L" WHERE jlgid=" + logid + L";\n" + + + L"UPDATE pgagent.pga_job " + + L" SET jobagentid=NULL, jobnextrun=NULL " + + L" WHERE jobid=" + jobid + ); } threadConn->Return(); - LogMessage(wxString::Format(_("Completed job: %s"), jobid.c_str()), LOG_DEBUG); + LogMessage((L"Completed job: " + jobid), LOG_DEBUG); } @@ -81,71 +75,69 @@ int Job::Execute() { int rc = 0; bool succeeded = false; - DBresult *steps = threadConn->Execute( - wxT("SELECT * ") - wxT(" FROM pgagent.pga_jobstep ") - wxT(" WHERE jstenabled ") - wxT(" AND jstjobid=") + jobid + - wxT(" ORDER BY jstname, jstid")); + DBresultPtr steps = threadConn->Execute( + L"SELECT * " + L" FROM pgagent.pga_jobstep " + L" WHERE jstenabled " + L" AND jstjobid=" + jobid + + L" ORDER BY jstname, jstid"); if (!steps) { - status = wxT("i"); + status = L"i"; return -1; } while (steps->HasData()) { DBconn *stepConn; - wxString jslid, stepid, jpecode, output; + std::wstring jslid, stepid, jpecode, output; - stepid = steps->GetString(wxT("jstid")); + stepid = steps->GetString(L"jstid"); - DBresult *id = threadConn->Execute( - wxT("SELECT nextval('pgagent.pga_jobsteplog_jslid_seq') AS id")); + DBresultPtr id = threadConn->Execute( + L"SELECT nextval('pgagent.pga_jobsteplog_jslid_seq') AS id"); if (id) { - jslid = id->GetString(wxT("id")); - DBresult *res = threadConn->Execute( - wxT("INSERT INTO pgagent.pga_jobsteplog(jslid, jsljlgid, jsljstid, jslstatus) ") - wxT("SELECT ") + jslid + wxT(", ") + logid + wxT(", ") + stepid + wxT(", 'r'") - wxT(" FROM pgagent.pga_jobstep WHERE jstid=") + stepid); + jslid = id->GetString(L"id"); + DBresultPtr res = threadConn->Execute( + L"INSERT INTO pgagent.pga_jobsteplog(jslid, jsljlgid, jsljstid, jslstatus) " + L"SELECT " + jslid + L", " + logid + L", " + stepid + L", 'r'" + + L" FROM pgagent.pga_jobstep WHERE jstid=" + stepid); if (res) { rc = res->RowsAffected(); - delete res; } else rc = -1; } - delete id; if (rc != 1) { - status = wxT("i"); + status = L"i"; return -1; } - switch ((int) steps->GetString(wxT("jstkind"))[0]) + switch ((int)steps->GetString(L"jstkind")[0]) { case 's': { - wxString jstdbname = steps->GetString(wxT("jstdbname")); - wxString jstconnstr = steps->GetString(wxT("jstconnstr")); + std::wstring jstdbname = steps->GetString(L"jstdbname"); + std::wstring jstconnstr = steps->GetString(L"jstconnstr"); stepConn = DBconn::Get(jstconnstr, jstdbname); if (stepConn) { - LogMessage(wxString::Format(_("Executing SQL step %s (part of job %s)"), stepid.c_str(), jobid.c_str()), LOG_DEBUG); - rc = stepConn->ExecuteVoid(steps->GetString(wxT("jstcode"))); + LogMessage((L"Executing SQL step " + stepid + L"(part of job " + jobid + L")"), LOG_DEBUG); + rc = stepConn->ExecuteVoid(steps->GetString(L"jstcode")); succeeded = stepConn->LastCommandOk(); output = stepConn->GetLastError(); stepConn->Return(); } else { - output = _("Couldn't get a connection to the database!"); + output = L"Couldn't get a connection to the database!"; succeeded = false; } @@ -155,104 +147,104 @@ int Job::Execute() case 'b': { // Batch jobs are more complex thank SQL, for obvious reasons... - LogMessage(wxString::Format(_("Executing batch step %s (part of job %s)"), stepid.c_str(), jobid.c_str()), LOG_DEBUG); + LogMessage((L"Executing batch step" + stepid + L"(part of job " + jobid + L")"), LOG_DEBUG); // Get a temporary filename, then reuse it to create an empty directory. - wxString dirname = wxFileName::CreateTempFileName(wxT("pga_")); - if (dirname.Length() == 0) - { - output = _("Couldn't get a temporary filename!"); - LogMessage(_("Couldn't get a temporary filename!"), LOG_WARNING); - rc = -1; - break; - } + std::wstring wTmpDir = getTemporaryDirectoryPath(); + std::string sDirectory(wTmpDir.begin(), wTmpDir.end()); + std::string sFilesName = ""; + std::string prefix = "pga_"; + int last_n_char = 7; + + // Genrate random string of 6 characters long to make unique dir name + std::string result = generateRandomString(7); + sFilesName = prefix + result; +#if BOOST_OS_WINDOWS + std::string sModel = (boost::format("%s\\%s") % sDirectory % sFilesName).str(); +#else + std::string sModel = (boost::format("%s/%s") % sDirectory % sFilesName).str(); +#endif + std::string dir_name = sModel; + std::wstring dirname(dir_name.begin(), dir_name.end()); - ; - if (!wxRemoveFile(dirname)) + if (dirname == L"") { - output.Printf(_("Couldn't remove temporary file: %s"), dirname.c_str()); + output = L"Couldn't get a temporary filename!"; LogMessage(output, LOG_WARNING); rc = -1; break; } - if (!wxMkdir(dirname, 0700)) + if (!boost::filesystem::create_directory(boost::filesystem::path(dir_name))) { - output.Printf(_("Couldn't create temporary directory: %s"), dirname.c_str()); - LogMessage(output, LOG_WARNING); + LogMessage((L"Couldn't create temporary directory: " + dirname), LOG_WARNING); rc = -1; break; } -#ifdef __WIN32__ - wxString filename = dirname + wxT("\\") + jobid + wxT("_") + stepid + wxT(".bat"); - wxString errorFile = dirname + wxT("\\") + jobid + wxT("_") + stepid + wxT("_error.txt"); +#if BOOST_OS_WINDOWS + std::wstring filename = dirname + L"\\" + jobid + L"_" + stepid + L".bat"; + std::wstring errorFile = dirname + L"\\" + jobid + L"_" + stepid + L"_error.txt"; #else - wxString filename = dirname + wxT("/") + jobid + wxT("_") + stepid + wxT(".scr"); - wxString errorFile = dirname + wxT("/") + jobid + wxT("_") + stepid + wxT("_error.txt"); + std::wstring filename = dirname + L"/" + jobid + L"_" + stepid + L".scr"; + std::wstring errorFile = dirname + L"/" + jobid + L"_" + stepid + L"_error.txt"; #endif - // Write the script - wxFile *file = new wxFile(); - - if (!file->Create(filename, true, wxS_IRUSR | wxS_IWUSR | wxS_IXUSR)) - { - output.Printf(_("Couldn't create temporary script file: %s"), filename.c_str()); - LogMessage(output, LOG_WARNING); - rc = -1; - break; - } - - if (!file->Open(filename, wxFile::write)) - { - output.Printf(_("Couldn't open temporary script file: %s"), filename.c_str()); - LogMessage(output, LOG_WARNING); - wxRemoveFile(filename); - wxRmdir(dirname); - rc = -1; - break; - } - - wxString code = steps->GetString(wxT("jstcode")); + std::wstring code = steps->GetString(L"jstcode"); // Cleanup the code. If we're on Windows, we need to make all line ends \r\n, // If we're on Unix, we need \n - code.Replace(wxT("\r\n"), wxT("\n")); -#ifdef __WIN32__ - code.Replace(wxT("\n"), wxT("\r\n")); + boost::replace_all(code, "\r\n", "\n"); +#if BOOST_OS_WINDOWS + boost::replace_all(code, "\n", "\r\n"); #endif + std::ofstream out_file; + std::string s_code(code.begin(), code.end()); + std::string sfilename(filename.begin(), filename.end()); + std::string serrorFile(errorFile.begin(), errorFile.end()); - if (!file->Write(code)) + out_file.open((const char *)sfilename.c_str(), std::ios::out); + if (out_file.fail()) { - output.Printf(_("Couldn't write to temporary script file: %s"), filename.c_str()); - LogMessage(output, LOG_WARNING); - wxRemoveFile(filename); - wxRmdir(dirname); + LogMessage((L"Couldn't open temporary script file: " + filename), LOG_WARNING); + if (boost::filesystem::exists(dirname)) + boost::filesystem::remove_all(dirname); rc = -1; break; } + else + { + out_file << s_code; + out_file.close(); +#if !BOOST_OS_WINDOWS + // change file permission to 700 for executable in linux + int ret = chmod((const char *)sfilename.c_str(), S_IRWXU); + if (ret != 0) + LogMessage((L"Error setting executable permission to file: " + filename), LOG_DEBUG); +#endif + } - file->Close(); - LogMessage(wxString::Format(_("Executing script file: %s"), filename.c_str()), LOG_DEBUG); + LogMessage((L"Executing script file: " + filename), LOG_DEBUG); // freopen function is used to redirect output of stream (stderr in our case) // into the specified file. - FILE *fpError = freopen(errorFile.mb_str(), "w", stderr); + FILE *fpError = freopen((const char *)serrorFile.c_str(), "w", stderr); // Execute the file and capture the output -#ifdef __WIN32__ +#if BOOST_OS_WINDOWS // The Windows way HANDLE h_script, h_process; DWORD dwRead; char chBuf[4098]; - h_script = win32_popen_r(filename.wc_str(), h_process); + h_script = win32_popen_r(filename.c_str(), h_process); if (!h_script) { - output.Printf(_("Couldn't execute script: %s, GetLastError() returned %d, errno = %d"), filename.c_str(), GetLastError(), errno); - LogMessage(output, LOG_WARNING); + LogMessage((boost::wformat(L"Couldn't execute script: %s, GetLastError() returned %s, errno = %d") % filename.c_str() % GetLastError() % errno).str(), LOG_WARNING); CloseHandle(h_process); rc = -1; + if (fpError) + fclose(fpError); break; } @@ -262,11 +254,11 @@ int Job::Execute() { for (;;) { - if(!ReadFile(h_script, chBuf, 4096, &dwRead, NULL) || dwRead == 0) + if (!ReadFile(h_script, chBuf, 4096, &dwRead, NULL) || dwRead == 0) break; chBuf[dwRead] = 0; - output += wxString::FromAscii(chBuf); + output += CharToWString((const char *)chBuf); } } @@ -280,12 +272,13 @@ int Job::Execute() FILE *fp_script; char buf[4098]; - fp_script = popen(filename.mb_str(wxConvUTF8), "r"); + fp_script = popen((const char *)sfilename.c_str(), "r"); if (!fp_script) { - output.Printf(_("Couldn't execute script: %s, errno = %d"), filename.c_str(), errno); - LogMessage(output, LOG_WARNING); + LogMessage((boost::wformat(L"Couldn't execute script: %s, errno = %d") % filename.c_str() % errno).str(), LOG_WARNING); rc = -1; + if(fpError) + fclose(fpError); break; } @@ -293,7 +286,7 @@ int Job::Execute() while(!feof(fp_script)) { if (fgets(buf, 4096, fp_script) != NULL) - output += wxString::FromAscii(buf); + output += CharToWString((const char *)buf); } rc = pclose(fp_script); @@ -306,50 +299,46 @@ int Job::Execute() #endif // set success status for batch runs, be pessimistic by default - LogMessage(wxString::Format(_("Script return code: %d"), rc), LOG_DEBUG); + LogMessage((boost::wformat(L"Script return code: %d") % rc).str(), LOG_DEBUG); succeeded = ((rc == 0) ? true : false); // If output is empty then either script did not return any output // or script threw some error into stderr. // Check script threw some error into stderr if (fpError) { - //fclose(fpError); - FILE* fpErr = fopen(errorFile.mb_str(), "r"); + fclose(fpError); + FILE* fpErr = fopen((const char *)serrorFile.c_str(), "r"); if (fpErr) { char buffer[4098]; - wxString errorMsg = wxEmptyString; + std::wstring errorMsg = L""; while (!feof(fpErr)) { if (fgets(buffer, 4096, fpErr) != NULL) - errorMsg += wxString(buffer, wxConvLibc); + errorMsg += CharToWString(buffer); } - if (errorMsg != wxEmptyString) { - wxString errmsg = - wxString::Format( - _("Script Error: \n%s\n"), - errorMsg.c_str()); - LogMessage(errmsg, LOG_WARNING); - output += wxT("\n") + errmsg; + if (errorMsg != L"") { + std::wstring errmsg = L"Script Error: \n" + errorMsg + L"\n", + LogMessage((L"Script Error: \n" + errorMsg + L"\n"), LOG_WARNING); + output += L"\n" + errmsg; } fclose(fpErr); } - wxRemoveFile(errorFile); } // Delete the file/directory. If we fail, don't overwrite the script output in the log, just throw warnings. - if (!wxRemoveFile(filename)) + try { - LogMessage(wxString::Format(_("Couldn't remove temporary script file: %s"), filename.c_str()), LOG_WARNING); - wxRmdir(dirname); - break; + boost::filesystem::path dir_path(dir_name); + if (boost::filesystem::exists(dir_path)) + boost::filesystem::remove_all(dir_path); } - - if (!wxRmdir(dirname)) + catch (boost::filesystem::filesystem_error const & e) { - LogMessage(wxString::Format(_("Couldn't remove temporary directory: "), dirname.c_str()), LOG_WARNING); + //display error message + LogMessage(CharToWString((const char *)e.what()), LOG_WARNING); break; } @@ -357,71 +346,76 @@ int Job::Execute() } default: { - output = _("Invalid step type!"); - status = wxT("i"); + output = L"Invalid step type!"; + status = L"i"; return -1; } } - wxString stepstatus; + std::wstring stepstatus; if (succeeded) - stepstatus = wxT("s"); + stepstatus = L"s"; else - stepstatus = steps->GetString(wxT("jstonerror")); + stepstatus = steps->GetString(L"jstonerror"); rc = threadConn->ExecuteVoid( - wxT("UPDATE pgagent.pga_jobsteplog ") - wxT(" SET jslduration = now() - jslstart, ") - wxT(" jslresult = ") + NumToStr(rc) + wxT(", jslstatus = '") + stepstatus + wxT("', ") - wxT(" jsloutput = ") + threadConn->qtDbString(output) + wxT(" ") - wxT(" WHERE jslid=") + jslid); - if (rc != 1 || stepstatus == wxT("f")) + L"UPDATE pgagent.pga_jobsteplog " + L" SET jslduration = now() - jslstart, " + L" jslresult = " + NumToStr(rc) + L", jslstatus = '" + stepstatus + L"', " + + L" jsloutput = " + threadConn->qtDbString(output) + L" " + + L" WHERE jslid=" + jslid); + if (rc != 1 || stepstatus == L"f") { - status = wxT("f"); + status = L"f"; return -1; } steps->MoveNext(); } - delete steps; - status = wxT("s"); + status = L"s"; return 0; } - -JobThread::JobThread(const wxString &jid) - : wxThread(wxTHREAD_DETACHED) +JobThread::JobThread(const std::wstring &jid) + : m_jobid(jid) { - LogMessage(wxString::Format(_("Creating job thread for job %s"), jid.c_str()), LOG_DEBUG); - - runnable = false; - jobid = jid; - - DBconn *threadConn = DBconn::Get(DBconn::GetBasicConnectString(), serviceDBname); - if (threadConn) - { - job = new Job(threadConn, jobid); - - if (job->Runnable()) - runnable = true; - } + LogMessage((L"Creating job thread for job " + m_jobid), LOG_DEBUG); } JobThread::~JobThread() { - LogMessage(wxString::Format(_("Destroying job thread for job %s"), jobid.c_str()), LOG_DEBUG); - delete job; + LogMessage(L"Destroying job thread for job " + m_jobid, LOG_DEBUG); } -void *JobThread::Entry() +void JobThread::operator()() { - if (runnable) + DBconn *threadConn = DBconn::Get( + DBconn::GetBasicConnectString(), serviceDBname + ); + + if (threadConn) { - job->Execute(); - } + Job job(threadConn, m_jobid); - return(NULL); + if (job.Runnable()) + { + job.Execute(); + } + else + { + // Failed to launch the thread. Insert an entry with + // "internal error" status in the joblog table, to leave + // a trace of fact that we tried to launch the job. + DBresultPtr res = threadConn->Execute( + L"INSERT INTO pgagent.pga_joblog(jlgid, jlgjobid, jlgstatus) " + L"VALUES (nextval('pgagent.pga_joblog_jlgid_seq'), " + + m_jobid + L", 'i')" + ); + if (res) + res = NULL; + } + } } diff --git a/misc.cpp b/misc.cpp index d8508df..2171e82 100644 --- a/misc.cpp +++ b/misc.cpp @@ -12,32 +12,33 @@ #include "pgAgent.h" #include "connection.h" -#ifndef __WXMSW__ +#if !BOOST_OS_WINDOWS #include +#include #endif -#define APPVERSION_STR wxT(PGAGENT_VERSION) +#define APPVERSION_STR PGAGENT_VERSION // In unix.c or win32.c -void usage(const wxString &executable); +void usage(const std::wstring &executable); -wxString getArg(int &argc, char **&argv) +std::wstring getArg(int &argc, char **&argv) { - wxString s; + std::wstring s; if (argv[0][2]) - s = wxString::FromAscii(argv[0] + 2); + s = CharToWString(argv[0] + 2); else { if (argc >= 1) { argc--; argv++; - s = wxString::FromAscii(argv[0]); + s = CharToWString(argv[0]); } else { // very bad! - LogMessage(_("Invalid command line argument"), LOG_ERROR); + LogMessage(L"Invalid command line argument", LOG_ERROR); } } @@ -46,11 +47,11 @@ wxString getArg(int &argc, char **&argv) void printVersion() { - wxPrintf(_("PostgreSQL Scheduling Agent\n")); - wxPrintf(_("Version: %s\n"), APPVERSION_STR); + printf("PostgreSQL Scheduling Agent\n"); + printf("Version: %s\n", APPVERSION_STR); } -void setOptions(int argc, char **argv, const wxString &executable) +void setOptions(int argc, char **argv, const std::wstring &executable) { while (argc-- > 0) { @@ -60,21 +61,21 @@ void setOptions(int argc, char **argv, const wxString &executable) { case 't': { - int val = atoi(getArg(argc, argv).mb_str(wxConvUTF8)); + int val = atoi((const char*)getArg(argc, argv).c_str()); if (val > 0) shortWait = val; break; } case 'r': { - int val = atoi(getArg(argc, argv).mb_str(wxConvUTF8)); + int val = atoi((const char*)getArg(argc, argv).c_str()); if (val >= 10) longWait = val; break; } case 'l': { - int val = atoi(getArg(argc, argv).mb_str(wxConvUTF8)); + int val = atoi((const char*)getArg(argc, argv).c_str()); if (val >= 0 && val <= 2) minLogLevel = val; break; @@ -82,9 +83,9 @@ void setOptions(int argc, char **argv, const wxString &executable) case 'v': { printVersion(); - exit (0); + exit(0); } -#ifndef __WXMSW__ +#if !BOOST_OS_WINDOWS case 'f': { runInForeground = true; @@ -105,9 +106,9 @@ void setOptions(int argc, char **argv, const wxString &executable) } else { - if (connectString != wxT("")) - connectString += wxT(" "); - connectString += wxString::FromAscii(*argv); + if (connectString != L"") + connectString += L" "; + connectString = connectString + CharToWString(*argv); if (**argv == '"') connectString = connectString.substr(1, connectString.length() - 2); } @@ -135,12 +136,88 @@ void WaitAWhile(const bool waitLong) } } +std::wstring NumToStr(const long l) +{ + std::wstring buf(boost::lexical_cast(l)); + return buf; +} +// This function is used to convert char* to std::wstring. +std::wstring CharToWString(const char* cstr) +{ + std::string s = std::string(cstr); + std::wstring wsTmp(s.begin(), s.end()); + return wsTmp; +} -wxString NumToStr(const long l) +// This function is used to convert std::wstring to char *. +char * WStringToChar(const std::wstring &wstr) { - wxString buf; - buf.Printf(wxT("%ld"), l); - return buf; + const wchar_t *wchar_str = wstr.c_str(); + int wstr_length = wcslen(wchar_str); + char *dst = new char[wstr_length + 10]; + memset(dst, 0x00, (wstr_length + 10)); + wcstombs(dst, wchar_str, wstr_length); + return dst; } +// Below function will generate random string of given character. +std::string generateRandomString(size_t length) +{ + srand(time(NULL)); + char str[length]; + str[length-1] = '\0'; + size_t i = 0; + int r; + + for(i = 0; i < length-1; ++i) + { + for(;;) + { + // interval between 'A' and 'z' + r = rand() % 57 + 65; + if((r >= 65 && r <= 90) || (r >= 97 && r <= 122)) + { + str[i] = (char)r; + break; + } + } + } + + return std::string(str); +} + +std::wstring getTemporaryDirectoryPath() +{ + +#if BOOST_OS_WINDOWS + std::wstring tmp_dir = L""; + wchar_t wcharPath[MAX_PATH]; + if (GetTempPathW(MAX_PATH, wcharPath)) + tmp_dir = wcharPath; +#else + // Read this environment variable (TMPDIR, TMP, TEMP, TEMPDIR) and if not found then use "/tmp" + std::wstring tmp_dir = L"/tmp"; + const char *s = getenv("TMPDIR"); + + if (s != NULL) + tmp_dir = CharToWString(s); + else + { + const char *s1 = getenv("TMP"); + if (s1 != NULL) + tmp_dir = CharToWString(s1); + else { + const char *s2 = getenv("TEMP"); + if (s2 != NULL) + tmp_dir = CharToWString(s2); + else { + const char *s3 = getenv("TEMPDIR"); + if (s3 != NULL) + tmp_dir = CharToWString(s2); + } + } + } +#endif + return tmp_dir; +} diff --git a/pgAgent.cpp b/pgAgent.cpp index c5e00fb..afee2df 100644 --- a/pgAgent.cpp +++ b/pgAgent.cpp @@ -11,22 +11,25 @@ #include "pgAgent.h" -#ifndef __WXMSW__ +#if !BOOST_OS_WINDOWS #include #endif -wxString connectString; -wxString serviceDBname; -wxString backendPid; +std::wstring connectString; +std::wstring serviceDBname; +std::wstring backendPid; long longWait = 30; long shortWait = 5; long minLogLevel = LOG_ERROR; +using namespace std; + #define MAXATTEMPTS 10 -#ifndef __WXMSW__ +#if !BOOST_OS_WINDOWS bool runInForeground = false; -wxString logFile = wxEmptyString; +std::wstring logFile = L""; + #else //pgAgent Initialized void Initialized(); @@ -38,28 +41,28 @@ int MainRestartLoop(DBconn *serviceConn) int rc; - LogMessage(_("Clearing zombies"), LOG_DEBUG); - rc = serviceConn->ExecuteVoid(wxT("CREATE TEMP TABLE pga_tmp_zombies(jagpid int4)")); + LogMessage(L"Clearing zombies", LOG_DEBUG); + rc = serviceConn->ExecuteVoid(L"CREATE TEMP TABLE pga_tmp_zombies(jagpid int4)"); if (serviceConn->BackendMinimumVersion(9, 2)) { rc = serviceConn->ExecuteVoid( - wxT("INSERT INTO pga_tmp_zombies (jagpid) ") - wxT("SELECT jagpid ") - wxT(" FROM pgagent.pga_jobagent AG ") - wxT(" LEFT JOIN pg_stat_activity PA ON jagpid=pid ") - wxT(" WHERE pid IS NULL") - ); + L"INSERT INTO pga_tmp_zombies (jagpid) " + L"SELECT jagpid " + L" FROM pgagent.pga_jobagent AG " + L" LEFT JOIN pg_stat_activity PA ON jagpid=pid " + L" WHERE pid IS NULL" + ); } else { rc = serviceConn->ExecuteVoid( - wxT("INSERT INTO pga_tmp_zombies (jagpid) ") - wxT("SELECT jagpid ") - wxT(" FROM pgagent.pga_jobagent AG ") - wxT(" LEFT JOIN pg_stat_activity PA ON jagpid=procpid ") - wxT(" WHERE procpid IS NULL") - ); + L"INSERT INTO pga_tmp_zombies (jagpid) " + L"SELECT jagpid " + L" FROM pgagent.pga_jobagent AG " + L" LEFT JOIN pg_stat_activity PA ON jagpid=procpid " + L" WHERE procpid IS NULL" + ); } if (rc > 0) @@ -67,30 +70,31 @@ int MainRestartLoop(DBconn *serviceConn) // There are orphaned agent entries // mark the jobs as aborted rc = serviceConn->ExecuteVoid( - wxT("UPDATE pgagent.pga_joblog SET jlgstatus='d' WHERE jlgid IN (") - wxT("SELECT jlgid ") - wxT("FROM pga_tmp_zombies z, pgagent.pga_job j, pgagent.pga_joblog l ") - wxT("WHERE z.jagpid=j.jobagentid AND j.jobid = l.jlgjobid AND l.jlgstatus='r');\n") - - wxT("UPDATE pgagent.pga_jobsteplog SET jslstatus='d' WHERE jslid IN ( ") - wxT("SELECT jslid ") - wxT("FROM pga_tmp_zombies z, pgagent.pga_job j, pgagent.pga_joblog l, pgagent.pga_jobsteplog s ") - wxT("WHERE z.jagpid=j.jobagentid AND j.jobid = l.jlgjobid AND l.jlgid = s.jsljlgid AND s.jslstatus='r');\n") - - wxT("UPDATE pgagent.pga_job SET jobagentid=NULL, jobnextrun=NULL ") - wxT(" WHERE jobagentid IN (SELECT jagpid FROM pga_tmp_zombies);\n") - - wxT("DELETE FROM pgagent.pga_jobagent ") - wxT(" WHERE jagpid IN (SELECT jagpid FROM pga_tmp_zombies);\n") - ); + L"UPDATE pgagent.pga_joblog SET jlgstatus='d' WHERE jlgid IN (" + L"SELECT jlgid " + L"FROM pga_tmp_zombies z, pgagent.pga_job j, pgagent.pga_joblog l " + L"WHERE z.jagpid=j.jobagentid AND j.jobid = l.jlgjobid AND l.jlgstatus='r');\n" + + L"UPDATE pgagent.pga_jobsteplog SET jslstatus='d' WHERE jslid IN ( " + L"SELECT jslid " + L"FROM pga_tmp_zombies z, pgagent.pga_job j, pgagent.pga_joblog l, pgagent.pga_jobsteplog s " + L"WHERE z.jagpid=j.jobagentid AND j.jobid = l.jlgjobid AND l.jlgid = s.jsljlgid AND s.jslstatus='r');\n" + + L"UPDATE pgagent.pga_job SET jobagentid=NULL, jobnextrun=NULL " + L" WHERE jobagentid IN (SELECT jagpid FROM pga_tmp_zombies);\n" + + L"DELETE FROM pgagent.pga_jobagent " + L" WHERE jagpid IN (SELECT jagpid FROM pga_tmp_zombies);\n" + ); } - rc = serviceConn->ExecuteVoid(wxT("DROP TABLE pga_tmp_zombies")); + rc = serviceConn->ExecuteVoid(L"DROP TABLE pga_tmp_zombies"); - wxString hostname = wxGetFullHostName(); + std::string host_name = boost::asio::ip::host_name(); + std::wstring hostname(host_name.begin(), host_name.end()); rc = serviceConn->ExecuteVoid( - wxT("INSERT INTO pgagent.pga_jobagent (jagpid, jagstation) SELECT pg_backend_pid(), '") + hostname + wxT("'")); + L"INSERT INTO pgagent.pga_jobagent (jagpid, jagstation) SELECT pg_backend_pid(), '" + hostname + L"'"); if (rc < 0) return rc; @@ -98,56 +102,35 @@ int MainRestartLoop(DBconn *serviceConn) { bool foundJobToExecute = false; - LogMessage(_("Checking for jobs to run"), LOG_DEBUG); - DBresult *res = serviceConn->Execute( - wxT("SELECT J.jobid ") - wxT(" FROM pgagent.pga_job J ") - wxT(" WHERE jobenabled ") - wxT(" AND jobagentid IS NULL ") - wxT(" AND jobnextrun <= now() ") - wxT(" AND (jobhostagent = '' OR jobhostagent = '") + hostname + wxT("')") - wxT(" ORDER BY jobnextrun")); + LogMessage(L"Checking for jobs to run", LOG_DEBUG); + DBresultPtr res = serviceConn->Execute( + L"SELECT J.jobid " + L" FROM pgagent.pga_job J " + L" WHERE jobenabled " + L" AND jobagentid IS NULL " + L" AND jobnextrun <= now() " + L" AND (jobhostagent = '' OR jobhostagent = '" + hostname + L"')" + L" ORDER BY jobnextrun"); if (res) { - while(res->HasData()) + while (res->HasData()) { - wxString jobid = res->GetString(wxT("jobid")); - - JobThread *jt = new JobThread(jobid); - - if (jt->Runnable()) - { - jt->Create(); - jt->Run(); - foundJobToExecute = true; - } - else - { - // Failed to launch the thread. Insert an entry with - // "internal error" status in the joblog table, to leave - // a trace of fact that we tried to launch the job. - DBresult *res = serviceConn->Execute( - wxT("INSERT INTO pgagent.pga_joblog(jlgid, jlgjobid, jlgstatus) ") - wxT("VALUES (nextval('pgagent.pga_joblog_jlgid_seq'), ") + jobid + wxT(", 'i')")); - if (res) - delete res; - - // A thread object that's started will destroy itself when - // it's finished, but one that never starts we'll have to - // destory ourselves. - delete jt; - } + std::wstring jobid = res->GetString(L"jobid"); + + boost::thread job_thread = boost::thread(JobThread(jobid)); + job_thread.detach(); + foundJobToExecute = true; res->MoveNext(); } + res = NULL; - delete res; - LogMessage(_("Sleeping..."), LOG_DEBUG); + LogMessage(L"Sleeping...", LOG_DEBUG); WaitAWhile(); } else { - LogMessage(_("Failed to query jobs table!"), LOG_ERROR); + LogMessage(L"Failed to query jobs table!", LOG_ERROR); } if (!foundJobToExecute) DBconn::ClearConnections(); @@ -163,7 +146,7 @@ void MainLoop() // OK, let's get down to business do { - LogMessage(_("Creating primary connection"), LOG_DEBUG); + LogMessage(L"Creating primary connection", LOG_DEBUG); DBconn *serviceConn = DBconn::InitConnection(connectString); if (serviceConn && serviceConn->IsValid()) @@ -171,59 +154,54 @@ void MainLoop() serviceDBname = serviceConn->GetDBname(); // Basic sanity check, and a chance to get the serviceConn's PID - LogMessage(_("Database sanity check"), LOG_DEBUG); - DBresult *res = serviceConn->Execute(wxT("SELECT count(*) As count, pg_backend_pid() AS pid FROM pg_class cl JOIN pg_namespace ns ON ns.oid=relnamespace WHERE relname='pga_job' AND nspname='pgagent'")); + LogMessage(L"Database sanity check", LOG_DEBUG); + DBresultPtr res = serviceConn->Execute(L"SELECT count(*) As count, pg_backend_pid() AS pid FROM pg_class cl JOIN pg_namespace ns ON ns.oid=relnamespace WHERE relname='pga_job' AND nspname='pgagent'"); if (res) { - wxString val = res->GetString(wxT("count")); + std::wstring val = res->GetString(L"count"); - if (val == wxT("0")) - LogMessage(_("Could not find the table 'pgagent.pga_job'. Have you run pgagent.sql on this database?"), LOG_ERROR); + if (val == L"0") + LogMessage(L"Could not find the table 'pgagent.pga_job'. Have you run pgagent.sql on this database?", LOG_ERROR); - backendPid = res->GetString(wxT("pid")); + backendPid = res->GetString(L"pid"); - delete res; res = NULL; } // Check for particular version bool hasSchemaVerFunc = false; - wxString sqlCheckSchemaVersion - = wxT("SELECT COUNT(*) ")\ - wxT("FROM pg_proc ")\ - wxT("WHERE proname = 'pgagent_schema_version' AND ")\ - wxT(" pronamespace = (SELECT oid ")\ - wxT(" FROM pg_namespace ")\ - wxT(" WHERE nspname = 'pgagent') AND ")\ - wxT(" prorettype = (SELECT oid ")\ - wxT(" FROM pg_type ")\ - wxT(" WHERE typname = 'int2') AND ")\ - wxT(" proargtypes = '' "); + std::wstring sqlCheckSchemaVersion + = L"SELECT COUNT(*) "\ + L"FROM pg_proc "\ + L"WHERE proname = 'pgagent_schema_version' AND "\ + L" pronamespace = (SELECT oid "\ + L" FROM pg_namespace "\ + L" WHERE nspname = 'pgagent') AND "\ + L" prorettype = (SELECT oid "\ + L" FROM pg_type "\ + L" WHERE typname = 'int2') AND "\ + L" proargtypes = '' "; res = serviceConn->Execute(sqlCheckSchemaVersion); if (res) { - if (res->IsValid() && res->GetString(0) == wxT("1")) + if (res->IsValid() && res->GetString(0) == L"1") hasSchemaVerFunc = true; - delete res; res = NULL; } if (!hasSchemaVerFunc) { - LogMessage(_("Couldn't find the function 'pgagent_schema_version' - please run pgagent_upgrade.sql."), LOG_ERROR); + LogMessage(L"Couldn't find the function 'pgagent_schema_version' - please run pgagent_upgrade.sql.", LOG_ERROR); } - wxString strPgAgentSchemaVer = serviceConn->ExecuteScalar(wxT("SELECT pgagent.pgagent_schema_version()")); - wxString currentPgAgentVersion; - currentPgAgentVersion.Printf(_("%d"), PGAGENT_VERSION_MAJOR); + std::wstring strPgAgentSchemaVer = serviceConn->ExecuteScalar(L"SELECT pgagent.pgagent_schema_version()"); + std::wstring currentPgAgentVersion = (boost::wformat(L"%d") % PGAGENT_VERSION_MAJOR).str(); if (strPgAgentSchemaVer != currentPgAgentVersion) { - wxString strSchemaVerMisMatch; - strSchemaVerMisMatch.Printf(_("Unsupported schema version: %s. Version %s is required - please run pgagent_upgrade.sql."), strPgAgentSchemaVer.c_str(), currentPgAgentVersion.c_str()); - LogMessage(strSchemaVerMisMatch, LOG_ERROR); + LogMessage((L"Unsupported schema version: " + strPgAgentSchemaVer + L". Version " + currentPgAgentVersion + L" is required - please run pgagent_upgrade.sql."), LOG_ERROR); } #ifdef WIN32 @@ -232,16 +210,16 @@ void MainLoop() MainRestartLoop(serviceConn); } - LogMessage(wxString::Format(_("Couldn't create the primary connection (attempt %d): %s"), attemptCount, serviceConn->GetLastError().c_str()), LOG_STARTUP); + LogMessage((boost::wformat(L"Couldn't create the primary connection (attempt %d): %s") % attemptCount % serviceConn->GetLastError()).str(), LOG_STARTUP); + DBconn::ClearConnections(true); // Try establishing primary connection upto MAXATTEMPTS times if (attemptCount++ >= (int)MAXATTEMPTS) { - LogMessage(wxString::Format(_("Stopping pgAgent: Couldn't establish the primary connection with the database server.")), LOG_ERROR); + LogMessage(L"Stopping pgAgent: Couldn't establish the primary connection with the database server.", LOG_ERROR); } WaitAWhile(); - } - while (1); + } while (1); } diff --git a/unix.cpp b/unix.cpp index 27febd3..7098e9b 100644 --- a/unix.cpp +++ b/unix.cpp @@ -14,86 +14,119 @@ // *nix only!! #ifndef WIN32 -#include -#include +#include #include +#include + +using namespace std; + void printVersion(); -void usage(const wxString &executable) +void usage(const std::wstring &executable) { - wxFileName *fn = new wxFileName(executable); + char *appName = WStringToChar(executable); printVersion(); - wxPrintf(_("Usage:\n")); - wxPrintf(fn->GetName() + _(" [options] \n")); - wxPrintf(_("options:\n")); - wxPrintf(_("-v (display version info and then exit)\n")); - wxPrintf(_("-f run in the foreground (do not detach from the terminal)\n")); - wxPrintf(_("-t \n")); - wxPrintf(_("-r =10, default 30)>\n")); - wxPrintf(_("-s \n")); - wxPrintf(_("-l \n")); + fprintf(stdout, "Usage:\n"); + fprintf(stdout, "%s [options] \n", appName); + fprintf(stdout, "options:\n"); + fprintf(stdout, "-v (display version info and then exit)\n"); + fprintf(stdout, "-f run in the foreground (do not detach from the terminal)\n"); + fprintf(stdout, "-t \n"); + fprintf(stdout, "-r =10, default 30)>\n"); + fprintf(stdout, "-s \n"); + fprintf(stdout, "-l \n"); + + if (appName) + delete []appName; } -void LogMessage(wxString msg, int level) +void LogMessage(const std::wstring &msg, const int &level) { - wxFFile file; - if (logFile.IsEmpty()) + std::wofstream out; + bool writeToStdOut = false; + + if (!logFile.empty()) { - file.Attach(stdout); + std::string log_file(logFile.begin(), logFile.end()); + out.open((const char *)log_file.c_str(), ios::out | ios::app); + if (!out.is_open()) + { + fprintf(stderr, "Can not open the logfile!"); + return; + } } else - { - file.Open(logFile.c_str(), wxT("a")); - } + writeToStdOut = true; - if (!file.IsOpened()) - { - wxFprintf(stderr, _("Can not open the logfile!")); - return; - } + boost::gregorian::date current_date(boost::gregorian::day_clock::local_day()); - wxDateTime logTime = wxDateTime::Now(); - wxString logTimeString = logTime.Format() + wxT(" : "); + std::wstring day_week = boost::lexical_cast(current_date.day_of_week()); + std::wstring year = boost::lexical_cast(current_date.year()); + std::wstring month = boost::lexical_cast(current_date.month()); + std::wstring day = boost::lexical_cast(current_date.day()); + + boost::posix_time::ptime pt = boost::posix_time::second_clock::local_time(); + std::wstring time_day = boost::lexical_cast(pt.time_of_day()); + + std::wstring logTimeString = L""; + logTimeString = day_week + L" " + month + L" " + day + L" " + time_day + L" " + year + L" "; switch (level) { case LOG_DEBUG: if (minLogLevel >= LOG_DEBUG) - file.Write(logTimeString + _("DEBUG: ") + msg + wxT("\n")); + { + logTimeString = logTimeString + L"DEBUG: " + msg + L"\n"; + if (writeToStdOut) + std::wcout << logTimeString; + else + out.write(logTimeString.c_str(), logTimeString.size()); + } break; case LOG_WARNING: if (minLogLevel >= LOG_WARNING) - file.Write(logTimeString + _("WARNING: ") + msg + wxT("\n")); + { + logTimeString = logTimeString + L"WARNING: " + msg + L"\n"; + if (writeToStdOut) + std::wcout << logTimeString; + else + out.write(logTimeString.c_str(), logTimeString.size()); + } break; case LOG_ERROR: - file.Write(logTimeString + _("ERROR: ") + msg + wxT("\n")); + logTimeString = logTimeString + L"ERROR: " + msg + L"\n"; + if (writeToStdOut) + std::wcout << logTimeString; + else + out.write(logTimeString.c_str(), logTimeString.size()); exit(1); break; case LOG_STARTUP: - file.Write(logTimeString + _("WARNING: ") + msg + wxT("\n")); + logTimeString = logTimeString + L"WARNING: " + msg + L"\n"; + if (writeToStdOut) + std::wcout << logTimeString; + else + out.write(logTimeString.c_str(), logTimeString.size()); break; } - if (logFile.IsEmpty()) + if (!logFile.empty()) { - file.Detach(); - } - else - { - file.Close(); + out.close(); } } + // Shamelessly lifted from pg_autovacuum... static void daemonize(void) { pid_t pid; pid = fork(); - if (pid == (pid_t) - 1) + if (pid == (pid_t)-1) { - LogMessage(_("Cannot disassociate from controlling TTY"), LOG_ERROR); + LogMessage(L"Cannot disassociate from controlling TTY", LOG_ERROR); exit(1); } else if (pid) @@ -102,7 +135,7 @@ static void daemonize(void) #ifdef HAVE_SETSID if (setsid() < 0) { - LogMessage(_("Cannot disassociate from controlling TTY"), LOG_ERROR); + LogMessage(L"Cannot disassociate from controlling TTY", LOG_ERROR); exit(1); } #endif @@ -111,11 +144,8 @@ static void daemonize(void) int main(int argc, char **argv) { - // Statup wx - wxInitialize(); - - wxString executable; - executable = wxString::FromAscii(argv[0]); + std::wstring executable; + executable.assign(CharToWString(argv[0])); if (argc < 2) { diff --git a/win32.cpp b/win32.cpp index 21c4b93..1114dd0 100644 --- a/win32.cpp +++ b/win32.cpp @@ -14,10 +14,10 @@ // This is for Win32 only!! #ifdef WIN32 -#include -#include #include +using namespace std; + // for debugging purposes, we can start the service paused #define START_SUSPENDED 0 @@ -25,8 +25,8 @@ static SERVICE_STATUS serviceStatus; static SERVICE_STATUS_HANDLE serviceStatusHandle; -static wxString serviceName; -static wxString user = wxT(".\\Administrator"), password; +static std::wstring serviceName; +static std::wstring user = L".\\Administrator", password; static HANDLE threadHandle = 0; @@ -58,29 +58,27 @@ void CheckForInterrupt() serviceIsRunning = true; } -void LogMessage(wxString msg, int level) +void LogMessage(const std::wstring &msg, const int &level) { if (eventHandle) { - LPCTSTR *tmp; - - tmp = (LPCTSTR *)malloc(sizeof(LPCTSTR)); - tmp[0] = _wcsdup(msg.wc_str()); + LPCWSTR tmp; + tmp = _wcsdup(msg.c_str()); switch (level) { case LOG_DEBUG: if (minLogLevel >= LOG_DEBUG) - ReportEvent(eventHandle, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, tmp, NULL); + ReportEventW(eventHandle, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, &tmp, NULL); break; case LOG_WARNING: if (minLogLevel >= LOG_WARNING) - ReportEvent(eventHandle, EVENTLOG_WARNING_TYPE, 0, 0, NULL, 1, 0, tmp, NULL); + ReportEventW(eventHandle, EVENTLOG_WARNING_TYPE, 0, 0, NULL, 1, 0, &tmp, NULL); break; case LOG_ERROR: - ReportEvent(eventHandle, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, tmp, NULL); + ReportEventW(eventHandle, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, &tmp, NULL); stopService(); // Set pgagent initialized to true, as initService @@ -96,9 +94,15 @@ void LogMessage(wxString msg, int level) // Log startup/connection warnings (valid for any log level) case LOG_STARTUP: - ReportEvent(eventHandle, EVENTLOG_WARNING_TYPE, 0, 0, NULL, 1, 0, tmp, NULL); + ReportEventW(eventHandle, EVENTLOG_WARNING_TYPE, 0, 0, NULL, 1, 0, &tmp, NULL); break; } + + if (tmp) + { + free((void *)tmp); + tmp = NULL; + } } else { @@ -106,20 +110,20 @@ void LogMessage(wxString msg, int level) { case LOG_DEBUG: if (minLogLevel >= LOG_DEBUG) - wxPrintf(_("DEBUG: %s\n"), msg); + wprintf(L"DEBUG: %s\n", msg.c_str()); break; case LOG_WARNING: if (minLogLevel >= LOG_WARNING) - wxPrintf(_("WARNING: %s\n"), msg); + wprintf(L"WARNING: %s\n", msg.c_str()); break; case LOG_ERROR: - wxPrintf(_("ERROR: %s\n"), msg); + wprintf(L"ERROR: %s\n", msg.c_str()); pgagentInitialized = true; exit(1); break; // Log startup/connection warnings (valid for any log level) case LOG_STARTUP: - wxPrintf(_("WARNING: %s\n"), msg); + wprintf(L"WARNING: %s\n", msg.c_str()); break; } } @@ -140,15 +144,15 @@ unsigned int __stdcall threadProcedure(void *unused) // _popen doesn't work in Win2K from a service so we have to // do it the fun way :-) -HANDLE win32_popen_r(const TCHAR *command, HANDLE &handle) +HANDLE win32_popen_r(const WCHAR *command, HANDLE &handle) { HANDLE hWrite, hRead; SECURITY_ATTRIBUTES saAttr; BOOL ret = FALSE; PROCESS_INFORMATION piProcInfo; - STARTUPINFO siStartInfo; - TCHAR *cmd; + STARTUPINFOW siStartInfo; + WCHAR *cmd; cmd = _wcsdup(command); @@ -172,16 +176,16 @@ HANDLE win32_popen_r(const TCHAR *command, HANDLE &handle) siStartInfo.hStdOutput = hWrite; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - ret = CreateProcess(NULL, - cmd, // command line - NULL, // process security attributes - NULL, // primary thread security attributes - TRUE, // handles are inherited - 0, // creation flags - NULL, // use parent's environment - NULL, // use parent's current directory - &siStartInfo, // STARTUPINFO pointer - &piProcInfo); // receives PROCESS_INFORMATION + ret = CreateProcessW(NULL, + cmd, // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + 0, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo); // receives PROCESS_INFORMATION if (!ret) return NULL; @@ -222,7 +226,7 @@ bool continueService() bool stopService() { pauseService(); - CloseHandle (threadHandle); + CloseHandle(threadHandle); threadHandle = 0; return true; } @@ -239,9 +243,9 @@ bool initService() { if (eventHandle) { - serviceStatus.dwWaitHint += 1000 ; + serviceStatus.dwWaitHint += 1000; serviceStatus.dwCheckPoint++; - SetServiceStatus(serviceStatusHandle, (LPSERVICE_STATUS) &serviceStatus); + SetServiceStatus(serviceStatusHandle, (LPSERVICE_STATUS)&serviceStatus); } Sleep(1000); } @@ -293,14 +297,14 @@ void CALLBACK serviceHandler(DWORD ctl) void CALLBACK serviceMain(DWORD argc, LPTSTR *argv) { - serviceName.Printf(wxT("%s"), (const char *)argv[0]); + serviceName = CharToWString((const char *)argv[0]); serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = SERVICE_START_PENDING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 15000; - serviceStatusHandle = RegisterServiceCtrlHandler(serviceName.c_str(), serviceHandler); + serviceStatusHandle = RegisterServiceCtrlHandlerW(serviceName.c_str(), serviceHandler); if (serviceStatusHandle) { SetServiceStatus(serviceStatusHandle, &serviceStatus); @@ -323,25 +327,24 @@ void CALLBACK serviceMain(DWORD argc, LPTSTR *argv) //////////////////////////////////////////////////////////// // installation and removal -bool installService(const wxString &serviceName, const wxString &executable, const wxString &args, const wxString &displayname, const wxString &user, const wxString &password) +bool installService(const std::wstring &serviceName, const std::wstring &executable, const std::wstring &args, const std::wstring &displayname, const std::wstring &user, const std::wstring &password) { - DWORD dwData; bool done = false; SC_HANDLE manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (manager) { - wxString cmd = executable + wxT(" ") + args; + std::wstring cmd = executable + L" " + args; - wxString quser; - if (!user.Contains(wxT("\\"))) - quser = wxT(".\\") + user; + std::wstring quser; + if (user.find(L"\\") == std::string::npos) + quser = L".\\" + user; else quser = user; - SC_HANDLE service = CreateService(manager, serviceName.c_str(), displayname.c_str(), SERVICE_ALL_ACCESS, - SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, - cmd.c_str(), 0, 0, 0, quser.c_str(), password.c_str()); + SC_HANDLE service = CreateServiceW(manager, serviceName.c_str(), displayname.c_str(), SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, + cmd.c_str(), 0, 0, 0, quser.c_str(), password.c_str()); if (service) { @@ -354,59 +357,89 @@ bool installService(const wxString &serviceName, const wxString &executable, co DWORD dw = GetLastError(); FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL - ); - wxString error; - error.Printf(wxT("%s"), lpMsgBuf); - LogMessage(error, LOG_ERROR); + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL + ); + LogMessage((boost::wformat(L"%s") % lpMsgBuf).str(), LOG_ERROR); } CloseServiceHandle(manager); } // Setup the event message DLL - wxRegKey *msgKey = new wxRegKey(wxT("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") + serviceName); - if(!msgKey->Exists()) + const std::wstring key_path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" + serviceName); + HKEY key; + DWORD last_error = RegCreateKeyExW(HKEY_LOCAL_MACHINE, + key_path.c_str(), + 0, + 0, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + 0, + &key, + 0); + + if (ERROR_SUCCESS == last_error) { - if (!msgKey->Create()) - LogMessage(_("Could not open the message source registry key."), LOG_WARNING); - } + std::size_t found = executable.find_last_of(L"/\\"); + std::wstring path = executable.substr(0, found) + L"\\pgaevent.dll"; - wxString path = executable.BeforeLast('\\') + wxT("\\pgaevent.dll"); + DWORD last_error; + const DWORD types_supported = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; - if (!msgKey->SetValue(wxT("EventMessageFile"), path)) - LogMessage(_("Could not set the event message file registry value."), LOG_WARNING); + last_error = RegSetValueExW(key, + L"EventMessageFile", + 0, + REG_SZ, + (unsigned char *)(path.c_str()), + (path.length() + 1)*sizeof(std::wstring)); - dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + if (ERROR_SUCCESS == last_error) + { + last_error = RegSetValueExW(key, + L"TypesSupported", + 0, + REG_DWORD, + (LPBYTE)&types_supported, + sizeof(types_supported)); + } - if (!msgKey->SetValue(wxT("TypesSupported"), dwData)) - LogMessage(_("Could not set the supported types."), LOG_WARNING);; + if (ERROR_SUCCESS != last_error) + { + LogMessage(L"Could not set the event message file registry value.", LOG_WARNING); + } + + RegCloseKey(key); + } + else + { + LogMessage(L"Could not open the message source registry key.", LOG_WARNING); + } return done; } -bool removeService(const wxString &serviceName) +bool removeService(const std::wstring &serviceName) { bool done = false; SC_HANDLE manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (manager) { - SC_HANDLE service = OpenService(manager, serviceName.c_str(), SERVICE_ALL_ACCESS); + SC_HANDLE service = OpenServiceW(manager, serviceName.c_str(), SERVICE_ALL_ACCESS); if (service) { SERVICE_STATUS serviceStatus; ControlService(service, SERVICE_CONTROL_STOP, &serviceStatus); int retries; - for (retries = 0 ; retries < 5 ; retries++) + for (retries = 0; retries < 5; retries++) { if (QueryServiceStatus(service, &serviceStatus)) { @@ -425,44 +458,45 @@ bool removeService(const wxString &serviceName) } // Remove the event message DLL - wxRegKey *msgKey = new wxRegKey(wxT("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\") + serviceName); - msgKey->DeleteSelf(); + const std::wstring key_path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" + serviceName); + DWORD last_error = RegDeleteKeyW(HKEY_LOCAL_MACHINE, key_path.c_str()); + if (ERROR_SUCCESS != last_error) + { + LogMessage(L"Failed to uninstall source", LOG_ERROR); + } return done; } - - -void usage(const wxString &executable) +void usage(const std::wstring &executable) { - wxFileName *fn = new wxFileName(executable); printVersion(); - wxPrintf(_("Usage:\n")); - wxPrintf(fn->GetName() + _(" REMOVE \n")); - wxPrintf(fn->GetName() + _(" INSTALL [options] \n")); - wxPrintf(fn->GetName() + _(" DEBUG [options] \n")); - wxPrintf(_("options:\n")); - wxPrintf(_("-v (display version info and then exit)\n")); - wxPrintf(_("-u \n")); - wxPrintf(_("-p \n")); - wxPrintf(_("-d \n")); - wxPrintf(_("-t \n")); - wxPrintf(_("-r =10, default 30)>\n")); - wxPrintf(_("-l \n")); + wprintf(L"Usage:\n"); + wprintf(L"%s REMOVE \n", executable.c_str()); + wprintf(L"%s INSTALL [options] \n", executable.c_str()); + wprintf(L"%s DEBUG [options] \n", executable.c_str()); + wprintf(L"options:\n"); + wprintf(L"-v (display version info and then exit)\n"); + wprintf(L"-u \n"); + wprintf(L"-p \n"); + wprintf(L"-d \n"); + wprintf(L"-t \n"); + wprintf(L"-r =10, default 30)>\n"); + wprintf(L"-l \n"); } //////////////////////////////////////////////////////////// -void setupForRun(int argc, char **argv, bool debug, const wxString &executable) +void setupForRun(int argc, char **argv, bool debug, const std::wstring &executable) { if (!debug) { - eventHandle = RegisterEventSource(0, serviceName.c_str()); + eventHandle = RegisterEventSourceW(0, serviceName.c_str()); if (!eventHandle) - LogMessage(_("Couldn't register event handle."), LOG_ERROR); + LogMessage(L"Couldn't register event handle.", LOG_ERROR); } setOptions(argc, argv, executable); @@ -471,12 +505,8 @@ void setupForRun(int argc, char **argv, bool debug, const wxString &executable) void main(int argc, char **argv) { - // Statup wx - wxInitialize(); - - wxFileName file = wxString::FromAscii(*argv++); - file.MakeAbsolute(); - wxString executable = file.GetFullPath(); + std::wstring executable; + executable.assign(CharToWString(*argv++)); if (argc < 3) { @@ -484,21 +514,21 @@ void main(int argc, char **argv) return; } - wxString command; - command = wxString::FromAscii(*argv++); + std::wstring command; + command.assign(CharToWString(*argv++)); - if (command != wxT("DEBUG")) + if (command != L"DEBUG") { - serviceName = wxString::FromAscii(*argv++); + serviceName.assign(CharToWString(*argv++)); argc -= 3; } else argc -= 2; - if (command == wxT("INSTALL")) + if (command == L"INSTALL") { - wxString displayname = _("PostgreSQL Scheduling Agent - ") + serviceName; - wxString args = wxT("RUN ") + serviceName; + std::wstring displayname = L"PostgreSQL Scheduling Agent - " + serviceName; + std::wstring args = L"RUN " + serviceName; while (argc-- > 0) { @@ -523,14 +553,14 @@ void main(int argc, char **argv) } default: { - args += wxT(" ") + wxString::FromAscii(*argv); + args += L" " + CharToWString(*argv); break; } } } else { - args += wxT(" ") + wxString::FromAscii(*argv); + args += L" " + CharToWString(*argv); } argv++; @@ -538,11 +568,11 @@ void main(int argc, char **argv) bool rc = installService(serviceName, executable, args, displayname, user, password); } - else if (command == wxT("REMOVE")) + else if (command == L"REMOVE") { bool rc = removeService(serviceName); } - else if (command == wxT("DEBUG")) + else if (command == L"DEBUG") { setupForRun(argc, argv, true, executable); @@ -553,15 +583,14 @@ void main(int argc, char **argv) WaitForSingleObject(threadHandle, INFINITE); } - else if (command == wxT("RUN")) + else if (command == L"RUN") { - wxString app = _("pgAgent Service"); + std::string app = "pgAgent Service"; SERVICE_TABLE_ENTRY serviceTable[] = - { (LPWSTR)app.wc_str(), serviceMain, 0, 0}; + { (LPSTR)app.c_str(), serviceMain, 0, 0 }; setupForRun(argc, argv, false, executable); - if (!StartServiceCtrlDispatcher(serviceTable)) { DWORD rc = GetLastError();